diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e2727c28aef..a75f8e18db9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,42 @@ +2017-09-26 Richard Biener + + Backport from mainline + 2017-09-19 Richard Biener + + 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 + + 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 + + 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 + + PR tree-optimization/82285 + * tree-vect-patterns.c (vect_recog_bool_pattern): Also handle + enumeral types. + + 2017-09-22 Richard Biener + + 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 PR target/81996 diff --git a/gcc/is-a.h b/gcc/is-a.h index b4e5279514f..2adc7409acb 100644 --- a/gcc/is-a.h +++ b/gcc/is-a.h @@ -103,6 +103,11 @@ TYPE dyn_cast (pointer) Note that we have converted two sets of assertions in the calls to varpool into safe and efficient use of a variable. +TYPE safe_dyn_cast (pointer) + + Like dyn_cast (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 'missing symbol' error message for 'is_a_helper<....>::test', it means that @@ -222,4 +227,13 @@ dyn_cast (U *p) return static_cast (0); } +/* Similar to dyn_cast, except that the pointer may be null. */ + +template +inline T +safe_dyn_cast (U *p) +{ + return p ? dyn_cast (p) : 0; +} + #endif /* GCC_IS_A_H */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 44410bcee7a..d76808b77a4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,32 @@ +2017-09-26 Richard Biener + + Backport from mainline + 2017-09-19 Richard Biener + + PR tree-optimization/82244 + * gcc.dg/torture/pr82244.c: New testcase. + + 2017-09-21 Richard Biener + + PR tree-optimization/82276 + PR tree-optimization/82244 + * gcc.dg/torture/pr82276.c: New testcase. + + 2017-09-20 Richard Biener + + PR tree-optimization/82264 + * gcc.dg/torture/pr82264.c: New testcase. + + 2017-09-25 Richard Biener + + PR tree-optimization/82285 + * gcc.dg/torture/pr82285.c: New testcase. + + 2017-09-22 Richard Biener + + PR tree-optimization/82291 + * gcc.dg/torture/pr82291.c: New testcase. + 2017-09-22 Jakub Jelinek PR sanitizer/81929 diff --git a/gcc/testsuite/gcc.dg/torture/pr82244.c b/gcc/testsuite/gcc.dg/torture/pr82244.c new file mode 100644 index 00000000000..3b385f97658 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr82244.c @@ -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(); + } + } + } + } +} diff --git a/gcc/testsuite/gcc.dg/torture/pr82264.c b/gcc/testsuite/gcc.dg/torture/pr82264.c new file mode 100644 index 00000000000..2bc03674ccd --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr82264.c @@ -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 (); }); +} diff --git a/gcc/testsuite/gcc.dg/torture/pr82276.c b/gcc/testsuite/gcc.dg/torture/pr82276.c new file mode 100644 index 00000000000..2f9efc8b914 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr82276.c @@ -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(); + } + } +} diff --git a/gcc/testsuite/gcc.dg/torture/pr82285.c b/gcc/testsuite/gcc.dg/torture/pr82285.c new file mode 100644 index 00000000000..6edc75070b2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr82285.c @@ -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; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr82291.c b/gcc/testsuite/gcc.dg/torture/pr82291.c new file mode 100644 index 00000000000..daa1665af20 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr82291.c @@ -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; +} diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c index eb637952e22..1dbf0a221b6 100644 --- a/gcc/tree-if-conv.c +++ b/gcc/tree-if-conv.c @@ -2198,7 +2198,7 @@ predicate_mem_writes (loop_p loop) gimple *stmt; int index; - if (is_true_predicate (cond) || is_false_predicate (cond)) + if (is_true_predicate (cond)) continue; swap = false; @@ -2211,96 +2211,106 @@ predicate_mem_writes (loop_p loop) vect_sizes.truncate (0); vect_masks.truncate (0); - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - if (!gimple_assign_single_p (stmt = gsi_stmt (gsi))) - continue; - else if (gimple_plf (stmt, GF_PLF_2)) - { - tree lhs = gimple_assign_lhs (stmt); - tree rhs = gimple_assign_rhs1 (stmt); - tree ref, addr, ptr, mask; - gimple *new_stmt; - gimple_seq stmts = NULL; - int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (lhs))); - ref = TREE_CODE (lhs) == SSA_NAME ? rhs : lhs; - mark_addressable (ref); - addr = force_gimple_operand_gsi (&gsi, build_fold_addr_expr (ref), - true, NULL_TREE, true, - GSI_SAME_STMT); - if (!vect_sizes.is_empty () - && (index = mask_exists (bitsize, vect_sizes)) != -1) - /* Use created mask. */ - mask = vect_masks[index]; - else - { - 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; - } + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);) + { + if (!gimple_assign_single_p (stmt = gsi_stmt (gsi))) + ; + else if (is_false_predicate (cond)) + { + unlink_stmt_vdef (stmt); + gsi_remove (&gsi, true); + release_defs (stmt); + continue; + } + else if (gimple_plf (stmt, GF_PLF_2)) + { + tree lhs = gimple_assign_lhs (stmt); + tree rhs = gimple_assign_rhs1 (stmt); + tree ref, addr, ptr, mask; + gimple *new_stmt; + gimple_seq stmts = NULL; + int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (lhs))); + ref = TREE_CODE (lhs) == SSA_NAME ? rhs : lhs; + mark_addressable (ref); + addr = force_gimple_operand_gsi (&gsi, build_fold_addr_expr (ref), + true, NULL_TREE, true, + GSI_SAME_STMT); + if (!vect_sizes.is_empty () + && (index = mask_exists (bitsize, vect_sizes)) != -1) + /* Use created mask. */ + mask = vect_masks[index]; + else + { + 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) - { - tree true_val - = constant_boolean_node (true, TREE_TYPE (mask)); - mask = gimple_build (&stmts, BIT_XOR_EXPR, - TREE_TYPE (mask), mask, true_val); - } - gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT); + if (swap) + { + tree true_val + = constant_boolean_node (true, TREE_TYPE (mask)); + mask = gimple_build (&stmts, BIT_XOR_EXPR, + TREE_TYPE (mask), mask, true_val); + } + gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT); - mask = ifc_temp_var (TREE_TYPE (mask), mask, &gsi); - /* Save mask and its size for further use. */ - vect_sizes.safe_push (bitsize); - vect_masks.safe_push (mask); - } - ptr = build_int_cst (reference_alias_ptr_type (ref), - get_object_alignment (ref)); - /* Copy points-to info if possible. */ - if (TREE_CODE (addr) == SSA_NAME && !SSA_NAME_PTR_INFO (addr)) - copy_ref_info (build2 (MEM_REF, TREE_TYPE (ref), addr, ptr), - ref); - if (TREE_CODE (lhs) == SSA_NAME) - { - new_stmt - = gimple_build_call_internal (IFN_MASK_LOAD, 3, addr, - ptr, mask); - gimple_call_set_lhs (new_stmt, lhs); - gimple_set_vuse (new_stmt, gimple_vuse (stmt)); - } - else - { - new_stmt - = gimple_build_call_internal (IFN_MASK_STORE, 4, addr, ptr, + mask = ifc_temp_var (TREE_TYPE (mask), mask, &gsi); + /* Save mask and its size for further use. */ + vect_sizes.safe_push (bitsize); + vect_masks.safe_push (mask); + } + ptr = build_int_cst (reference_alias_ptr_type (ref), + get_object_alignment (ref)); + /* Copy points-to info if possible. */ + if (TREE_CODE (addr) == SSA_NAME && !SSA_NAME_PTR_INFO (addr)) + copy_ref_info (build2 (MEM_REF, TREE_TYPE (ref), addr, ptr), + ref); + if (TREE_CODE (lhs) == SSA_NAME) + { + new_stmt + = gimple_build_call_internal (IFN_MASK_LOAD, 3, addr, + ptr, mask); + gimple_call_set_lhs (new_stmt, lhs); + gimple_set_vuse (new_stmt, gimple_vuse (stmt)); + } + else + { + new_stmt + = gimple_build_call_internal (IFN_MASK_STORE, 4, addr, ptr, mask, rhs); - gimple_set_vuse (new_stmt, gimple_vuse (stmt)); - gimple_set_vdef (new_stmt, gimple_vdef (stmt)); - SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt; - } + gimple_set_vuse (new_stmt, gimple_vuse (stmt)); + gimple_set_vdef (new_stmt, gimple_vdef (stmt)); + SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt; + } - gsi_replace (&gsi, new_stmt, true); - } - else if (gimple_vdef (stmt)) - { - tree lhs = gimple_assign_lhs (stmt); - tree rhs = gimple_assign_rhs1 (stmt); - tree type = TREE_TYPE (lhs); + gsi_replace (&gsi, new_stmt, true); + } + else if (gimple_vdef (stmt)) + { + tree lhs = gimple_assign_lhs (stmt); + tree rhs = gimple_assign_rhs1 (stmt); + tree type = TREE_TYPE (lhs); - lhs = ifc_temp_var (type, unshare_expr (lhs), &gsi); - rhs = ifc_temp_var (type, unshare_expr (rhs), &gsi); - if (swap) - std::swap (lhs, rhs); - cond = force_gimple_operand_gsi_1 (&gsi, unshare_expr (cond), - is_gimple_condexpr, NULL_TREE, - true, GSI_SAME_STMT); - rhs = fold_build_cond_expr (type, unshare_expr (cond), rhs, lhs); - gimple_assign_set_rhs1 (stmt, ifc_temp_var (type, rhs, &gsi)); - update_stmt (stmt); - } + lhs = ifc_temp_var (type, unshare_expr (lhs), &gsi); + rhs = ifc_temp_var (type, unshare_expr (rhs), &gsi); + if (swap) + std::swap (lhs, rhs); + cond = force_gimple_operand_gsi_1 (&gsi, unshare_expr (cond), + is_gimple_condexpr, NULL_TREE, + true, GSI_SAME_STMT); + rhs = fold_build_cond_expr (type, unshare_expr (cond), rhs, lhs); + gimple_assign_set_rhs1 (stmt, ifc_temp_var (type, rhs, &gsi)); + update_stmt (stmt); + } + gsi_next (&gsi); + } } } diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 20f5ce2d140..b64c0fd5259 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -2990,16 +2990,13 @@ vn_phi_eq (const_vn_phi_t const vp1, const_vn_phi_t const vp2) return false; /* Verify the controlling stmt is the same. */ - gimple *last1 = last_stmt (idom1); - gimple *last2 = last_stmt (idom2); - if (gimple_code (last1) != GIMPLE_COND - || gimple_code (last2) != GIMPLE_COND) + gcond *last1 = safe_dyn_cast (last_stmt (idom1)); + gcond *last2 = safe_dyn_cast (last_stmt (idom2)); + if (! last1 || ! last2) return false; bool inverted_p; - if (! cond_stmts_equal_p (as_a (last1), - vp1->cclhs, vp1->ccrhs, - as_a (last2), - vp2->cclhs, vp2->ccrhs, + if (! cond_stmts_equal_p (last1, vp1->cclhs, vp1->ccrhs, + last2, vp2->cclhs, vp2->ccrhs, &inverted_p)) return false; @@ -3084,7 +3081,7 @@ vn_phi_lookup (gimple *phi) vp1.ccrhs = NULL_TREE; basic_block idom1 = get_immediate_dominator (CDI_DOMINATORS, vp1.block); if (EDGE_COUNT (idom1->succs) == 2) - if (gcond *last1 = dyn_cast (last_stmt (idom1))) + if (gcond *last1 = safe_dyn_cast (last_stmt (idom1))) { vp1.cclhs = vn_valueize (gimple_cond_lhs (last1)); vp1.ccrhs = vn_valueize (gimple_cond_rhs (last1)); @@ -3130,7 +3127,7 @@ vn_phi_insert (gimple *phi, tree result) vp1->ccrhs = NULL_TREE; basic_block idom1 = get_immediate_dominator (CDI_DOMINATORS, vp1->block); if (EDGE_COUNT (idom1->succs) == 2) - if (gcond *last1 = dyn_cast (last_stmt (idom1))) + if (gcond *last1 = safe_dyn_cast (last_stmt (idom1))) { vp1->cclhs = vn_valueize (gimple_cond_lhs (last1)); vp1->ccrhs = vn_valueize (gimple_cond_rhs (last1)); diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c index 39f01337608..18d5f922d22 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -3641,7 +3641,7 @@ vect_recog_bool_pattern (vec *stmts, tree *type_in, rhs_code = gimple_assign_rhs_code (last_stmt); 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) return NULL; vectype = get_vectype_for_scalar_type (TREE_TYPE (lhs)); diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 697cd88502e..9431b90cf52 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -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 are registered in the replacement table so that we can fix the SSA web 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; }