Reformulated comment to better describe what it does. (Sorry for inconvenience) Signed-off-by: Jan Pokorny <pokorny_jan@xxxxxxxxx> --- liveness.c | 29 ++++++++++++++++++++--------- 1 files changed, 20 insertions(+), 9 deletions(-) diff --git a/liveness.c b/liveness.c index eeff0f7..8c15645 100644 --- a/liveness.c +++ b/liveness.c @@ -13,21 +13,32 @@ #include "flow.h" static void phi_defines(struct instruction * phi_node, pseudo_t target, - void (*defines)(struct basic_block *, struct instruction *, pseudo_t)) + void (*defines)(struct basic_block *, struct instruction *, pseudo_t), + unsigned long generation) { pseudo_t phi; FOR_EACH_PTR(phi_node->phi_list, phi) { - struct instruction *def; if (phi == VOID) continue; - def = phi->def; - if (!def || !def->bb) - continue; - if (def->opcode == OP_PHI) { - phi_defines(def, target, defines); + if (!phi->def || !phi->def->bb) continue; + + /* + * In case of "(PHISOURCE->PHI->)+ PHISOURCE->PHI" chain, move + * "defines" information upstream to BBs of very initial PHISOURCEs; + * recursion guarded by generation marking of PHI instructions BBs. + */ + pseudo_t src_pseudo = phi->def->phi_src; + if (src_pseudo->type == PSEUDO_REG + && src_pseudo->def->opcode == OP_PHI) { + phi_node->bb->generation = generation; + if (src_pseudo->def->bb->generation != generation) { + phi_defines(src_pseudo->def, target, defines, generation); + continue; + } } - defines(def->bb, phi->def, target); + + defines(phi->def->bb, phi->def, target); } END_FOR_EACH_PTR(phi); } @@ -103,7 +114,7 @@ static void track_instruction_usage(struct basic_block *bb, struct instruction * /* Other */ case OP_PHI: /* Phi-nodes are "backwards" nodes. Their def doesn't matter */ - phi_defines(insn, insn->target, def); + phi_defines(insn, insn->target, def, ++bb_generation); break; case OP_PHISOURCE: -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-sparse" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html