re PR tree-optimization/87609 (miscompilation with restrict and loop)

2019-02-22  Richard Biener  <rguenther@suse.de>

	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
This commit is contained in:
Richard Biener 2019-02-22 08:38:14 +00:00 committed by Richard Biener
parent 3c8b06dcc6
commit 229d576cde
7 changed files with 100 additions and 9 deletions

View File

@ -1,3 +1,17 @@
2019-02-22 Richard Biener <rguenther@suse.de>
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 <rguenther@suse.de>
PR tree-optimization/87609

View File

@ -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)
{

View File

@ -54,6 +54,19 @@ struct profile_record
bool run;
};
typedef int_hash <unsigned short, 0> 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_hash, unsigned short> *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);

View File

@ -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;
}

View File

@ -1,3 +1,8 @@
2019-02-22 Richard Biener <rguenther@suse.de>
PR middle-end/87609
* gcc.dg/torture/restrict-7.c: New testcase.
2019-02-21 Jakub Jelinek <jakub@redhat.com>
PR c++/89285

View File

@ -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;
}

View File

@ -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<dependence_hash,
unsigned short>;
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. */