From 8b89204e0d7e2caaaa03ff8ed79da5bf6f2e1b36 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Fri, 26 Mar 2021 00:41:22 +0100 Subject: fix remove_merging_phisrc() The current implementation of remove_merging_phisrc() can't work correctly when these phi-sources belong to a basic block with several children to the same target basic block (this happens commonly with OP_SWITCH). Fix this by directly scanning the source basic block for the presence of any phi-source. Once identified, the processing is kept unchanged: remove these phi-sources if a sibling phi-source will 'overwrite' them in the target block. Fixes: 2fdaca9e7175e62f08d259f5cb3ec7c9725bba68 Signed-off-by: Luc Van Oostenryck --- flow.c | 30 ++++++++++++++++++++---------- validation/optim/multi-phisrc.c | 1 - 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/flow.c b/flow.c index c866dec8..d46d0ee1 100644 --- a/flow.c +++ b/flow.c @@ -843,21 +843,26 @@ static int retarget_parents(struct basic_block *bb, struct basic_block *target) return REPEAT_CFG_CLEANUP; } -static void remove_merging_phisrc(struct basic_block *top, struct instruction *insn) +static void remove_merging_phisrc(struct instruction *insn, struct basic_block *bot) { - struct instruction *user = insn->phi_node; + struct instruction *node = insn->phi_node; pseudo_t phi; - FOR_EACH_PTR(user->phi_list, phi) { + if (!node) { + kill_instruction(insn); + return; + } + + FOR_EACH_PTR(node->phi_list, phi) { struct instruction *phisrc; if (phi == VOID) continue; phisrc = phi->def; - if (phisrc->bb != top) - continue; - REPLACE_CURRENT_PTR(phi, VOID); - kill_instruction(phisrc); + if (phisrc->bb == bot) { + kill_instruction(insn); + return; + } } END_FOR_EACH_PTR(phi); } @@ -901,6 +906,14 @@ static int merge_bb(struct basic_block *top, struct basic_block *bot) replace_bb_in_list(&bb->parents, bot, top, 1); } END_FOR_EACH_PTR(bb); + FOR_EACH_PTR(top->insns, insn) { + if (!insn->bb) + continue; + if (insn->opcode != OP_PHISOURCE) + continue; + remove_merging_phisrc(insn, bot); + } END_FOR_EACH_PTR(insn); + kill_instruction(delete_last_instruction(&top->insns)); FOR_EACH_PTR(bot->insns, insn) { if (!insn->bb) @@ -910,9 +923,6 @@ static int merge_bb(struct basic_block *top, struct basic_block *bot) case OP_PHI: remove_merging_phi(top, insn); continue; - case OP_PHISOURCE: - remove_merging_phisrc(top, insn); - break; } insn->bb = top; add_instruction(&top->insns, insn); diff --git a/validation/optim/multi-phisrc.c b/validation/optim/multi-phisrc.c index c6f21f2d..ff31c083 100644 --- a/validation/optim/multi-phisrc.c +++ b/validation/optim/multi-phisrc.c @@ -17,7 +17,6 @@ void foo(int p, int a) /* * check-name: multi-phisrc * check-command: test-linearize -Wno-decl $file - * check-known-to-fail * * check-output-ignore * check-output-excludes: phi -- cgit 1.2.3-korg