Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions cranelift/codegen/src/opts/arithmetic.isle
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,67 @@
(rule (simplify (bxor ty (bxor ty (bxor ty a b) c) d))
(subsume (bxor ty (bxor ty a b) (bxor ty c d))))


;; Similar rules but for associating combinations of + and -

;; a -(b-(c-d)) = (a-b) + (c-d)
(rule (simplify (isub ty a (isub ty b (isub ty c d))))
(subsume (iadd ty (isub ty a b) (isub ty c d))))

;; a -(b-(c+d)) = (a-b) + (c+d)
(rule (simplify (isub ty a (isub ty b (iadd ty c d))))
(subsume (iadd ty (isub ty a b) (iadd ty c d))))

;; a -(b+(c-d)) = (a-b) - (c-d)
(rule (simplify (isub ty a (iadd ty b (isub ty c d))))
(subsume (isub ty (isub ty a b) (isub ty c d))))

;; a -(b+(c+d)) = (a-b) - (c+d)
(rule (simplify (isub ty a (iadd ty b (iadd ty c d))))
(subsume (isub ty (isub ty a b) (iadd ty c d))))

;; a +(b-(c-d)) = (a+b) - (c-d)
(rule (simplify (iadd ty a (isub ty b (isub ty c d))))
(subsume (isub ty (iadd ty a b) (isub ty c d))))

;; a +(b-(c+d)) = (a+b) - (c+d)
(rule (simplify (iadd ty a (isub ty b (iadd ty c d))))
(subsume (isub ty (iadd ty a b) (iadd ty c d))))

;; a +(b+(c-d)) = (a+b) + (c-d)
(rule (simplify (iadd ty a (iadd ty b (isub ty c d))))
(subsume (iadd ty (iadd ty a b) (isub ty c d))))

;; and nested the other way

;; ((a-b)-c)-d = (a-b) - (c+d)
(rule (simplify (isub ty (isub ty (isub ty a b) c) d))
(subsume (isub ty (isub ty a b) (iadd ty c d))))

;; ((a-b)-c)+d = (a-b) - (c-d)
(rule (simplify (iadd ty (isub ty (isub ty a b) c) d))
(subsume (isub ty (isub ty a b) (isub ty c d))))

;; ((a-b)+c)-d = (a-b) + (c-d)
(rule (simplify (isub ty (iadd ty (isub ty a b) c) d))
(subsume (iadd ty (isub ty a b) (isub ty c d))))

;; ((a-b)+c)+d = (a-b) + (c+d)
(rule (simplify (iadd ty (iadd ty (isub ty a b) c) d))
(subsume (iadd ty (isub ty a b) (iadd ty c d))))

;; ((a+b)-c)-d = (a+b) - (c+d)
(rule (simplify (isub ty (isub ty (iadd ty a b) c) d))
(subsume (isub ty (iadd ty a b) (iadd ty c d))))

;; ((a+b)-c)+d = (a+b) - (c-d)
(rule (simplify (iadd ty (isub ty (iadd ty a b) c) d))
(subsume (isub ty (iadd ty a b) (isub ty c d))))

;; ((a+b)+c)-d = (a+b) + (c-d)
(rule (simplify (isub ty (iadd ty (iadd ty a b) c) d))
(subsume (iadd ty (iadd ty a b) (isub ty c d))))

;; Detect people open-coding `mulhi`: (x as big * y as big) >> bits
;; LLVM doesn't have an intrinsic for it, so you'll see it in code like
;; <https://github.com/rust-lang/rust/blob/767453eb7ca188e991ac5568c17b984dd4893e77/library/core/src/num/mod.rs#L174-L180>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,171 @@ block0(v0: i8):
v28 = ireduce.i16 v27
return v28
}

function %iadd_sub_1_shallow_and_wide(i32, i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32, v3: i32):
v4 = isub v2, v3
v5 = isub v1, v4
v6 = isub v0, v5
return v6
; check: v7 = isub v0, v1
; nextln: v4 = isub v2, v3
; nextln: v8 = iadd v7, v4
; check: return v8
}

function %iadd_sub_2_shallow_and_wide(i32, i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32, v3: i32):
v4 = iadd v2, v3
v5 = isub v1, v4
v6 = isub v0, v5
return v6
; check: v7 = isub v0, v1
; nextln: v4 = iadd v2, v3
; nextln: v8 = iadd v7, v4
; check: return v8
}

function %iadd_sub_3_shallow_and_wide(i32, i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32, v3: i32):
v4 = isub v2, v3
v5 = iadd v1, v4
v6 = isub v0, v5
return v6
; check: v7 = isub v0, v1
; nextln: v4 = isub v2, v3
; nextln: v8 = isub v7, v4
; check: return v8
}

function %iadd_sub_4_shallow_and_wide(i32, i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32, v3: i32):
v4 = iadd v2, v3
v5 = iadd v1, v4
v6 = isub v0, v5
return v6
; check: v7 = isub v0, v1
; nextln: v4 = iadd v2, v3
; nextln: v8 = isub v7, v4
; check: return v8
}

function %iadd_sub_5_shallow_and_wide(i32, i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32, v3: i32):
v4 = isub v2, v3
v5 = isub v1, v4
v6 = iadd v0, v5
return v6
; check: v7 = iadd v0, v1
; nextln: v4 = isub v2, v3
; nextln: v8 = isub v7, v4
; check: return v8
}

function %iadd_sub_6_shallow_and_wide(i32, i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32, v3: i32):
v4 = iadd v2, v3
v5 = isub v1, v4
v6 = iadd v0, v5
return v6
; check: v7 = iadd v0, v1
; nextln: v4 = iadd v2, v3
; nextln: v8 = isub v7, v4
; check: return v8
}

function %iadd_sub_7_shallow_and_wide(i32, i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32, v3: i32):
v4 = isub v2, v3
v5 = iadd v1, v4
v6 = iadd v0, v5
return v6
; check: v7 = iadd v0, v1
; nextln: v4 = isub v2, v3
; nextln: v8 = iadd v7, v4
; check: return v8
}

function %isub_add_1_shallow_and_wide(i32, i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32, v3: i32):
v4 = isub v0, v1
v5 = isub v4, v2
v6 = isub v5, v3
return v6
; check: v4 = isub v0, v1
; nextln: v7 = iadd v2, v3
; nextln: v8 = isub v4, v7
; check: return v8
}

function %isub_add_2_shallow_and_wide(i32, i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32, v3: i32):
v4 = isub v0, v1
v5 = isub v4, v2
v6 = iadd v5, v3
return v6
; check: v4 = isub v0, v1
; nextln: v7 = isub v2, v3
; nextln: v8 = isub v4, v7
; check: return v8
}

function %isub_add_3_shallow_and_wide(i32, i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32, v3: i32):
v4 = isub v0, v1
v5 = iadd v4, v2
v6 = isub v5, v3
return v6
; check: v4 = isub v0, v1
; nextln: v7 = isub v2, v3
; nextln: v8 = iadd v4, v7
; check: return v8
}

function %isub_add_4_shallow_and_wide(i32, i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32, v3: i32):
v4 = isub v0, v1
v5 = iadd v4, v2
v6 = iadd v5, v3
return v6
; check: v4 = isub v0, v1
; nextln: v7 = iadd v2, v3
; nextln: v8 = iadd v4, v7
; check: return v8
}

function %isub_add_5_shallow_and_wide(i32, i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32, v3: i32):
v4 = iadd v0, v1
v5 = isub v4, v2
v6 = isub v5, v3
return v6
; check: v4 = iadd v0, v1
; nextln: v7 = iadd v2, v3
; nextln: v8 = isub v4, v7
; check: return v8
}

function %isub_add_6_shallow_and_wide(i32, i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32, v3: i32):
v4 = iadd v0, v1
v5 = isub v4, v2
v6 = iadd v5, v3
return v6
; check: v4 = iadd v0, v1
; nextln: v7 = isub v2, v3
; nextln: v8 = isub v4, v7
; check: return v8
}

function %isub_add_7_shallow_and_wide(i32, i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32, v3: i32):
v4 = iadd v0, v1
v5 = iadd v4, v2
v6 = isub v5, v3
return v6
; check: v4 = iadd v0, v1
; nextln: v7 = isub v2, v3
; nextln: v8 = iadd v4, v7
; check: return v8
}