diff options
| -rw-r--r-- | simplify.c | 11 | ||||
| -rw-r--r-- | validation/optim/muldiv-minus-one.c | 13 |
2 files changed, 24 insertions, 0 deletions
@@ -339,6 +339,9 @@ static int simplify_asr(struct instruction *insn, pseudo_t pseudo, long long val static int simplify_mul_div(struct instruction *insn, long long value) { + unsigned long long sbit = 1ULL << (insn->size - 1); + unsigned long long bits = sbit | (sbit - 1); + if (value == 1) return replace_with_pseudo(insn, insn->src1); @@ -347,6 +350,14 @@ static int simplify_mul_div(struct instruction *insn, long long value) case OP_MULU: if (value == 0) return replace_with_pseudo(insn, insn->src2); + if (!(value & sbit)) // positive + break; + + value |= ~bits; + if (value == -1) { + insn->opcode = OP_NEG; + return REPEAT_CSE; + } } return 0; diff --git a/validation/optim/muldiv-minus-one.c b/validation/optim/muldiv-minus-one.c new file mode 100644 index 00000000..729b7344 --- /dev/null +++ b/validation/optim/muldiv-minus-one.c @@ -0,0 +1,13 @@ +typedef unsigned int u32; + +int smulm1(int a) { return a * -1; } +u32 umulm1(u32 a) { return a * (u32) -1; } + +/* + * check-name: muldiv-minus-one + * check-command: test-linearize -Wno-decl $file + * check-output-ignore + * + * check-output-excludes: mul[us]\\. + * check-output-contains: neg\\. + */ |
