aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/simplify.c
diff options
Diffstat (limited to 'simplify.c')
-rw-r--r--simplify.c69
1 files changed, 43 insertions, 26 deletions
diff --git a/simplify.c b/simplify.c
index 0a29db18..02709ce4 100644
--- a/simplify.c
+++ b/simplify.c
@@ -1280,10 +1280,14 @@ static int simplify_compare_constant(struct instruction *insn, long long value)
case OP_SET_EQ:
if ((value & bits) != value)
return replace_with_value(insn, 0);
+ if (value == bits && is_power_of_2(bits))
+ return replace_binop_value(insn, OP_SET_NE, 0);
break;
case OP_SET_NE:
if ((value & bits) != value)
return replace_with_value(insn, 1);
+ if (value == bits && is_power_of_2(bits))
+ return replace_binop_value(insn, OP_SET_EQ, 0);
break;
case OP_SET_LE: case OP_SET_LT:
value = sign_extend(value, def->size);
@@ -1414,6 +1418,20 @@ static int simplify_compare_constant(struct instruction *insn, long long value)
break;
}
break;
+ case OP_TRUNC:
+ osize = def->orig_type->bit_size;
+ switch (insn->opcode) {
+ case OP_SET_EQ: case OP_SET_NE:
+ if (one_use(def->target)) {
+ insn->itype = def->orig_type;
+ def->type = def->orig_type;
+ def->size = osize;
+ def->src2 = value_pseudo(bits);
+ return replace_opcode(def, OP_AND);
+ }
+ break;
+ }
+ break;
case OP_ZEXT:
osize = def->orig_type->bit_size;
bits = bits_mask(osize);
@@ -2321,6 +2339,21 @@ static int simplify_cast(struct instruction *insn)
return replace_pseudo(insn, &insn->src1, def->src1);
}
break;
+ case OP_NOT:
+ switch (insn->opcode) {
+ case OP_TRUNC:
+ if (one_use(src)) {
+ // TRUNC(NOT(x)) --> NOT(TRUNC(x))
+ insn->opcode = OP_NOT;
+ def->orig_type = def->type;
+ def->opcode = OP_TRUNC;
+ def->type = insn->type;
+ def->size = insn->size;
+ return REPEAT_CSE;
+ }
+ break;
+ }
+ break;
case OP_OR:
switch (insn->opcode) {
case OP_TRUNC:
@@ -2571,23 +2604,12 @@ static int simplify_branch(struct instruction *insn)
pseudo_t cond = insn->cond;
/* Constant conditional */
- if (constant(cond)) {
- insert_branch(insn->bb, insn, cond->value ? insn->bb_true : insn->bb_false);
- return REPEAT_CSE;
- }
+ if (constant(cond))
+ return convert_to_jump(insn, cond->value ? insn->bb_true : insn->bb_false);
/* Same target? */
- if (insn->bb_true == insn->bb_false) {
- struct basic_block *bb = insn->bb;
- struct basic_block *target = insn->bb_false;
- remove_bb_from_list(&target->parents, bb, 1);
- remove_bb_from_list(&bb->children, target, 1);
- insn->bb_false = NULL;
- kill_use(&insn->cond);
- insn->cond = NULL;
- insn->opcode = OP_BR;
- return REPEAT_CSE|REPEAT_CFG_CLEANUP;
- }
+ if (insn->bb_true == insn->bb_false)
+ return convert_to_jump(insn, insn->bb_true);
/* Conditional on a SETNE $0 or SETEQ $0 */
if (cond->type == PSEUDO_REG) {
@@ -2603,14 +2625,10 @@ static int simplify_branch(struct instruction *insn)
if (constant(def->src2) && constant(def->src3)) {
long long val1 = def->src2->value;
long long val2 = def->src3->value;
- if (!val1 && !val2) {
- insert_branch(insn->bb, insn, insn->bb_false);
- return REPEAT_CSE;
- }
- if (val1 && val2) {
- insert_branch(insn->bb, insn, insn->bb_true);
- return REPEAT_CSE;
- }
+ if (!val1 && !val2)
+ return convert_to_jump(insn, insn->bb_false);
+ if (val1 && val2)
+ return convert_to_jump(insn, insn->bb_true);
if (val2) {
struct basic_block *tmp = insn->bb_true;
insn->bb_true = insn->bb_false;
@@ -2646,8 +2664,7 @@ static int simplify_switch(struct instruction *insn)
return 0;
found:
- insert_branch(insn->bb, insn, jmp->target);
- return REPEAT_CSE;
+ return convert_to_jump(insn, jmp->target);
}
static struct basic_block *is_label(pseudo_t pseudo)
@@ -2684,7 +2701,7 @@ static int simplify_cgoto(struct instruction *insn)
continue;
remove_bb_from_list(&jmp->target->parents, bb, 1);
remove_bb_from_list(&bb->children, jmp->target, 1);
- MARK_CURRENT_DELETED(jmp);
+ DELETE_CURRENT_PTR(jmp);
} END_FOR_EACH_PTR(jmp);
kill_use(&insn->src);
insn->opcode = OP_BR;