Backport PRs 82244, 82264, 82276, 82285, 82291

2017-09-26  Richard Biener  <rguenther@suse.de>

	Backport from mainline
	2017-09-19  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/82244
	* tree-vrp.c (remove_range_assertions): Do not propagate
	a constant to abnormals but replace the assert with a copy.

	* gcc.dg/torture/pr82244.c: New testcase.

	2017-09-21  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/82276
	PR tree-optimization/82244
	* tree-vrp.c (build_assert_expr_for): Set
	SSA_NAME_OCCURS_IN_ABNORMAL_PHI if the variable we assert on
	has it set.
	(remove_range_assertions): Revert earlier change.

	* gcc.dg/torture/pr82276.c: New testcase.

	2017-09-20  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/82264
	* tree-ssa-sccvn.c (vn_phi_eq): Use safe_dyn_cast to check
	for GIMPLE_CONDs.
	(vn_phi_lookup): Likewise.
	(vn_phi_insert): Likewise.
	* is-a.h (safe_dyn_cast): New.

	* gcc.dg/torture/pr82264.c: New testcase.

	2017-09-25  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/82285
	* tree-vect-patterns.c (vect_recog_bool_pattern): Also handle
	enumeral types.

	* gcc.dg/torture/pr82285.c: New testcase.

	2017-09-22  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/82291
	* tree-if-conv.c (predicate_mem_writes): Make sure to
	remove writes in blocks predicated with false.

	* gcc.dg/torture/pr82291.c: New testcase.

From-SVN: r253190
This commit is contained in:
Richard Biener 2017-09-26 10:16:40 +00:00 committed by Richard Biener
parent bff800cf76
commit 87c7cf4766
12 changed files with 329 additions and 98 deletions

View File

@ -1,3 +1,42 @@
2017-09-26 Richard Biener <rguenther@suse.de>
Backport from mainline
2017-09-19 Richard Biener <rguenther@suse.de>
PR tree-optimization/82244
* tree-vrp.c (remove_range_assertions): Do not propagate
a constant to abnormals but replace the assert with a copy.
2017-09-21 Richard Biener <rguenther@suse.de>
PR tree-optimization/82276
PR tree-optimization/82244
* tree-vrp.c (build_assert_expr_for): Set
SSA_NAME_OCCURS_IN_ABNORMAL_PHI if the variable we assert on
has it set.
(remove_range_assertions): Revert earlier change.
2017-09-20 Richard Biener <rguenther@suse.de>
PR tree-optimization/82264
* tree-ssa-sccvn.c (vn_phi_eq): Use safe_dyn_cast to check
for GIMPLE_CONDs.
(vn_phi_lookup): Likewise.
(vn_phi_insert): Likewise.
* is-a.h (safe_dyn_cast): New.
2017-09-25 Richard Biener <rguenther@suse.de>
PR tree-optimization/82285
* tree-vect-patterns.c (vect_recog_bool_pattern): Also handle
enumeral types.
2017-09-22 Richard Biener <rguenther@suse.de>
PR tree-optimization/82291
* tree-if-conv.c (predicate_mem_writes): Make sure to
remove writes in blocks predicated with false.
2017-09-21 Alan Modra <amodra@gmail.com> 2017-09-21 Alan Modra <amodra@gmail.com>
PR target/81996 PR target/81996

View File

@ -103,6 +103,11 @@ TYPE dyn_cast <TYPE> (pointer)
Note that we have converted two sets of assertions in the calls to varpool Note that we have converted two sets of assertions in the calls to varpool
into safe and efficient use of a variable. into safe and efficient use of a variable.
TYPE safe_dyn_cast <TYPE> (pointer)
Like dyn_cast <TYPE> (pointer), except that it accepts null pointers
and returns null results for them.
If you use these functions and get a 'inline function not defined' or a If you use these functions and get a 'inline function not defined' or a
'missing symbol' error message for 'is_a_helper<....>::test', it means that 'missing symbol' error message for 'is_a_helper<....>::test', it means that
@ -222,4 +227,13 @@ dyn_cast (U *p)
return static_cast <T> (0); return static_cast <T> (0);
} }
/* Similar to dyn_cast, except that the pointer may be null. */
template <typename T, typename U>
inline T
safe_dyn_cast (U *p)
{
return p ? dyn_cast <T> (p) : 0;
}
#endif /* GCC_IS_A_H */ #endif /* GCC_IS_A_H */

View File

@ -1,3 +1,32 @@
2017-09-26 Richard Biener <rguenther@suse.de>
Backport from mainline
2017-09-19 Richard Biener <rguenther@suse.de>
PR tree-optimization/82244
* gcc.dg/torture/pr82244.c: New testcase.
2017-09-21 Richard Biener <rguenther@suse.de>
PR tree-optimization/82276
PR tree-optimization/82244
* gcc.dg/torture/pr82276.c: New testcase.
2017-09-20 Richard Biener <rguenther@suse.de>
PR tree-optimization/82264
* gcc.dg/torture/pr82264.c: New testcase.
2017-09-25 Richard Biener <rguenther@suse.de>
PR tree-optimization/82285
* gcc.dg/torture/pr82285.c: New testcase.
2017-09-22 Richard Biener <rguenther@suse.de>
PR tree-optimization/82291
* gcc.dg/torture/pr82291.c: New testcase.
2017-09-22 Jakub Jelinek <jakub@redhat.com> 2017-09-22 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/81929 PR sanitizer/81929

View File

@ -0,0 +1,31 @@
/* { dg-do compile } */
typedef struct a {
struct a *b;
} a;
extern int d(void);
extern int g(void);
extern int h(void);
extern int _setjmp(void *);
int c(void)
{
1 ? d() : 0;
a *e;
while (e) {
e = (e == (a *) c) ? 0 : e->b;
while (e) {
int f = 0;
g();
if (_setjmp(0)) {
if (f & 6) {
;
} else if (f & 2) {
h();
}
}
}
}
}

View File

@ -0,0 +1,21 @@
/* { dg-do compile } */
char a;
int c;
unsigned b ();
unsigned
setjmp ()
{
}
static void
d ()
{
if (b ())
c = 3;
}
void
e ()
{
d ();
a && ({ setjmp (); });
}

View File

@ -0,0 +1,32 @@
/* { dg-do compile } */
typedef struct a {
struct a *b;
} a;
extern int d(void);
extern int g(void);
extern int h(void);
extern int _setjmp();
extern int i(void);
void c(void) {
1 ? d() : 0;
a *e;
while (e) {
e = (e == (a *) c) ? 0 : e->b;
while (e) {
unsigned int f = 0;
g();
_setjmp(f);
if (f & 6) {
;
} else if (f & 2) {
;
} else {
h();
}
i();
}
}
}

View File

@ -0,0 +1,16 @@
/* { dg-do run } */
enum tst { first = 0, second = 1 };
int
main ()
{
enum tst data[16];
for (unsigned i = 0; i < 16; i++)
data[i] = (i < 5 ? second : first);
if (data[2] != second)
__builtin_abort ();
return 0;
}

View File

@ -0,0 +1,37 @@
/* { dg-do run } */
int a, c, d, *h;
unsigned b;
int *fn1 ()
{
int *f[3], g = 0;
for (; g < 3; g++)
f[g] = &a;
if (--b > a)
{
if (a > b)
d++;
return f[0];
}
}
void fn2 ()
{
for (; c >= 0; --c)
{
int j[] = { 0, 0, 0, 0, 0 };
int *k = fn1 ();
if (!k)
__builtin_abort ();
h = &j[4];
}
}
int main ()
{
fn2 ();
if (d != 0)
__builtin_abort ();
return 0;
}

View File

@ -2198,7 +2198,7 @@ predicate_mem_writes (loop_p loop)
gimple *stmt; gimple *stmt;
int index; int index;
if (is_true_predicate (cond) || is_false_predicate (cond)) if (is_true_predicate (cond))
continue; continue;
swap = false; swap = false;
@ -2211,96 +2211,106 @@ predicate_mem_writes (loop_p loop)
vect_sizes.truncate (0); vect_sizes.truncate (0);
vect_masks.truncate (0); vect_masks.truncate (0);
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
if (!gimple_assign_single_p (stmt = gsi_stmt (gsi))) {
continue; if (!gimple_assign_single_p (stmt = gsi_stmt (gsi)))
else if (gimple_plf (stmt, GF_PLF_2)) ;
{ else if (is_false_predicate (cond))
tree lhs = gimple_assign_lhs (stmt); {
tree rhs = gimple_assign_rhs1 (stmt); unlink_stmt_vdef (stmt);
tree ref, addr, ptr, mask; gsi_remove (&gsi, true);
gimple *new_stmt; release_defs (stmt);
gimple_seq stmts = NULL; continue;
int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (lhs))); }
ref = TREE_CODE (lhs) == SSA_NAME ? rhs : lhs; else if (gimple_plf (stmt, GF_PLF_2))
mark_addressable (ref); {
addr = force_gimple_operand_gsi (&gsi, build_fold_addr_expr (ref), tree lhs = gimple_assign_lhs (stmt);
true, NULL_TREE, true, tree rhs = gimple_assign_rhs1 (stmt);
GSI_SAME_STMT); tree ref, addr, ptr, mask;
if (!vect_sizes.is_empty () gimple *new_stmt;
&& (index = mask_exists (bitsize, vect_sizes)) != -1) gimple_seq stmts = NULL;
/* Use created mask. */ int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (lhs)));
mask = vect_masks[index]; ref = TREE_CODE (lhs) == SSA_NAME ? rhs : lhs;
else mark_addressable (ref);
{ addr = force_gimple_operand_gsi (&gsi, build_fold_addr_expr (ref),
if (COMPARISON_CLASS_P (cond)) true, NULL_TREE, true,
mask = gimple_build (&stmts, TREE_CODE (cond), GSI_SAME_STMT);
boolean_type_node, if (!vect_sizes.is_empty ()
TREE_OPERAND (cond, 0), && (index = mask_exists (bitsize, vect_sizes)) != -1)
TREE_OPERAND (cond, 1)); /* Use created mask. */
else mask = vect_masks[index];
{ else
gcc_assert (TREE_CODE (cond) == SSA_NAME); {
mask = cond; if (COMPARISON_CLASS_P (cond))
} mask = gimple_build (&stmts, TREE_CODE (cond),
boolean_type_node,
TREE_OPERAND (cond, 0),
TREE_OPERAND (cond, 1));
else
{
gcc_assert (TREE_CODE (cond) == SSA_NAME);
mask = cond;
}
if (swap) if (swap)
{ {
tree true_val tree true_val
= constant_boolean_node (true, TREE_TYPE (mask)); = constant_boolean_node (true, TREE_TYPE (mask));
mask = gimple_build (&stmts, BIT_XOR_EXPR, mask = gimple_build (&stmts, BIT_XOR_EXPR,
TREE_TYPE (mask), mask, true_val); TREE_TYPE (mask), mask, true_val);
} }
gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT); gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT);
mask = ifc_temp_var (TREE_TYPE (mask), mask, &gsi); mask = ifc_temp_var (TREE_TYPE (mask), mask, &gsi);
/* Save mask and its size for further use. */ /* Save mask and its size for further use. */
vect_sizes.safe_push (bitsize); vect_sizes.safe_push (bitsize);
vect_masks.safe_push (mask); vect_masks.safe_push (mask);
} }
ptr = build_int_cst (reference_alias_ptr_type (ref), ptr = build_int_cst (reference_alias_ptr_type (ref),
get_object_alignment (ref)); get_object_alignment (ref));
/* Copy points-to info if possible. */ /* Copy points-to info if possible. */
if (TREE_CODE (addr) == SSA_NAME && !SSA_NAME_PTR_INFO (addr)) if (TREE_CODE (addr) == SSA_NAME && !SSA_NAME_PTR_INFO (addr))
copy_ref_info (build2 (MEM_REF, TREE_TYPE (ref), addr, ptr), copy_ref_info (build2 (MEM_REF, TREE_TYPE (ref), addr, ptr),
ref); ref);
if (TREE_CODE (lhs) == SSA_NAME) if (TREE_CODE (lhs) == SSA_NAME)
{ {
new_stmt new_stmt
= gimple_build_call_internal (IFN_MASK_LOAD, 3, addr, = gimple_build_call_internal (IFN_MASK_LOAD, 3, addr,
ptr, mask); ptr, mask);
gimple_call_set_lhs (new_stmt, lhs); gimple_call_set_lhs (new_stmt, lhs);
gimple_set_vuse (new_stmt, gimple_vuse (stmt)); gimple_set_vuse (new_stmt, gimple_vuse (stmt));
} }
else else
{ {
new_stmt new_stmt
= gimple_build_call_internal (IFN_MASK_STORE, 4, addr, ptr, = gimple_build_call_internal (IFN_MASK_STORE, 4, addr, ptr,
mask, rhs); mask, rhs);
gimple_set_vuse (new_stmt, gimple_vuse (stmt)); gimple_set_vuse (new_stmt, gimple_vuse (stmt));
gimple_set_vdef (new_stmt, gimple_vdef (stmt)); gimple_set_vdef (new_stmt, gimple_vdef (stmt));
SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt; SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt;
} }
gsi_replace (&gsi, new_stmt, true); gsi_replace (&gsi, new_stmt, true);
} }
else if (gimple_vdef (stmt)) else if (gimple_vdef (stmt))
{ {
tree lhs = gimple_assign_lhs (stmt); tree lhs = gimple_assign_lhs (stmt);
tree rhs = gimple_assign_rhs1 (stmt); tree rhs = gimple_assign_rhs1 (stmt);
tree type = TREE_TYPE (lhs); tree type = TREE_TYPE (lhs);
lhs = ifc_temp_var (type, unshare_expr (lhs), &gsi); lhs = ifc_temp_var (type, unshare_expr (lhs), &gsi);
rhs = ifc_temp_var (type, unshare_expr (rhs), &gsi); rhs = ifc_temp_var (type, unshare_expr (rhs), &gsi);
if (swap) if (swap)
std::swap (lhs, rhs); std::swap (lhs, rhs);
cond = force_gimple_operand_gsi_1 (&gsi, unshare_expr (cond), cond = force_gimple_operand_gsi_1 (&gsi, unshare_expr (cond),
is_gimple_condexpr, NULL_TREE, is_gimple_condexpr, NULL_TREE,
true, GSI_SAME_STMT); true, GSI_SAME_STMT);
rhs = fold_build_cond_expr (type, unshare_expr (cond), rhs, lhs); rhs = fold_build_cond_expr (type, unshare_expr (cond), rhs, lhs);
gimple_assign_set_rhs1 (stmt, ifc_temp_var (type, rhs, &gsi)); gimple_assign_set_rhs1 (stmt, ifc_temp_var (type, rhs, &gsi));
update_stmt (stmt); update_stmt (stmt);
} }
gsi_next (&gsi);
}
} }
} }

View File

@ -2990,16 +2990,13 @@ vn_phi_eq (const_vn_phi_t const vp1, const_vn_phi_t const vp2)
return false; return false;
/* Verify the controlling stmt is the same. */ /* Verify the controlling stmt is the same. */
gimple *last1 = last_stmt (idom1); gcond *last1 = safe_dyn_cast <gcond *> (last_stmt (idom1));
gimple *last2 = last_stmt (idom2); gcond *last2 = safe_dyn_cast <gcond *> (last_stmt (idom2));
if (gimple_code (last1) != GIMPLE_COND if (! last1 || ! last2)
|| gimple_code (last2) != GIMPLE_COND)
return false; return false;
bool inverted_p; bool inverted_p;
if (! cond_stmts_equal_p (as_a <gcond *> (last1), if (! cond_stmts_equal_p (last1, vp1->cclhs, vp1->ccrhs,
vp1->cclhs, vp1->ccrhs, last2, vp2->cclhs, vp2->ccrhs,
as_a <gcond *> (last2),
vp2->cclhs, vp2->ccrhs,
&inverted_p)) &inverted_p))
return false; return false;
@ -3084,7 +3081,7 @@ vn_phi_lookup (gimple *phi)
vp1.ccrhs = NULL_TREE; vp1.ccrhs = NULL_TREE;
basic_block idom1 = get_immediate_dominator (CDI_DOMINATORS, vp1.block); basic_block idom1 = get_immediate_dominator (CDI_DOMINATORS, vp1.block);
if (EDGE_COUNT (idom1->succs) == 2) if (EDGE_COUNT (idom1->succs) == 2)
if (gcond *last1 = dyn_cast <gcond *> (last_stmt (idom1))) if (gcond *last1 = safe_dyn_cast <gcond *> (last_stmt (idom1)))
{ {
vp1.cclhs = vn_valueize (gimple_cond_lhs (last1)); vp1.cclhs = vn_valueize (gimple_cond_lhs (last1));
vp1.ccrhs = vn_valueize (gimple_cond_rhs (last1)); vp1.ccrhs = vn_valueize (gimple_cond_rhs (last1));
@ -3130,7 +3127,7 @@ vn_phi_insert (gimple *phi, tree result)
vp1->ccrhs = NULL_TREE; vp1->ccrhs = NULL_TREE;
basic_block idom1 = get_immediate_dominator (CDI_DOMINATORS, vp1->block); basic_block idom1 = get_immediate_dominator (CDI_DOMINATORS, vp1->block);
if (EDGE_COUNT (idom1->succs) == 2) if (EDGE_COUNT (idom1->succs) == 2)
if (gcond *last1 = dyn_cast <gcond *> (last_stmt (idom1))) if (gcond *last1 = safe_dyn_cast <gcond *> (last_stmt (idom1)))
{ {
vp1->cclhs = vn_valueize (gimple_cond_lhs (last1)); vp1->cclhs = vn_valueize (gimple_cond_lhs (last1));
vp1->ccrhs = vn_valueize (gimple_cond_rhs (last1)); vp1->ccrhs = vn_valueize (gimple_cond_rhs (last1));

View File

@ -3641,7 +3641,7 @@ vect_recog_bool_pattern (vec<gimple *> *stmts, tree *type_in,
rhs_code = gimple_assign_rhs_code (last_stmt); rhs_code = gimple_assign_rhs_code (last_stmt);
if (CONVERT_EXPR_CODE_P (rhs_code)) if (CONVERT_EXPR_CODE_P (rhs_code))
{ {
if (TREE_CODE (TREE_TYPE (lhs)) != INTEGER_TYPE if (! INTEGRAL_TYPE_P (TREE_TYPE (lhs))
|| TYPE_PRECISION (TREE_TYPE (lhs)) == 1) || TYPE_PRECISION (TREE_TYPE (lhs)) == 1)
return NULL; return NULL;
vectype = get_vectype_for_scalar_type (TREE_TYPE (lhs)); vectype = get_vectype_for_scalar_type (TREE_TYPE (lhs));

View File

@ -4897,7 +4897,12 @@ build_assert_expr_for (tree cond, tree v)
operand of the ASSERT_EXPR. Create it so the new name and the old one operand of the ASSERT_EXPR. Create it so the new name and the old one
are registered in the replacement table so that we can fix the SSA web are registered in the replacement table so that we can fix the SSA web
after adding all the ASSERT_EXPRs. */ after adding all the ASSERT_EXPRs. */
create_new_def_for (v, assertion, NULL); tree new_def = create_new_def_for (v, assertion, NULL);
/* Make sure we preserve abnormalness throughout an ASSERT_EXPR chain
given we have to be able to fully propagate those out to re-create
valid SSA when removing the asserts. */
if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (v))
SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_def) = 1;
return assertion; return assertion;
} }