From 2402ffb6711e01619f6fff7dc6f55be650ef2e23 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 22 Sep 2017 12:00:55 +0000 Subject: [PATCH] re PR tree-optimization/82291 (wrong code at -O3 on x86_64-linux-gnu) 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. * gcc.dg/torture/pr82291.c: New testcase. From-SVN: r253093 --- gcc/ChangeLog | 6 + gcc/testsuite/ChangeLog | 5 + gcc/testsuite/gcc.dg/torture/pr82291.c | 37 +++++ gcc/tree-if-conv.c | 190 +++++++++++++------------ 4 files changed, 148 insertions(+), 90 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr82291.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index aa55e18557f..5b9217c4b0a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +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-22 Richard Biener * sese.c: Include cfganal.h. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6f25855cdb1..1c2776af002 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-09-22 Richard Biener + + PR tree-optimization/82291 + * gcc.dg/torture/pr82291.c: New testcase. + 2017-09-22 Sergey Shalnov * gcc.target/i386/avx512f-constant-set.c: New test. 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 968d93cf86b..e2fce3c114a 100644 --- a/gcc/tree-if-conv.c +++ b/gcc/tree-if-conv.c @@ -2197,7 +2197,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; @@ -2210,97 +2210,107 @@ 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; - gcall *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); - - 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, + 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; + gcall *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); + + 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_call_set_nothrow (new_stmt, true); + 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_call_set_nothrow (new_stmt, true); - 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); - } + 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); + } + gsi_next (&gsi); + } } } -- 2.30.2