aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2004-11-30 19:18:34 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:05:19 -0700
commit59070f30ecdb61b449a14c335c94d2e2377010d6 (patch)
treed24faee9f7883ae1111149be6bffb3fea4f4a1ca /simplify.c
parentA sparse "context" instruction has side effects. Don't allow (diff)
downloadsparse-59070f30ecdb61b449a14c335c94d2e2377010d6.tar.gz
sparse-59070f30ecdb61b449a14c335c94d2e2377010d6.tar.bz2
sparse-59070f30ecdb61b449a14c335c94d2e2377010d6.zip
Simplify seteq/setne $0 + conditional branch.
Diffstat (limited to 'simplify.c')
-rw-r--r--simplify.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/simplify.c b/simplify.c
index 3b1ce0e..2244b0d 100644
--- a/simplify.c
+++ b/simplify.c
@@ -500,13 +500,47 @@ static int simplify_select(struct instruction *insn, struct instruction *setcc)
return 0;
}
+/*
+ * Simplify "set_ne/eq $0 + br"
+ */
+static int simplify_cond_branch(struct instruction *br, pseudo_t cond, struct instruction *def, pseudo_t *pp)
+{
+ use_pseudo(*pp, &br->cond);
+ remove_usage(cond, &br->cond);
+ if (def->opcode == OP_SET_EQ) {
+ struct basic_block *true = br->bb_true;
+ struct basic_block *false = br->bb_false;
+ br->bb_false = true;
+ br->bb_true = false;
+ }
+ return REPEAT_CSE;
+}
+
static int simplify_branch(struct instruction *insn)
{
pseudo_t cond = insn->cond;
- if (!cond || !constant(cond))
+
+ if (!cond)
return 0;
- insert_branch(insn->bb, insn, cond->value ? insn->bb_true : insn->bb_false);
- return REPEAT_CSE;
+
+ /* Constant conditional */
+ if (constant(cond)) {
+ insert_branch(insn->bb, insn, cond->value ? insn->bb_true : insn->bb_false);
+ return REPEAT_CSE;
+ }
+
+ /* Conditional on a SETNE $0 or SETEQ $0 */
+ if (cond->type == PSEUDO_REG) {
+ struct instruction *def = cond->def;
+
+ if (def->opcode == OP_SET_NE || def->opcode == OP_SET_EQ) {
+ if (constant(def->src1) && !def->src1->value)
+ return simplify_cond_branch(insn, cond, def, &def->src2);
+ if (constant(def->src2) && !def->src2->value)
+ return simplify_cond_branch(insn, cond, def, &def->src1);
+ }
+ }
+ return 0;
}
static int simplify_switch(struct instruction *insn)