If the OP_COMPUTEDGOTO's source pseudo is defined by an OP_SETVAL with a label, then this label is the only possible destination of the computed goto which can then be transformed into a simple branch. So, convert such computed goto into a simple OP_BR which may then participate in other flow simplifications. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- simplify.c | 30 ++++++++++++++++++++++++++++++ validation/optim/cgoto01.c | 24 ++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 validation/optim/cgoto01.c diff --git a/simplify.c b/simplify.c index e58fb6cf3941..08022c97437a 100644 --- a/simplify.c +++ b/simplify.c @@ -2112,6 +2112,34 @@ found: return REPEAT_CSE; } +static int simplify_cgoto(struct instruction *insn) +{ + struct basic_block *target, *bb = insn->bb; + struct instruction *def; + struct multijmp *jmp; + + switch (DEF_OPCODE(def, insn->cond)) { + case OP_SETVAL: + if (def->val->type != EXPR_LABEL) + break; + target = def->val->symbol->bb_target; + if (!target->ep) + return 0; + FOR_EACH_PTR(insn->multijmp_list, jmp) { + if (jmp->target == target) + continue; + remove_bb_from_list(&jmp->target->parents, bb, 1); + remove_bb_from_list(&bb->children, jmp->target, 1); + MARK_CURRENT_DELETED(jmp); + } END_FOR_EACH_PTR(jmp); + kill_use(&insn->cond); + insn->opcode = OP_BR; + insn->bb_true = target; + return REPEAT_CSE|REPEAT_CFG_CLEANUP; + } + return 0; +} + int simplify_instruction(struct instruction *insn) { unsigned flags; @@ -2190,6 +2218,8 @@ int simplify_instruction(struct instruction *insn) return simplify_branch(insn); case OP_SWITCH: return simplify_switch(insn); + case OP_COMPUTEDGOTO: + return simplify_cgoto(insn); case OP_RANGE: return simplify_range(insn); case OP_FADD: diff --git a/validation/optim/cgoto01.c b/validation/optim/cgoto01.c new file mode 100644 index 000000000000..94b2c2c429db --- /dev/null +++ b/validation/optim/cgoto01.c @@ -0,0 +1,24 @@ +void abort(void) __attribute__((__noreturn__)); + +int foo(int a) +{ + void *label; + + if (a == a) + label = &&L1; + else + label = &&L2; + goto *label; +L1: return 0; +L2: abort(); +} + +/* + * check-name: cgoto01 + * check-command: test-linearize -Wno-decl $file + * + * check-output-ignore + * check-output-excludes: set\\. + * check-output-excludes: jmp + * check-output-excludes: call + */ -- 2.29.2