Commit 70e2a30a by Ilya Leoshkevich Committed by Ilya Leoshkevich

Allow COND_EXPR and VEC_COND_EXPR condtions to trap

Right now gimplifier does not allow VEC_COND_EXPR's condition to trap
and introduces a temporary if this could happen, for example, generating

  _5 = _4 > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 };
  _6 = VEC_COND_EXPR <_5, { -1, -1, -1, -1 }, { 0, 0, 0, 0 }>;

from GENERIC

  VEC_COND_EXPR < (*b > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 }) ,
                  { -1, -1, -1, -1 } ,
		  { 0, 0, 0, 0 } >

This is not necessary and makes the resulting GIMPLE harder to analyze.
Change the gimplifier so as to allow COND_EXPR and VEC_COND_EXPR
conditions to trap.

This patch takes special care to avoid introducing trapping comparisons
in GIMPLE_COND.  They are not allowed, because they would require 3
outgoing edges (then, else and EH), which is awkward to say the least.
Therefore, computations of such conditions should live in their own basic
blocks.

gcc/ChangeLog:

2019-10-07  Ilya Leoshkevich  <iii@linux.ibm.com>

	PR target/77918
	* gimple-expr.c (gimple_cond_get_ops_from_tree): Assert that the
	caller passes a non-trapping condition.
	(is_gimple_condexpr): Allow trapping conditions.
	(is_gimple_condexpr_1): New helper function.
	(is_gimple_condexpr_for_cond): New function, acts like old
	is_gimple_condexpr.
	* gimple-expr.h (is_gimple_condexpr_for_cond): New function.
	* gimple.c (gimple_could_trap_p_1): Handle COND_EXPR and
	VEC_COND_EXPR. Fix an issue with statements like i = (fp < 1.).
	* gimplify.c (gimplify_cond_expr): Use
	is_gimple_condexpr_for_cond.
	(gimplify_expr): Allow is_gimple_condexpr_for_cond.
	* tree-eh.c (operation_could_trap_p): Assert on COND_EXPR and
	VEC_COND_EXPR.
	(tree_could_trap_p): Handle COND_EXPR and VEC_COND_EXPR.
	* tree-ssa-forwprop.c (forward_propagate_into_gimple_cond): Use
	is_gimple_condexpr_for_cond, remove pointless tmp check
	(forward_propagate_into_cond): Remove pointless tmp check.

From-SVN: r276659
parent 880dcdae
2019-10-07 Ilya Leoshkevich <iii@linux.ibm.com>
PR target/77918
* gimple-expr.c (gimple_cond_get_ops_from_tree): Assert that the
caller passes a non-trapping condition.
(is_gimple_condexpr): Allow trapping conditions.
(is_gimple_condexpr_1): New helper function.
(is_gimple_condexpr_for_cond): New function, acts like old
is_gimple_condexpr.
* gimple-expr.h (is_gimple_condexpr_for_cond): New function.
* gimple.c (gimple_could_trap_p_1): Handle COND_EXPR and
VEC_COND_EXPR. Fix an issue with statements like i = (fp < 1.).
* gimplify.c (gimplify_cond_expr): Use
is_gimple_condexpr_for_cond.
(gimplify_expr): Allow is_gimple_condexpr_for_cond.
* tree-eh.c (operation_could_trap_p): Assert on COND_EXPR and
VEC_COND_EXPR.
(tree_could_trap_p): Handle COND_EXPR and VEC_COND_EXPR.
* tree-ssa-forwprop.c (forward_propagate_into_gimple_cond): Use
is_gimple_condexpr_for_cond, remove pointless tmp check
(forward_propagate_into_cond): Remove pointless tmp check.
2019-10-07 Vladislav Ivanishin <vlad@ispras.ru> 2019-10-07 Vladislav Ivanishin <vlad@ispras.ru>
* gimple-iterator.h (gsi_next_nonvirtual_phi): Change the semantics to * gimple-iterator.h (gsi_next_nonvirtual_phi): Change the semantics to
......
...@@ -574,6 +574,7 @@ gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p, ...@@ -574,6 +574,7 @@ gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p,
|| TREE_CODE (cond) == TRUTH_NOT_EXPR || TREE_CODE (cond) == TRUTH_NOT_EXPR
|| is_gimple_min_invariant (cond) || is_gimple_min_invariant (cond)
|| SSA_VAR_P (cond)); || SSA_VAR_P (cond));
gcc_checking_assert (!tree_could_throw_p (cond));
extract_ops_from_tree (cond, code_p, lhs_p, rhs_p); extract_ops_from_tree (cond, code_p, lhs_p, rhs_p);
...@@ -605,17 +606,33 @@ is_gimple_lvalue (tree t) ...@@ -605,17 +606,33 @@ is_gimple_lvalue (tree t)
|| TREE_CODE (t) == BIT_FIELD_REF); || TREE_CODE (t) == BIT_FIELD_REF);
} }
/* Return true if T is a GIMPLE condition. */ /* Helper for is_gimple_condexpr and is_gimple_condexpr_for_cond. */
bool static bool
is_gimple_condexpr (tree t) is_gimple_condexpr_1 (tree t, bool allow_traps)
{ {
return (is_gimple_val (t) || (COMPARISON_CLASS_P (t) return (is_gimple_val (t) || (COMPARISON_CLASS_P (t)
&& !tree_could_throw_p (t) && (allow_traps || !tree_could_throw_p (t))
&& is_gimple_val (TREE_OPERAND (t, 0)) && is_gimple_val (TREE_OPERAND (t, 0))
&& is_gimple_val (TREE_OPERAND (t, 1)))); && is_gimple_val (TREE_OPERAND (t, 1))));
} }
/* Return true if T is a GIMPLE condition. */
bool
is_gimple_condexpr (tree t)
{
return is_gimple_condexpr_1 (t, true);
}
/* Like is_gimple_condexpr, but does not allow T to trap. */
bool
is_gimple_condexpr_for_cond (tree t)
{
return is_gimple_condexpr_1 (t, false);
}
/* Return true if T is a gimple address. */ /* Return true if T is a gimple address. */
bool bool
......
...@@ -41,6 +41,7 @@ extern void gimple_cond_get_ops_from_tree (tree, enum tree_code *, tree *, ...@@ -41,6 +41,7 @@ extern void gimple_cond_get_ops_from_tree (tree, enum tree_code *, tree *,
tree *); tree *);
extern bool is_gimple_lvalue (tree); extern bool is_gimple_lvalue (tree);
extern bool is_gimple_condexpr (tree); extern bool is_gimple_condexpr (tree);
extern bool is_gimple_condexpr_for_cond (tree);
extern bool is_gimple_address (const_tree); extern bool is_gimple_address (const_tree);
extern bool is_gimple_invariant_address (const_tree); extern bool is_gimple_invariant_address (const_tree);
extern bool is_gimple_ip_invariant_address (const_tree); extern bool is_gimple_ip_invariant_address (const_tree);
......
...@@ -2149,10 +2149,22 @@ gimple_could_trap_p_1 (gimple *s, bool include_mem, bool include_stores) ...@@ -2149,10 +2149,22 @@ gimple_could_trap_p_1 (gimple *s, bool include_mem, bool include_stores)
return false; return false;
case GIMPLE_ASSIGN: case GIMPLE_ASSIGN:
t = gimple_expr_type (s);
op = gimple_assign_rhs_code (s); op = gimple_assign_rhs_code (s);
/* For COND_EXPR and VEC_COND_EXPR only the condition may trap. */
if (op == COND_EXPR || op == VEC_COND_EXPR)
return tree_could_trap_p (gimple_assign_rhs1 (s));
/* For comparisons we need to check rhs operand types instead of rhs type
(which is BOOLEAN_TYPE). */
if (TREE_CODE_CLASS (op) == tcc_comparison)
t = TREE_TYPE (gimple_assign_rhs1 (s));
else
t = gimple_expr_type (s);
if (get_gimple_rhs_class (op) == GIMPLE_BINARY_RHS) if (get_gimple_rhs_class (op) == GIMPLE_BINARY_RHS)
div = gimple_assign_rhs2 (s); div = gimple_assign_rhs2 (s);
return (operation_could_trap_p (op, FLOAT_TYPE_P (t), return (operation_could_trap_p (op, FLOAT_TYPE_P (t),
(INTEGRAL_TYPE_P (t) (INTEGRAL_TYPE_P (t)
&& TYPE_OVERFLOW_TRAPS (t)), && TYPE_OVERFLOW_TRAPS (t)),
......
...@@ -4142,8 +4142,8 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback) ...@@ -4142,8 +4142,8 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
/* Now do the normal gimplification. */ /* Now do the normal gimplification. */
/* Gimplify condition. */ /* Gimplify condition. */
ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL, is_gimple_condexpr, ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL,
fb_rvalue); is_gimple_condexpr_for_cond, fb_rvalue);
if (ret == GS_ERROR) if (ret == GS_ERROR)
return GS_ERROR; return GS_ERROR;
gcc_assert (TREE_OPERAND (expr, 0) != NULL_TREE); gcc_assert (TREE_OPERAND (expr, 0) != NULL_TREE);
...@@ -12976,6 +12976,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ...@@ -12976,6 +12976,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
else if (gimple_test_f == is_gimple_val else if (gimple_test_f == is_gimple_val
|| gimple_test_f == is_gimple_call_addr || gimple_test_f == is_gimple_call_addr
|| gimple_test_f == is_gimple_condexpr || gimple_test_f == is_gimple_condexpr
|| gimple_test_f == is_gimple_condexpr_for_cond
|| gimple_test_f == is_gimple_mem_rhs || gimple_test_f == is_gimple_mem_rhs
|| gimple_test_f == is_gimple_mem_rhs_or_call || gimple_test_f == is_gimple_mem_rhs_or_call
|| gimple_test_f == is_gimple_reg_rhs || gimple_test_f == is_gimple_reg_rhs
......
...@@ -2523,6 +2523,10 @@ operation_could_trap_p (enum tree_code op, bool fp_operation, bool honor_trapv, ...@@ -2523,6 +2523,10 @@ operation_could_trap_p (enum tree_code op, bool fp_operation, bool honor_trapv,
bool honor_snans = fp_operation && flag_signaling_nans != 0; bool honor_snans = fp_operation && flag_signaling_nans != 0;
bool handled; bool handled;
/* This function cannot tell whether or not COND_EXPR and VEC_COND_EXPR could
trap, because that depends on the respective condition op. */
gcc_assert (op != COND_EXPR && op != VEC_COND_EXPR);
if (TREE_CODE_CLASS (op) != tcc_comparison if (TREE_CODE_CLASS (op) != tcc_comparison
&& TREE_CODE_CLASS (op) != tcc_unary && TREE_CODE_CLASS (op) != tcc_unary
&& TREE_CODE_CLASS (op) != tcc_binary) && TREE_CODE_CLASS (op) != tcc_binary)
...@@ -2610,6 +2614,10 @@ tree_could_trap_p (tree expr) ...@@ -2610,6 +2614,10 @@ tree_could_trap_p (tree expr)
if (!expr) if (!expr)
return false; return false;
/* For COND_EXPR and VEC_COND_EXPR only the condition may trap. */
if (TREE_CODE (expr) == COND_EXPR || TREE_CODE (expr) == VEC_COND_EXPR)
expr = TREE_OPERAND (expr, 0);
code = TREE_CODE (expr); code = TREE_CODE (expr);
t = TREE_TYPE (expr); t = TREE_TYPE (expr);
......
...@@ -527,9 +527,10 @@ forward_propagate_into_gimple_cond (gcond *stmt) ...@@ -527,9 +527,10 @@ forward_propagate_into_gimple_cond (gcond *stmt)
tmp = forward_propagate_into_comparison_1 (stmt, code, tmp = forward_propagate_into_comparison_1 (stmt, code,
boolean_type_node, boolean_type_node,
rhs1, rhs2); rhs1, rhs2);
if (tmp) if (tmp
&& is_gimple_condexpr_for_cond (tmp))
{ {
if (dump_file && tmp) if (dump_file)
{ {
fprintf (dump_file, " Replaced '"); fprintf (dump_file, " Replaced '");
print_gimple_expr (dump_file, stmt, 0); print_gimple_expr (dump_file, stmt, 0);
...@@ -607,7 +608,7 @@ forward_propagate_into_cond (gimple_stmt_iterator *gsi_p) ...@@ -607,7 +608,7 @@ forward_propagate_into_cond (gimple_stmt_iterator *gsi_p)
if (tmp if (tmp
&& is_gimple_condexpr (tmp)) && is_gimple_condexpr (tmp))
{ {
if (dump_file && tmp) if (dump_file)
{ {
fprintf (dump_file, " Replaced '"); fprintf (dump_file, " Replaced '");
print_generic_expr (dump_file, cond); print_generic_expr (dump_file, cond);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment