diff options
author | 2005-02-04 11:40:03 -0700 | |
---|---|---|
committer | 2005-04-07 21:06:18 -0700 | |
commit | 246ccfb6db7ea420f658f59ff3c0401748cf8f4c (patch) | |
tree | b33411374ba7a16147744e989aefb43933fb5f12 /simplify.c | |
parent | Don't optimize away casts too early. (diff) | |
download | sparse-246ccfb6db7ea420f658f59ff3c0401748cf8f4c.tar.gz sparse-246ccfb6db7ea420f658f59ff3c0401748cf8f4c.tar.bz2 sparse-246ccfb6db7ea420f658f59ff3c0401748cf8f4c.zip |
Simplify OP_CAST of OP_AND.
We can remove the cast if the AND made it unnecessary.
Diffstat (limited to 'simplify.c')
-rw-r--r-- | simplify.c | 28 |
1 files changed, 21 insertions, 7 deletions
@@ -553,17 +553,31 @@ static int simplify_memop(struct instruction *insn) static int simplify_cast(struct instruction *insn) { - int orig_size; + int orig_size, size; + pseudo_t src; if (dead_insn(insn, &insn->src, NULL, NULL)) return REPEAT_CSE; - if (0 && insn->opcode == OP_PTRCAST) - return 0; orig_size = insn->orig_type ? insn->orig_type->bit_size : 0; - if (orig_size < 0) - orig_size = 0; - if (insn->size != orig_size) - return 0; + size = insn->size; + src = insn->src; + + /* A cast of a "and" might be a no-op.. */ + if (src->type == PSEUDO_REG) { + struct instruction *def = src->def; + if (def->opcode == OP_AND && def->size >= size) { + pseudo_t val = def->src2; + if (val->type == PSEUDO_VAL) { + unsigned long long value = val->value; + if (!(value >> (size-1))) + goto simplify; + } + } + } + + return 0; + +simplify: return replace_with_pseudo(insn, insn->src); } |