From: Richard Biener Date: Fri, 22 Feb 2019 08:38:14 +0000 (+0000) Subject: re PR tree-optimization/87609 (miscompilation with restrict and loop) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=229d576cde53ac4396583da3642ca969cca413d1;p=gcc.git re PR tree-optimization/87609 (miscompilation with restrict and loop) 2019-02-22 Richard Biener PR middle-end/87609 * cfghooks.h (dependence_hash): New typedef. (struct copy_bb_data): New type. (cfg_hooks::duplicate_block): Adjust to take a copy_bb_data argument. (duplicate_block): Likewise. * cfghooks.c (duplicate_block): Pass down copy_bb_data. (copy_bbs): Create and pass down copy_bb_data. * cfgrtl.c (cfg_layout_duplicate_bb): Adjust. (rtl_duplicate_bb): Likewise. * tree-cfg.c (gimple_duplicate_bb): If the copy_bb_data arg is not NULL remap dependence info. * gcc.dg/torture/restrict-7.c: New testcase. From-SVN: r269098 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a35b0aa1a51..7397b50465a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2019-02-22 Richard Biener + + PR middle-end/87609 + * cfghooks.h (dependence_hash): New typedef. + (struct copy_bb_data): New type. + (cfg_hooks::duplicate_block): Adjust to take a copy_bb_data argument. + (duplicate_block): Likewise. + * cfghooks.c (duplicate_block): Pass down copy_bb_data. + (copy_bbs): Create and pass down copy_bb_data. + * cfgrtl.c (cfg_layout_duplicate_bb): Adjust. + (rtl_duplicate_bb): Likewise. + * tree-cfg.c (gimple_duplicate_bb): If the copy_bb_data arg is not NULL + remap dependence info. + 2019-02-22 Richard Biener PR tree-optimization/87609 diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c index 6562beae616..a1d603a207e 100644 --- a/gcc/cfghooks.c +++ b/gcc/cfghooks.c @@ -1066,7 +1066,7 @@ can_duplicate_block_p (const_basic_block bb) AFTER. */ basic_block -duplicate_block (basic_block bb, edge e, basic_block after) +duplicate_block (basic_block bb, edge e, basic_block after, copy_bb_data *id) { edge s, n; basic_block new_bb; @@ -1082,7 +1082,7 @@ duplicate_block (basic_block bb, edge e, basic_block after) gcc_checking_assert (can_duplicate_block_p (bb)); - new_bb = cfg_hooks->duplicate_block (bb); + new_bb = cfg_hooks->duplicate_block (bb, id); if (after) move_block_after (new_bb, after); @@ -1337,6 +1337,7 @@ copy_bbs (basic_block *bbs, unsigned n, basic_block *new_bbs, unsigned i, j; basic_block bb, new_bb, dom_bb; edge e; + copy_bb_data id; /* Mark the blocks to be copied. This is used by edge creation hooks to decide whether to reallocate PHI nodes capacity to avoid reallocating @@ -1349,7 +1350,7 @@ copy_bbs (basic_block *bbs, unsigned n, basic_block *new_bbs, { /* Duplicate. */ bb = bbs[i]; - new_bb = new_bbs[i] = duplicate_block (bb, NULL, after); + new_bb = new_bbs[i] = duplicate_block (bb, NULL, after, &id); after = new_bb; if (bb->loop_father) { diff --git a/gcc/cfghooks.h b/gcc/cfghooks.h index 8244f5a5ac7..e9385c99443 100644 --- a/gcc/cfghooks.h +++ b/gcc/cfghooks.h @@ -54,6 +54,19 @@ struct profile_record bool run; }; +typedef int_hash dependence_hash; + +/* Optional data for duplicate_block. */ + +struct copy_bb_data +{ + copy_bb_data() : dependence_map (NULL) {} + ~copy_bb_data () { delete dependence_map; } + + /* A map from the copied BBs dependence info cliques to + equivalents in the BBs duplicated to. */ + hash_map *dependence_map; +}; struct cfg_hooks { @@ -112,7 +125,7 @@ struct cfg_hooks bool (*can_duplicate_block_p) (const_basic_block a); /* Duplicate block A. */ - basic_block (*duplicate_block) (basic_block a); + basic_block (*duplicate_block) (basic_block a, copy_bb_data *); /* Higher level functions representable by primitive operations above if we didn't have some oddities in RTL and Tree representations. */ @@ -227,7 +240,8 @@ extern void tidy_fallthru_edges (void); extern void predict_edge (edge e, enum br_predictor predictor, int probability); extern bool predicted_by_p (const_basic_block bb, enum br_predictor predictor); extern bool can_duplicate_block_p (const_basic_block); -extern basic_block duplicate_block (basic_block, edge, basic_block); +extern basic_block duplicate_block (basic_block, edge, basic_block, + copy_bb_data * = NULL); extern bool block_ends_with_call_p (basic_block bb); extern bool empty_block_p (basic_block); extern basic_block split_block_before_cond_jump (basic_block); diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 56564c2fda7..08e534f2485 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -4250,7 +4250,7 @@ duplicate_insn_chain (rtx_insn *from, rtx_insn *to) /* Create a duplicate of the basic block BB. */ static basic_block -cfg_layout_duplicate_bb (basic_block bb) +cfg_layout_duplicate_bb (basic_block bb, copy_bb_data *) { rtx_insn *insn; basic_block new_bb; @@ -5080,9 +5080,9 @@ rtl_can_remove_branch_p (const_edge e) } static basic_block -rtl_duplicate_bb (basic_block bb) +rtl_duplicate_bb (basic_block bb, copy_bb_data *id) { - bb = cfg_layout_duplicate_bb (bb); + bb = cfg_layout_duplicate_bb (bb, id); bb->aux = NULL; return bb; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 78d9d2c82e4..7cb6b240d0c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-02-22 Richard Biener + + PR middle-end/87609 + * gcc.dg/torture/restrict-7.c: New testcase. + 2019-02-21 Jakub Jelinek PR c++/89285 diff --git a/gcc/testsuite/gcc.dg/torture/restrict-7.c b/gcc/testsuite/gcc.dg/torture/restrict-7.c new file mode 100644 index 00000000000..107371098b3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/restrict-7.c @@ -0,0 +1,27 @@ +/* { dg-do run } */ + +extern void abort (void); + +static inline __attribute__((always_inline)) void +copy(int *restrict a, int *restrict b) +{ + *b = *a; + *a = 7; +} + +void __attribute__((noinline)) +floppy(int mat[static 2], unsigned idxs[static 3]) +{ + for (int i = 0; i < 3; i++) + copy(&mat[i%2], &mat[idxs[i]]); +} + +int main() +{ + int mat[2] = {10, 20}; + unsigned idxs[3] = {1, 0, 1}; + floppy(mat, idxs); + if (mat[0] != 7 || mat[1] != 10) + abort (); + return 0; +} diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index f196428a4c4..eac70274c17 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -6164,7 +6164,7 @@ gimple_can_duplicate_bb_p (const_basic_block bb ATTRIBUTE_UNUSED) preserve SSA form. */ static basic_block -gimple_duplicate_bb (basic_block bb) +gimple_duplicate_bb (basic_block bb, copy_bb_data *id) { basic_block new_bb; gimple_stmt_iterator gsi_tgt; @@ -6228,6 +6228,36 @@ gimple_duplicate_bb (basic_block bb) && (!VAR_P (base) || !DECL_HAS_VALUE_EXPR_P (base))) DECL_NONSHAREABLE (base) = 1; } + + if (id) + for (unsigned i = 0; i < gimple_num_ops (copy); ++i) + { + tree op = gimple_op (copy, i); + if (!op) + continue; + if (TREE_CODE (op) == ADDR_EXPR + || TREE_CODE (op) == WITH_SIZE_EXPR) + op = TREE_OPERAND (op, 0); + while (handled_component_p (op)) + op = TREE_OPERAND (op, 0); + if ((TREE_CODE (op) == MEM_REF + || TREE_CODE (op) == TARGET_MEM_REF) + && MR_DEPENDENCE_CLIQUE (op) != 0) + { + if (!id->dependence_map) + id->dependence_map = new hash_map; + bool existed; + unsigned short &newc = id->dependence_map->get_or_insert + (MR_DEPENDENCE_CLIQUE (op), &existed); + if (!existed) + { + gcc_assert (MR_DEPENDENCE_CLIQUE (op) <= cfun->last_clique); + newc = ++cfun->last_clique; + } + MR_DEPENDENCE_CLIQUE (op) = newc; + } + } /* Create new names for all the definitions created by COPY and add replacement mappings for each new name. */