diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-11-14 01:57:39 +0100 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-11-21 18:18:43 +0100 |
commit | 7943063c5206e28f00d6f4c5117de034c369cd92 (patch) | |
tree | e00c927210592dd665e545b2210268d72d1b7ab1 | |
parent | d02b992124038a142416ef1b07011b726a55d772 (diff) | |
download | sparse-7943063c5206e28f00d6f4c5117de034c369cd92.tar.gz |
simplify OP_COMPUTEDGOTO with unique and known target
If the OP_COMPUTEDGOTO's source pseudo is defined by a single
OP_SETVAL/EXPR_LABEL, then the corresponding basic block is the
only possible destination and the computed goto can then be
simplified 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@gmail.com>
-rw-r--r-- | simplify.c | 30 | ||||
-rw-r--r-- | validation/optim/cgoto01.c | 1 |
2 files changed, 30 insertions, 1 deletions
@@ -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->src)) { + 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->src); + 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 index 350c6cd9..94b2c2c4 100644 --- a/validation/optim/cgoto01.c +++ b/validation/optim/cgoto01.c @@ -16,7 +16,6 @@ L2: abort(); /* * check-name: cgoto01 * check-command: test-linearize -Wno-decl $file - * check-known-to-fail * * check-output-ignore * check-output-excludes: set\\. |