This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap
- From: Ilya Leoshkevich <iii at linux dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: richard dot guenther at gmail dot com, richard dot sandiford at arm dot com, segher at kernel dot crashing dot org, joseph at codesourcery dot com, krebbel at linux dot ibm dot com, rdapp at linux dot ibm dot com, Ilya Leoshkevich <iii at linux dot ibm dot com>
- Date: Thu, 5 Sep 2019 13:10:11 +0200
- Subject: [PATCH v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap
- References: <20190905111019.8951-1-iii@linux.ibm.com>
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.
In particular, one of the next patches in series needs to get to
VEC_COND_EXPR's comparison code, which is not possible when a temporary
is introduced.
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-09-03 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_ternary_operands_ok_p): New function to remove code
duplication i verify_gimple_assign_ternary and
valid_gimple_rhs_p.
* gimple.c (gimple_could_trap_p_1): Handle COND_EXPR and
VEC_COND_EXPR.
* gimplify.c (gimplify_cond_expr): Use
is_gimple_condexpr_for_cond.
(gimplify_expr): Allow is_gimple_condexpr_for_cond.
* tree-cfg.c (verify_gimple_assign_ternary): Use
gimple_ternary_operands_ok_p.
* 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.
* tree-ssa-propagate.c (valid_gimple_rhs_p): Use
gimple_ternary_operands_ok_p.
---
gcc/gimple-expr.c | 25 +++++++++++++++++++++----
gcc/gimple-expr.h | 11 +++++++++++
gcc/gimple.c | 2 ++
gcc/gimplify.c | 5 +++--
gcc/tree-cfg.c | 5 +----
gcc/tree-eh.c | 8 ++++++++
gcc/tree-ssa-forwprop.c | 7 ++++---
gcc/tree-ssa-propagate.c | 9 ++++-----
8 files changed, 54 insertions(+), 18 deletions(-)
diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
index b0c9f9b671a..46e5f000580 100644
--- a/gcc/gimple-expr.c
+++ b/gcc/gimple-expr.c
@@ -571,6 +571,7 @@ gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p,
|| TREE_CODE (cond) == TRUTH_NOT_EXPR
|| is_gimple_min_invariant (cond)
|| SSA_VAR_P (cond));
+ gcc_assert (!tree_could_throw_p (cond));
extract_ops_from_tree (cond, code_p, lhs_p, rhs_p);
@@ -602,17 +603,33 @@ is_gimple_lvalue (tree t)
|| 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
-is_gimple_condexpr (tree t)
+static bool
+is_gimple_condexpr_1 (tree t, bool allow_traps)
{
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, 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. */
bool
diff --git a/gcc/gimple-expr.h b/gcc/gimple-expr.h
index 1ad1432bd17..27190b1e5fe 100644
--- a/gcc/gimple-expr.h
+++ b/gcc/gimple-expr.h
@@ -41,6 +41,7 @@ extern void gimple_cond_get_ops_from_tree (tree, enum tree_code *, tree *,
tree *);
extern bool is_gimple_lvalue (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_invariant_address (const_tree);
extern bool is_gimple_ip_invariant_address (const_tree);
@@ -175,4 +176,14 @@ gimple_call_addr_fndecl (const_tree fn)
return NULL_TREE;
}
+static inline bool
+gimple_ternary_operands_ok_p (enum tree_code code, tree op1, tree op2, tree op3)
+{
+ return ((code == VEC_COND_EXPR || code == COND_EXPR)
+ ? is_gimple_condexpr (op1)
+ : is_gimple_val (op1))
+ && is_gimple_val (op2)
+ && is_gimple_val (op3);
+}
+
#endif /* GCC_GIMPLE_EXPR_H */
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 633ef512a19..fd14fbec15e 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -2144,6 +2144,8 @@ gimple_could_trap_p_1 (gimple *s, bool include_mem, bool include_stores)
op = gimple_assign_rhs_code (s);
if (get_gimple_rhs_class (op) == GIMPLE_BINARY_RHS)
div = gimple_assign_rhs2 (s);
+ else if (op == COND_EXPR || op == VEC_COND_EXPR)
+ op = TREE_CODE (gimple_assign_rhs1 (s));
return (operation_could_trap_p (op, FLOAT_TYPE_P (t),
(INTEGRAL_TYPE_P (t)
&& TYPE_OVERFLOW_TRAPS (t)),
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index daa0b71c191..920e423381c 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -4141,8 +4141,8 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
/* Now do the normal gimplification. */
/* Gimplify condition. */
- ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL, is_gimple_condexpr,
- fb_rvalue);
+ ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL,
+ is_gimple_condexpr_for_cond, fb_rvalue);
if (ret == GS_ERROR)
return GS_ERROR;
gcc_assert (TREE_OPERAND (expr, 0) != NULL_TREE);
@@ -12973,6 +12973,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
else if (gimple_test_f == is_gimple_val
|| gimple_test_f == is_gimple_call_addr
|| 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_or_call
|| gimple_test_f == is_gimple_reg_rhs
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index b75fdb2e63f..4d2239e9d2f 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -4121,10 +4121,7 @@ verify_gimple_assign_ternary (gassign *stmt)
return true;
}
- if (((rhs_code == VEC_COND_EXPR || rhs_code == COND_EXPR)
- ? !is_gimple_condexpr (rhs1) : !is_gimple_val (rhs1))
- || !is_gimple_val (rhs2)
- || !is_gimple_val (rhs3))
+ if (!gimple_ternary_operands_ok_p (rhs_code, rhs1, rhs2, rhs3))
{
error ("invalid operands in ternary operation");
return true;
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 5bb07e49d28..98dc95a07cd 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -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 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
&& TREE_CODE_CLASS (op) != tcc_unary
&& TREE_CODE_CLASS (op) != tcc_binary)
@@ -2610,6 +2614,10 @@ tree_could_trap_p (tree expr)
if (!expr)
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);
t = TREE_TYPE (expr);
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index c464c899586..edc5417f455 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -524,9 +524,10 @@ forward_propagate_into_gimple_cond (gcond *stmt)
tmp = forward_propagate_into_comparison_1 (stmt, code,
boolean_type_node,
rhs1, rhs2);
- if (tmp)
+ if (tmp
+ && is_gimple_condexpr_for_cond (tmp))
{
- if (dump_file && tmp)
+ if (dump_file)
{
fprintf (dump_file, " Replaced '");
print_gimple_expr (dump_file, stmt, 0);
@@ -604,7 +605,7 @@ forward_propagate_into_cond (gimple_stmt_iterator *gsi_p)
if (tmp
&& is_gimple_condexpr (tmp))
{
- if (dump_file && tmp)
+ if (dump_file)
{
fprintf (dump_file, " Replaced '");
print_generic_expr (dump_file, cond);
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index 7172ef8b4e6..be34e25fc40 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -523,11 +523,10 @@ valid_gimple_rhs_p (tree expr)
default:
if (get_gimple_rhs_class (code) == GIMPLE_TERNARY_RHS)
{
- if (((code == VEC_COND_EXPR || code == COND_EXPR)
- ? !is_gimple_condexpr (TREE_OPERAND (expr, 0))
- : !is_gimple_val (TREE_OPERAND (expr, 0)))
- || !is_gimple_val (TREE_OPERAND (expr, 1))
- || !is_gimple_val (TREE_OPERAND (expr, 2)))
+ if (!gimple_ternary_operands_ok_p (code,
+ TREE_OPERAND (expr, 0),
+ TREE_OPERAND (expr, 1),
+ TREE_OPERAND (expr, 2)))
return false;
break;
}
--
2.21.0