add_join_conditional()'s job is to take the 2 alternatives of the conditional, make a phi-node from them and return the corresponding pseudo but if one of the alternatives is not available it's useless to create a phi-node and the other alternative can then directly be returned. The problem is that in this later case, the pseudo directly returned is the PSEUDO_PHI of the corresponding phi-source. This gives erroneous code like, for example: phisrc.32 %phi1 <- $0 ret.32 %phi1 instead of: ret.32 $0 since the %ph1 should only be used by a phi-node instruction. Fix this by returning phi-source's operand instead. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- linearize.c | 4 ++-- validation/linear/join-cond-discard.c | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 validation/linear/join-cond-discard.c diff --git a/linearize.c b/linearize.c index e80715ab2458..7a6f745fd4fc 100644 --- a/linearize.c +++ b/linearize.c @@ -1678,9 +1678,9 @@ static pseudo_t add_join_conditional(struct entrypoint *ep, struct expression *e struct instruction *phi_node; if (phi1 == VOID) - return phi2; + return (phi2 == VOID) ? phi2 : phi2->def->src; if (phi2 == VOID) - return phi1; + return (phi1 == VOID) ? phi1 : phi1->def->src; phi_node = alloc_typed_instruction(OP_PHI, expr->ctype); use_pseudo(phi_node, phi1, add_pseudo(&phi_node->phi_list, phi1)); diff --git a/validation/linear/join-cond-discard.c b/validation/linear/join-cond-discard.c new file mode 100644 index 000000000000..9f07a7d499f6 --- /dev/null +++ b/validation/linear/join-cond-discard.c @@ -0,0 +1,19 @@ +void abort(void) __attribute__((noreturn)); + +int bar(int a) +{ + return a ? (abort(), 0) : 0; +} + +int qux(int a) +{ + return a ? (abort(), 0) : (abort(), 1); +} + +/* + * check-name: join-cond-discard + * check-command: test-linearize -Wno-decl $file + * + * check-output-ignore + * check-output-excludes: phisrc\\..*phi + */ -- 2.30.0