aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-11-14 01:57:39 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-11-21 18:18:43 +0100
commit7943063c5206e28f00d6f4c5117de034c369cd92 (patch)
treee00c927210592dd665e545b2210268d72d1b7ab1
parentd02b992124038a142416ef1b07011b726a55d772 (diff)
downloadsparse-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.c30
-rw-r--r--validation/optim/cgoto01.c1
2 files changed, 30 insertions, 1 deletions
diff --git a/simplify.c b/simplify.c
index e58fb6cf..132d408f 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->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\\.