perf(optimiser): fold neutral arithmetic and bitwise operations
3 files changed, +17 −2
- src/Examples.thy modified +8 −0
- src/Model.thy modified +7 −2
- tests/native.py modified +2 −0
src/Examples.thy modified
| @@ -27,6 +27,14 @@ lemma constant_fold: | ||
| 27 | 27 | "optimise (Binary Add (Literal (-1)) (Literal 1)) = Literal 0" |
| 28 | 28 | by eval |
| 29 | 29 | |
| 30 | +lemma neutral_arithmetic: | |
| 31 | + "optimise (Binary Mul (Binary Add (Input X) (Literal 0)) (Literal 1)) = Input X" | |
| 32 | + by eval | |
| 33 | + | |
| 34 | +lemma neutral_bits: | |
| 35 | + "optimise (Binary And (Binary Xor (Input Y) (Literal 0)) (Literal (-1))) = Input Y" | |
| 36 | + by eval | |
| 37 | + | |
| 30 | 38 | lemma dead_branch: |
| 31 | 39 | "optimise (Cond (Literal 0) (Input X) (Input Y)) = Input Y" |
| 32 | 40 | by eval |
src/Model.thy modified
| @@ -44,7 +44,12 @@ fun scoped :: "nat \<Rightarrow> expression \<Rightarrow> bool" where | ||
| 44 | 44 | |
| 45 | 45 | fun fold_binary :: "operator \<Rightarrow> expression \<Rightarrow> expression \<Rightarrow> expression" where |
| 46 | 46 | "fold_binary op (Literal a) (Literal b) = Literal (operate op a b)" |
| 47 | -| "fold_binary op a b = Binary op a b" | |
| 47 | +| "fold_binary op a b = (if b = Literal 0 \<and> op \<in> {Add,Sub,Or,Xor,Shl,Shr} then a | |
| 48 | + else if a = Literal 0 \<and> op \<in> {Add,Or,Xor} then b | |
| 49 | + else if b = Literal 1 \<and> op = Mul then a | |
| 50 | + else if a = Literal 1 \<and> op = Mul then b | |
| 51 | + else if b = Literal (-1) \<and> op = And then a | |
| 52 | + else if a = Literal (-1) \<and> op = And then b else Binary op a b)" | |
| 48 | 53 | |
| 49 | 54 | fun fold_cond :: "expression \<Rightarrow> expression \<Rightarrow> expression \<Rightarrow> expression" where |
| 50 | 55 | "fold_cond (Literal c) a b = (if c = 0 then b else a)" |
| @@ -58,7 +63,7 @@ fun optimise :: "expression \<Rightarrow> expression" where | ||
| 58 | 63 | |
| 59 | 64 | lemma fold_binary_value: |
| 60 | 65 | "evaluate (fold_binary op a b) env inputs = operate op (evaluate a env inputs) (evaluate b env inputs)" |
| 61 | - by (cases a; cases b) auto | |
| 66 | + by (cases op; cases a; cases b) auto | |
| 62 | 67 | |
| 63 | 68 | lemma fold_cond_value: |
| 64 | 69 | "evaluate (fold_cond c a b) env inputs = (if evaluate c env inputs = 0 then evaluate b env inputs else evaluate a env inputs)" |
tests/native.py modified
| @@ -65,6 +65,8 @@ def main(): | ||
| 65 | 65 | raise RuntimeError("native differential tests require an x86-64 Linux host") |
| 66 | 66 | rng = random.Random(0x52454D59) |
| 67 | 67 | cases = [(op, "x", "y") for op in OPERATORS] |
| 68 | + cases += [(op, "x", 0) for op in ("+", "-", "or", "xor", "shl", "shr")] | |
| 69 | + cases += [("*", "x", 1), ("*", 1, "x"), ("and", "x", MASK)] | |
| 68 | 70 | cases += [("let", "a", ("+", "x", 3), ("+", "y", ("let", "b", "t", ("*", "a", "b")))), |
| 69 | 71 | ("let", "x", "y", ("if", "t", ("+", "x", 1), ("-", "x", 1)))] |
| 70 | 72 | cases += [generate(rng, 5, ["x", "y", "t"]) for _ in range(117)] |