aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-02-04 11:40:03 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:06:18 -0700
commit246ccfb6db7ea420f658f59ff3c0401748cf8f4c (patch)
treeb33411374ba7a16147744e989aefb43933fb5f12 /simplify.c
parentDon't optimize away casts too early. (diff)
downloadsparse-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.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/simplify.c b/simplify.c
index 0d0f1b1..a1f798b 100644
--- a/simplify.c
+++ b/simplify.c
@@ -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);
}