diff --git a/cranelift/codegen/src/opts/algebraic.isle b/cranelift/codegen/src/opts/algebraic.isle index 03ed0be235..cce5ebe6c1 100644 --- a/cranelift/codegen/src/opts/algebraic.isle +++ b/cranelift/codegen/src/opts/algebraic.isle @@ -62,6 +62,14 @@ _)) (subsume zero)) +;; x*-1 == -1*x == ineg(x). +(rule (simplify (imul ty x (iconst ty c))) + (if-let -1 (i64_sextend_imm64 ty c)) + (ineg ty x)) +(rule (simplify (imul ty (iconst ty c) x)) + (if-let -1 (i64_sextend_imm64 ty c)) + (ineg ty x)) + ;; x/1 == x. (rule (simplify (sdiv ty x diff --git a/cranelift/filetests/filetests/egraph/algebraic.clif b/cranelift/filetests/filetests/egraph/algebraic.clif index 0687330302..c29d67abee 100644 --- a/cranelift/filetests/filetests/egraph/algebraic.clif +++ b/cranelift/filetests/filetests/egraph/algebraic.clif @@ -250,6 +250,27 @@ block0(v0: i32): ; check: return v2 } +function %mul_minus_one(i32) -> i32 { +block0(v0: i32): + v1 = iconst.i32 0xffff_ffff ; -1 + v2 = imul v0, v1 + return v2 + ; check: v3 = ineg v0 + ; check: v4 -> v3 + ; check: return v3 +} + +function %mul_minus_one_commuted(i32) -> i32 { +block0(v0: i32): + v1 = iconst.i32 0xffff_ffff ; -1 + v2 = imul v1, v0 + return v2 + ; check: v3 = ineg v0 + ; check: v5 -> v3 + ; check: v6 -> v3 + ; check: return v3 +} + function %or_and_y_with_not_y_i8(i8, i8) -> i8 { block0(v0: i8, v1: i8): v2 = band v0, v1