diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-01-22 18:34:14 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-07 21:06:16 -0700 |
commit | 378908b588e2266f3751165d28218607beaec2eb (patch) | |
tree | 3bc6b24e19d2ce28e97e416ba57ac183f4ff161c /simplify.c | |
parent | Split the binops where signedness matters into unsigned and signed. (diff) | |
download | sparse-378908b588e2266f3751165d28218607beaec2eb.tar.gz sparse-378908b588e2266f3751165d28218607beaec2eb.tar.bz2 sparse-378908b588e2266f3751165d28218607beaec2eb.zip |
Make constant instruction simplification take the sign of the
instruction into account now that we have it.
Diffstat (limited to 'simplify.c')
-rw-r--r-- | simplify.c | 49 |
1 files changed, 29 insertions, 20 deletions
@@ -280,7 +280,18 @@ static int simplify_constant_binop(struct instruction *insn) /* FIXME! Verify signs and sizes!! */ long long left = insn->src1->value; long long right = insn->src2->value; - long long res, mask; + unsigned long long ul, ur; + long long res, mask, bits; + + mask = 1ULL << (insn->size-1); + bits = mask | (mask-1); + + if (left & mask) + left |= ~bits; + if (right & mask) + right |= ~bits; + ul = left & bits; + ur = right & bits; switch (insn->opcode) { case OP_ADD: @@ -290,30 +301,38 @@ static int simplify_constant_binop(struct instruction *insn) res = left - right; break; case OP_MULU: + res = ul * ur; + break; case OP_MULS: - /* FIXME! Check sign! */ res = left * right; break; case OP_DIVU: + if (!ur) + return 0; + res = ul / ur; + break; case OP_DIVS: if (!right) return 0; - /* FIXME! Check sign! */ res = left / right; break; case OP_MODU: + if (!ur) + return 0; + res = ul % ur; + break; case OP_MODS: if (!right) return 0; - /* FIXME! Check sign! */ res = left % right; break; case OP_SHL: res = left << right; break; case OP_LSR: + res = ul >> ur; + break; case OP_ASR: - /* FIXME! Check sign! */ res = left >> right; break; /* Logical */ @@ -341,44 +360,34 @@ static int simplify_constant_binop(struct instruction *insn) res = left != right; break; case OP_SET_LE: - /* FIXME! Check sign! */ res = left <= right; break; case OP_SET_GE: - /* FIXME! Check sign! */ res = left >= right; break; case OP_SET_LT: - /* FIXME! Check sign! */ res = left < right; break; case OP_SET_GT: - /* FIXME! Check sign! */ res = left > right; break; case OP_SET_B: - /* FIXME! Check sign! */ - res = (unsigned long long) left < (unsigned long long) right; + res = ul < ur; break; case OP_SET_A: - /* FIXME! Check sign! */ - res = (unsigned long long) left > (unsigned long long) right; + res = ul > ur; break; case OP_SET_BE: - /* FIXME! Check sign! */ - res = (unsigned long long) left <= (unsigned long long) right; + res = ul <= ur; break; case OP_SET_AE: - /* FIXME! Check sign! */ - res = (unsigned long long) left >= (unsigned long long) right; + res = ul >= ur; break; default: return 0; } - mask = 1ULL << (insn->size-1); - res &= mask | (mask-1); + res &= bits; - /* FIXME!! Sign??? */ replace_with_pseudo(insn, value_pseudo(res)); return REPEAT_CSE; } |