From a8464c8103bbac6462174baa1e098c850cc287bb Mon Sep 17 00:00:00 2001 From: luisacicolini Date: Fri, 17 Apr 2026 13:51:06 +0100 Subject: [PATCH 01/13] polishing --- SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean | 25 ++++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean b/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean index db58a4c633..66eefc1f1c 100644 --- a/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean +++ b/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean @@ -1179,7 +1179,7 @@ theorem hw_fork_refines1_with_fork: intro hcontra specialize hfstVldTrue2 fstSentIdx (by omega) simp [toStream, hfstVldTrue2] at hfstSentIdx - by_cases fstRecfst : fstRdyOut ≤ fstRdyOut2 + by_cases fstRecfst : fstRdyOut ≤ fstRdyOut2 · /- first receiver comes first -/ by_cases fstRecBeforeSent : fstVldTrue + fstRdyOut ≤ fstSentIdx · /- first receiver before sent -/ @@ -1190,6 +1190,11 @@ theorem hw_fork_refines1_with_fork: · funext i have := rdOut1_before_allDone (hfork := h_6) (n := i) /- what happens to `rdOut1` after data is dispatched? -/ + have heq : Stream'.drop (fstSentIdx + 1) rdIn_1 i = rdIn_1 (fstSentIdx + 1 + i) := by + simp [Stream'.drop] + congr 1 + grind + rw [heq] sorry · sorry @@ -1198,20 +1203,14 @@ theorem hw_fork_refines1_with_fork: · sorry · /- first receiver after sent -/ sorry - · /- first receiver after sent -/ - by_cases sndRecBeforeSent : fstVldTrue + fstRdyOut2 ≤ fstSentIdx - · /- second receiver before sent -/ - sorry - · /- first receiver after sent -/ - sorry + · /- first receiver after sent, implies second receiver after sent -/ + have : fstSentIdx ≤ fstVldTrue + fstRdyOut2 := by omega + sorry · /- second receiver comes first -/ by_cases fstRecBeforeSent : fstVldTrue + fstRdyOut ≤ fstSentIdx - · /- first receiver before sent -/ - by_cases sndRecBeforeSent : fstVldTrue + fstRdyOut2 ≤ fstSentIdx - · /- second receiver before sent -/ - sorry - · /- first receiver after sent -/ - sorry + · /- first receiver before sent, implies second receiver before sent -/ + have : fstVldTrue + fstRdyOut2 ≤ fstSentIdx := by omega + sorry · /- first receiver after sent -/ by_cases sndRecBeforeSent : fstVldTrue + fstRdyOut2 ≤ fstSentIdx · /- second receiver before sent -/ From cd9730f9c314e734f90d017b7bfc236388d0f20d Mon Sep 17 00:00:00 2001 From: luisacicolini Date: Thu, 30 Apr 2026 13:31:53 +0100 Subject: [PATCH 02/13] fix --- SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean | 34 +++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean b/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean index 66eefc1f1c..c13b164b7e 100644 --- a/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean +++ b/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean @@ -7,13 +7,18 @@ namespace HWComponents open HandshakeStream -def hw_constant (b : Bool) : BitVec 1 := - if b then 1#1 else 0#1 +/- + RTL-level definitions of circuit components +-/ +def hw_constant (b : Bool) : BitVec 1 := if b then 1#1 else 0#1 + +def comb_xor (x y : BitVec 1) : BitVec 1 := BitVec.xor x y -def comb_xor : BitVec 1 → BitVec 1 → BitVec 1 := BitVec.xor -def comb_and : BitVec 1 → BitVec 1 → BitVec 1 := BitVec.and -def comb_add : BitVec 32 → BitVec 32 → BitVec 32 := BitVec.add -def comb_or : BitVec 1 → BitVec 1 → BitVec 1 := BitVec.or +def comb_and (x y : BitVec 1) : BitVec 1 := BitVec.and x y + +def comb_add (x y : BitVec 32) : BitVec 32 := BitVec.add x y + +def comb_or (x y : BitVec 1) : BitVec 1 := BitVec.or x y namespace TRY1 @@ -1195,8 +1200,21 @@ theorem hw_fork_refines1_with_fork: congr 1 grind rw [heq] - - sorry + by_cases hfalse : rdIn_1 (fstSentIdx + 1 + i) = 0#1 + · have := congr_fun h_7 (fstSentIdx + 1 + i) + unfold toStream at this + simp [hfalse] at * + rw [hw_fork_eq] + + have : ∀ k, ∀ i, Stream'.drop k rdOut1_1 i = rdOut1_1 (i + k) := by + intros + simp [Stream'.drop, Stream'.get] + simp [hw_fork', Stream'.corec'] + unfold fork_corec + simp [comb_and, comb_xor, comb_or, hw_constant] + + sorry + · sorry · sorry · sorry · sorry From 5bbb70a64b55e554f3056428b69b17c7d24d5362 Mon Sep 17 00:00:00 2001 From: luisacicolini Date: Thu, 30 Apr 2026 13:32:13 +0100 Subject: [PATCH 03/13] pull out main lemma --- .../CIRCT/HandshakeToHW/fork_lowering.lean | 1614 +++++++++++++++++ 1 file changed, 1614 insertions(+) create mode 100644 SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean diff --git a/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean b/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean new file mode 100644 index 0000000000..ca62d028c6 --- /dev/null +++ b/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean @@ -0,0 +1,1614 @@ +import SSA.Projects.CIRCT.Stream.Basic +import SSA.Projects.CIRCT.Stream.Lemmas +import SSA.Projects.CIRCT.Register.Basic +import SSA.Projects.CIRCT.Register.Lemmas + +namespace HWComponents + +open HandshakeStream + + + +/-- + Latency-insensitive (handshake) fork component. + We assume that there are infinite buffers at the input and output of the fork. + This implies that ready == 1 (at the output), and that the input stream can be delayed infinitely long. + + Under this assumption, we do not really need the registers, + because we will instantly emit a value, and the registers will be constant true. + + This spec is the same as the hardware implementation if we guarantee that + a `ready` signal is received (no deadlock). + -/ +def handshake.fork (in0 : Stream (BitVec 32)) : Stream (BitVec 32) × Stream (BitVec 32) := + (in0, in0) + + +/- + RTL-level definitions of circuit components +-/ +def hw_constant (b : Bool) : BitVec 1 := if b then 1#1 else 0#1 + +def comb_xor (x y : BitVec 1) : BitVec 1 := BitVec.xor x y + +def comb_and (x y : BitVec 1) : BitVec 1 := BitVec.and x y + +def comb_add (x y : BitVec 32) : BitVec 32 := BitVec.add x y + +def comb_or (x y : BitVec 1) : BitVec 1 := BitVec.or x y + +/-- + RTL implementation of fork circuit. + We assume that valid signals are given by the stream, + and that ready signals are given by nondeterministic booleans. + -/ +def rtl.fork (_ready _ready_1 _valid : Stream' (BitVec 1)) (_in0 : Stream' (BitVec 32)) + : Stream' ( BitVec 1 -- ready (_12) + × BitVec 1 -- valid_0 (_3) + × BitVec 1 -- valid_1 (_9) + × BitVec 32 -- rawOutput + × BitVec 32 -- rawOutput + ) + := + Stream'.corec' (α := Nat × BitVec 1 × BitVec 1) (fun (i, _emitted_0, _emitted_1) => + let _true := hw_constant true + let _false := hw_constant false + let _2 := comb_xor _emitted_0 _true + let _3 := comb_and _2 (_valid i) + let _4 := comb_and (_ready i) _3 + let _5 := comb_or _4 _emitted_0 -- done0 + let _8 := comb_xor _emitted_1 _true + let _9 := comb_and _8 (_valid i) + let _10 := comb_and (_ready_1 i) _9 + let _11 := comb_or _10 _emitted_1 -- done1 + let _12 := comb_and _5 _11 -- allDone + let _rawOutput := _in0 i + let _0 := comb_xor _12 _true + let _1 := comb_and _5 _0 + let _6 := comb_xor _12 _true + let _7 := comb_and _11 _6 + ((_12, _3, _9, _rawOutput, _rawOutput), (i + 1, _1, _7)) + ) (0, 0#1, 0#1) + +def split_stream2 : + Stream' (a × b × c × d × e) → Stream' a × Stream' b × Stream' c × Stream' d × Stream' e := + fun g => + (fun i => (g i).1, + fun i => (g i).2.1, + fun i => (g i).2.2.1, + fun i => (g i).2.2.2.1, + fun i => (g i).2.2.2.2) + + +/-- At the handshake level: (manual) delayed fork ~ normal fork: the outputs of the fork are bisimilar + for any delay (up to any numbers of `none` inserted, anywhere). -/ +theorem fork_refines {a x y x' y'} : + (x, y) = handshake.fork a → + x ~ x' → + y ~ y' → + x ~ x' ∧ y ~ y' := by grind + +/-- Stream := Stream' (Option α) -/ +def toStream {α} (rdy : Stream' (BitVec 1)) (vld : Stream' (BitVec 1)) (data : Stream' α) : Stream α := fun i => + if rdy i == 1#1 && vld i == 1#1 then + .some (data i) + else + .none + +/- the standard implementation of the fork refines the handshake fork (`TRY2.hw_fork`) -/ + +/-- weaker def where we do not assume that rdy is by default 0#1 -/ +def globallyValidUntilReady (vld rdy : Stream' (BitVec 1)) : Prop := + ∀ (i : Nat), + (vld i = 1#1) → + ∃ (k : Nat), + rdy (i + k) = 1#1 ∧ vld (i + k) = 1#1 ∧ + ∀ (j : Nat) (_hj : j < k), + vld (i + j) = 1#1 + +/-- This def is stronger than the one above -/ +def globallyValidUntilReady' (vld rdy : Stream' (BitVec 1)) : Prop := + ∀ (i : Nat), + (vld i = 1#1) → + ∃ (k : Nat), + rdy (i + k) = 1#1 ∧ vld (i + k) = 1#1 ∧ + ∀ (j : Nat) (_hj : j < k), + vld (i + j) = 1#1 ∧ rdy (i + j) = 0#1 + -- we should add sth like vld (i + k + 1) = 0#1? + +def globallyValidAndData (vld : Stream' (BitVec 1)) (data : Stream' (BitVec w)) : Prop := + ∀ (i : Nat), + (vld i = 1#1 ∧ vld (i + 1) = 1#1) → + data i = data (i + 1) + +def relation : Stream (BitVec w) → Stream (BitVec w) → Prop := fun x y => + ∃ (rd1 vld1 : Stream' (BitVec 1)) (data1 : Stream' (BitVec w)) + (rd2 vld2 : Stream' (BitVec 1)) (data2 : Stream' (BitVec w)), + x = toStream rd1 vld1 data1 ∧ + globallyValidUntilReady rd1 vld1 ∧ + globallyValidAndData vld1 data1 ∧ + y = toStream rd2 vld2 data2 ∧ + globallyValidUntilReady rd2 vld2 ∧ + globallyValidAndData vld2 data2 + /- we need to say something about `x` and `y`. -/ + +/-- G(F(val = 1))-/ +def globallyFinallyReady (x : Stream' (BitVec 1)) := + ∀ (i : Nat), + ∃ (k : Nat), + x (i + k) = 1#1 + +inductive relation' : Stream (BitVec w) → Stream (BitVec w) → Prop where + | intro x y rd vld data rd1 vld1 o1 : /- same as `∀ x y` -/ + /- x is the high-level (input), y is the low-level (output) -/ + x = toStream rd vld data → + y = toStream rd1 vld1 o1 → + (∀ j, (rd j = 1#1 ∧ vld j = 1#1) ↔ rd1 j = 1#1 ∧ vld1 j = 1#1) → + -- (∃ k, rd k = 1#1 ∧ vld k = 1) → /- at least one transition happens frfr -/ + globallyValidUntilReady vld rd → + globallyValidAndData vld data → + globallyFinallyReady rd1 → + (∀ n, vld n = 1#1 → data n = o1 n) → /- when the signal is valid, data and output are the same -/ + relation' x y /- defining the type of the relation -/ + +inductive relation_fork : Stream (BitVec w) → Stream (BitVec w) → Prop where + | intro x y rdIn vldIn dataIn rdOut1 vldOut1 dataOut1 rdOut2 vldOut2 dataOut2 : /- same as `∀ x y` -/ + /- x is the high-level (input), y is the low-level (output) -/ + x = toStream rdIn vldIn dataIn → + y = toStream rdOut1 vldOut1 dataOut1 → + /- if a signal in `x` is valid (`vldIn i = 1#1`), it will remain valid (at least) until a + ready signal is received (`rdIn (i + k) = 1#1`). A ready signal is eventually definitely received. -/ + globallyValidUntilReady vldIn rdIn → + globallyValidUntilReady vldOut1 rdOut1 → + globallyValidUntilReady vldOut2 rdOut2 → + /- if a signal in `x` is valid for more than one cycle (`vldIn i = 1#1 ∧ vldIn (i + 1) = 1#1`), + the data does not change (`dataIn i = dataIn (i + 1)`) -/ + globallyValidAndData vldIn dataIn → + /- eventually a ready signal arrives from both receivers (`rdOut1 i = 1#1`), (`rdOut2 i = 1#1`) -/ + globallyFinallyReady rdOut1 → + globallyFinallyReady rdOut2 → + /- input/output relationship around the `fork` module -/ + + (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn) → + relation_fork x y + + +/- + our implementation of `fork` should not allow this, assuming that the input is + well-formed (including its ready signals!). + + val1 = 1 1 1 + data1 = 2 3 4 + rd1 = 1 1 1 + out1: 2 3 4 + + val2 = 1 1 1 + data2 = 2 3 4 + rd2 = 0 1 1 + out2: - 3 4 + +-/ + + +/-- We unfold one step of the corecursive definition of `fork` -/ +def fork_corec (_ready _ready_1 _valid : Stream' (BitVec 1)) (_in0 : Stream' (BitVec 32)) := + fun (i, _emitted_0, _emitted_1) => + let _true := hw_constant true + let _false := hw_constant false + let _2 := comb_xor _emitted_0 _true + let _3 := comb_and _2 (_valid i) + let _4 := comb_and (_ready i) _3 + let _5 := comb_or _4 _emitted_0 -- done0 + let _8 := comb_xor _emitted_1 _true + let _9 := comb_and _8 (_valid i) + let _10 := comb_and (_ready_1 i) _9 + let _11 := comb_or _10 _emitted_1 -- done1 + let _12 := comb_and _5 _11 -- allDone + let _rawOutput := _in0 i + let _0 := comb_xor _12 _true + let _1 := comb_and _5 _0 + let _6 := comb_xor _12 _true + let _7 := comb_and _11 _6 + ((_12, _3, _9, _rawOutput, _rawOutput), (i+1, _1, _7)) + +/-- We re-define the fork circuit in terms of `fork_corec` -/ +def hw_fork' (_ready _ready_1 _valid : Stream' (BitVec 1)) (_in0 : Stream' (BitVec 32)) + : Stream' ( BitVec 1 -- ready (_12) + × BitVec 1 -- valid_0 (_3) + × BitVec 1 -- valid_1 (_9) + × BitVec 32 -- rawOutput + × BitVec 32 -- rawOutput + ) + := Stream'.corec' (α := Nat × BitVec 1 × BitVec 1) (fork_corec _ready _ready_1 _valid _in0) (0, 0#1, 0#1) + + + + +/-- Prove that iterating `n` times starting from the `m`-th index of the stream yields the `n + m`-th index-/ +theorem fork_corec1 : + (Stream'.iterate (Prod.snd ∘ fork_corec rd0_in rd1_in vld_in data_in) (m, x, y) n).1 = n + m := by + induction n generalizing m x y with + | zero => grind [Stream'.iterate] + | succ x h => + rw [Stream'.iterate_eq] + dsimp [Stream'.cons] + dsimp [fork_corec] + grind + +theorem hw_fork'_vldOut1_of_none (h : ∀ k, vldIn k = 0#1) : + ((hw_fork' rdOut1 rdOut2 vldIn dataIn) k).2.1 = 0#1 := by + unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get + generalize hst : Stream'.iterate + (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) k = s + obtain ⟨a, b, c⟩ := s + dsimp [fork_corec, comb_and, comb_xor, hw_constant] + specialize h a + simp [h] + +theorem hw_fork'_vldOut2_of_none (h : ∀ k, vldIn k = 0#1) : + ((hw_fork' rdOut1 rdOut2 vldIn dataIn) k).2.2.1 = 0#1 := by + unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get + generalize hst : Stream'.iterate + (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) k = s + obtain ⟨a, b, c⟩ := s + dsimp [fork_corec, comb_and, comb_xor, hw_constant] + specialize h a + simp [h] + +lemma iterate_back_succ (f : α → α) (s : α) (n : ℕ) : + Stream'.iterate f s (n + 1) = f (Stream'.iterate f s n) := by + induction n generalizing s with + | zero => simp [Stream'.iterate_eq, Stream'.cons] + | succ k ih => rw [Stream'.iterate_eq, Stream'.cons, ih]; rfl + +lemma fork_emitted_zero_of_all_none (h : ∀ k, vldIn k = 0#1) : + ∀ k, (Stream'.iterate (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) + (0, 0#1, 0#1) k).2 = (0#1, 0#1) := by + intro k + induction k with + | zero => simp [Stream'.iterate] + | succ k ih => + rw [iterate_back_succ] + generalize hsk : Stream'.iterate + (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) k = s + obtain ⟨a, b, c⟩ := s + simp [hsk] at ih + obtain ⟨rfl, rfl⟩ := ih + simp only [Function.comp] + dsimp [fork_corec, comb_and, comb_xor, comb_or, hw_constant] + simp [h a] + +-- when vld is always 0, all signal outputs (not data) are 0 +theorem hw_fork'_of_all_none (h : ∀ k, vldIn k = 0#1) : + ∀ k, ((hw_fork' rdOut1 rdOut2 vldIn dataIn) k).1 = 0#1 ∧ + ((hw_fork' rdOut1 rdOut2 vldIn dataIn) k).2.1 = 0#1 ∧ + ((hw_fork' rdOut1 rdOut2 vldIn dataIn) k).2.2.1 = 0#1 := by + unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get + intro k + and_intros + · generalize hst : Stream'.iterate + (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) k = s + obtain ⟨a, b, c⟩ := s + dsimp [fork_corec, comb_and, comb_xor, hw_constant] + have hbc := fork_emitted_zero_of_all_none (dataIn := dataIn) (rdOut1 := rdOut1) + (rdOut2 := rdOut2) h k + rw [hst] at hbc + simp at hbc + obtain ⟨rfl, rfl⟩ := hbc + simp [h a, comb_or] + · generalize hst : Stream'.iterate + (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) k = s + obtain ⟨a, b, c⟩ := s + dsimp [fork_corec, comb_and, comb_xor, hw_constant] + specialize h a + simp [h] + · generalize hst : Stream'.iterate + (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) k = s + obtain ⟨a, b, c⟩ := s + dsimp [fork_corec, comb_and, comb_xor, hw_constant] + specialize h a + simp [h] + +/-- Prove that (at RTL level) the input and output data at the `n`-th position are the same. + This is possible because `hw_fork'` does not introduce any delay, and there is no transformation + happening on the data. -/ +theorem hw_fork_out0 + (h : ⟨rdy_out, vld0_out, vld1_out, data0_out, data1_out⟩ = split_stream2 (hw_fork' rd0_in rd1_in vld_in data_in)) : + (∀ n, data_in n = data0_out n) := by + intro n + simp [split_stream2] at h + simp [h] + unfold hw_fork'; clear h + unfold Stream'.corec' Stream'.corec Stream'.map Stream'.get + generalize h: (Stream'.iterate (Prod.snd ∘ fork_corec rd0_in rd1_in vld_in data_in) (0, 0#1, 0#1) n) = y + obtain ⟨a, b, c⟩ := y + dsimp [fork_corec] + rw [show a = (a, b, c).1 by rfl, ←h, fork_corec1]; rfl + +theorem hw_fork_out1 + (h : ⟨rdy_out, vld0_out, vld1_out, data0_out, data1_out⟩ = + split_stream2 (hw_fork' rd0_in rd1_in vld_in data_in)) : + (∀ n, data_in n = data1_out n) := by + intro n + simp [split_stream2] at h + simp [h] + unfold hw_fork'; clear h + unfold Stream'.corec' Stream'.corec Stream'.map Stream'.get + generalize h: (Stream'.iterate (Prod.snd ∘ fork_corec rd0_in rd1_in vld_in data_in) (0, 0#1, 0#1) n) = y + obtain ⟨a, b, c⟩ := y + dsimp [fork_corec] + rw [show a = (a, b, c).1 by rfl, ←h, fork_corec1]; rfl + + + + +theorem fork_corec1bis : + (Stream'.iterate (Prod.snd ∘ fork_corec rd0_in rd1_in vld_in data_in) (m, x, y) n).1 = n + m := by + induction n generalizing m x y with + | zero => grind [Stream'.iterate] + | succ x h => + rw [Stream'.iterate_eq] + dsimp [Stream'.cons] + dsimp [fork_corec] + grind + +theorem hw_fork_eq : rtl.fork rd0 rd1 vld data = hw_fork' rd0 rd1 vld data := by + unfold rtl.fork hw_fork' + congr 1 + +theorem vldOut1_implies_vldIn + (h : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = + split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) + (hvld : vldOut1 n = 1#1) : vldIn n = 1#1 := by + rw [hw_fork_eq] at h + simp [split_stream2] at h + obtain ⟨-, hvldout1, -⟩ := h + have hn := congr_fun hvldout1 n + rw [hvld] at hn + unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn + generalize hst : Stream'.iterate + (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) n = s at hn + obtain ⟨a, b, c⟩ := s + dsimp [fork_corec, comb_and, comb_xor, hw_constant] at hn + have heq : a = n := by + have := @fork_corec1 rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 n + rw [hst] at this + simp at this + assumption + rw [← heq] + apply Classical.byContradiction + intro hcontra + have : vldIn a = 0#1 := by grind + simp [this] at hn + +theorem vldOut2_implies_vldIn + (h : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = + split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) + (hvld : vldOut2 n = 1#1) : vldIn n = 1#1 := by + rw [hw_fork_eq] at h + simp [split_stream2] at h + obtain ⟨-, -, hvldout2, -⟩ := h + have hn := congr_fun hvldout2 n + rw [hvld] at hn + unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn + generalize hst : Stream'.iterate + (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) n = s at hn + obtain ⟨a, b, c⟩ := s + dsimp [fork_corec, comb_and, comb_xor, hw_constant] at hn + have heq : a = n := by + have := @fork_corec1 rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 n + rw [hst] at this + simp at this + assumption + rw [← heq] + apply Classical.byContradiction + intro hcontra + have : vldIn a = 0#1 := by grind + simp [this] at hn + +theorem rdOut1_before_allDone + (hfork : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = + split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) (hvldOut1 : vldOut1 n = 1#1) + (hgvurIn : globallyValidUntilReady vldIn rdIn) : + ∃ k, rdIn (n + k) = 1#1 ∧ vldIn (n + k) = 1#1 := by + have hvldIn := vldOut1_implies_vldIn hfork hvldOut1 + unfold globallyValidUntilReady at hgvurIn + specialize hgvurIn n hvldIn + obtain ⟨k, hk⟩ := hgvurIn + exists k + simp [hk] + +lemma iterate_succ_apply (f : α → α) (s : α) (n : ℕ) : + Stream'.iterate f s (n + 1) = f (Stream'.iterate f s n) := by + induction n generalizing s with + | zero => simp [Stream'.iterate] + | succ k ih => + rw [Stream'.iterate_eq, Stream'.cons] + exact ih _ + + + +theorem vldOut_eq_vldIn_of_fork_unitl_sent + (hfork : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = + split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) + /- nothing is emitted before `n`, as emission occurs if `rdOut1 j ∧ vldOut1 j` -/ + (hbefore : ∀ j < n, rdOut1 j = 0#1 ∨ vldOut1 j = 0#1) : + vldOut1 n = vldIn n := by + rw [hw_fork_eq] at hfork + simp [split_stream2] at hfork + obtain ⟨-, hvldout1, -⟩ := hfork + have hn := congr_fun hvldout1 n + unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn + generalize hst : Stream'.iterate + (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) n = s at hn + obtain ⟨a, b, c⟩ := s + dsimp [fork_corec, comb_and, comb_xor, hw_constant] at hn + have hb : b = 0#1 := by + apply Classical.byContradiction + intro hcontra + have : b = 1#1 := by grind + subst this + simp at hn + suffices key : ∀ m, (∀ j < m, rdOut1 j = 0#1 ∨ vldOut1 j = 0#1) → + (Stream'.iterate (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) m).2.1 = 0#1 by + have := key n hbefore + rw [hst] at this + simp at this + intro m + induction m with + | zero => simp [Stream'.iterate] + | succ k ihk => + intro hbef + have hbk := ihk (fun j hj => hbef j (Nat.lt_succ_of_lt hj)) + generalize hsk : Stream'.iterate + (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) k = sk + obtain ⟨ak, bk, ck⟩ := sk + simp [hsk] at hbk; subst hbk + rw [iterate_back_succ, hsk] + have hak : ak = k := by + have := @fork_corec1 rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 k + simp [hsk] at this; omega + have hk := hbef k (Nat.lt_succ_self k) + simp only [Function.comp] + have hvldk : vldOut1 k = vldIn ak := by + have h := congr_fun hvldout1 k + unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at h + simp_rw [hsk] at h + dsimp [fork_corec, comb_and, comb_xor, hw_constant] at h + simp_all + ext k hk + simp [show k = 0 by omega] + dsimp [fork_corec, comb_and, comb_xor, comb_or, hw_constant] + subst hak + by_cases hrd : rdOut1 ak = 1#1 <;> by_cases hvld : vldIn ak = 1#1 <;> by_cases hck : ck = 1#1 <;> by_cases hrd2 : rdOut2 ak = 1#1 + · simp [hrd, hvld, hck] + · simp [hrd, hvld, hck] + · have h0 : ck = 0#1 := by grind + simp [hrd, hvld, h0, hrd2] + · have h0 : ck = 0#1 := by grind + have h1 : rdOut2 ak = 0#1 := by grind + simp [hrd] at hk + simp_all + · have h0 : vldIn ak = 0#1 := by grind + simp [hrd, h0, hrd2] + · have h0 : vldIn ak = 0#1 := by grind + have h1 : rdOut2 ak = 0#1 := by grind + simp [hrd, h0, h1] + · have h0 : vldIn ak = 0#1 := by grind + simp [hrd, h0] + · simp [hrd] at hk + simp_all + · have h1 : rdOut1 ak = 0#1 := by grind + simp [h1, hvld, hck] + · have h1 : rdOut1 ak = 0#1 := by grind + simp [hvld, hck, h1] + · have h1 : rdOut1 ak = 0#1 := by grind + simp [hvld, h1] + · have h1 : rdOut1 ak = 0#1 := by grind + simp [h1, hvld] + · have h1 : rdOut1 ak = 0#1 := by grind + simp [h1, hck] + · have h1 : rdOut1 ak = 0#1 := by grind + simp [h1, hck] + · have h1 : rdOut1 ak = 0#1 := by grind + simp [h1] + · have h1 : rdOut1 ak = 0#1 := by grind + simp [h1] + simp [hb] at hn + have heq : a = n := by + have := @fork_corec1 rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 n + rw [hst] at this + simp at this + assumption + rw [← heq] at ⊢ hn + simp [hn] + ext k hk + simp [show k = 0 by omega] + +theorem vldOut_of_vldIn_rdy + (hfork : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = + split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) + /- nothing has been accepted so far -/ + (hbefore : ∀ l < j, rdOut1 l = 0#1 ∨ vldOut1 l = 0#1) + (hin : vldIn j = 1#1 ∧ rdIn j = 1#1) : + vldOut1 j = 1#1 := by + rw [vldOut_eq_vldIn_of_fork_unitl_sent (hfork := hfork) (hbefore := hbefore)] + simp [hin] + +theorem vldOut_eq_vldIn_of_fork_unitl_sent2 + (hfork : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = + split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) + /- nothing is emitted before `n`, as emission occurs if `rdOut1 j ∧ vldOut1 j` -/ + (hbefore : ∀ j < n, rdOut2 j = 0#1 ∨ vldOut2 j = 0#1) : + vldOut2 n = vldIn n := by + rw [hw_fork_eq] at hfork + simp [split_stream2] at hfork + obtain ⟨-, -, hvldout2, -⟩ := hfork + have hn := congr_fun hvldout2 n + unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn + generalize hst : Stream'.iterate + (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) n = s at hn + obtain ⟨a, b, c⟩ := s + dsimp [fork_corec, comb_and, comb_xor, hw_constant] at hn + have hc0 : c = 0#1 := by + suffices key : ∀ m, (∀ j < m, rdOut2 j = 0#1 ∨ vldOut2 j = 0#1) → + (Stream'.iterate (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) + (0, 0#1, 0#1) m).2.2 = 0#1 by + have := key n hbefore + rw [hst] at this; simpa using this + intro m + induction m with + | zero => simp [Stream'.iterate] + | succ k ihk => + intro hbef + have hck := ihk (fun j hj => hbef j (Nat.lt_succ_of_lt hj)) + generalize hsk : Stream'.iterate + (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) k = sk + obtain ⟨ak, bk, ck⟩ := sk + simp [hsk] at hck; subst hck + have hak : ak = k := by + have := @fork_corec1 rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 k + grind + have hvldk : vldOut2 k = vldIn ak := by + have h := congr_fun hvldout2 k + unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at h + simp_rw [hsk] at h + dsimp [fork_corec, comb_and, comb_xor, hw_constant] at h + simp_all + ext k hk + simp [show k = 0 by omega] + have hk := hbef k (Nat.lt_succ_self k) + rw [iterate_back_succ, hsk] + simp only [Function.comp] + dsimp [fork_corec, comb_and, comb_xor, comb_or, hw_constant] + rcases hk with h | h + · simp_all + · rw [hvldk] at h + rcases hak ▸ h with h + have hvldInA : vldIn ak = 0#1 := by grind + simp [hvldInA]; + have heq : a = n := by + have := @fork_corec1 rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 n + rw [hst] at this + simp at this + assumption + rw [← heq] at ⊢ hn + simp [hn] + ext k hk + simp [show k = 0 by omega] + intros + simp [hc0] + +theorem data_remains_constant_if + (h : globallyValidAndData vld data) + (h' : globallyValidUntilReady vld rdy) : + ∀ i, vld i = 1#1 → + ∃ k, (rdy (i + k) = 1#1 ∧ vld (i + k) = 1#1 ∧ + (∀ j (_hj : j ≤ k), vld (i + j) = 1#1 )∧ + (∀ j (_hj : j ≤ k), data (i + j) = data i)) := by + unfold globallyValidAndData at h + unfold globallyValidUntilReady at h' + intros i + specialize h' i + by_cases htrue : vld i = 1#1 + · simp [htrue] at h' ⊢ + obtain ⟨k, hk⟩ := h' + exists k + simp [hk] + by_cases hk0 : 0 < k + · and_intros + · intro j hj + obtain ⟨h1, h2, h3⟩ := hk + by_cases hlt : j < k + · apply h3 + exact hlt + · simp [show j = k by omega, h2] + · intros l hl + induction l + · simp + · case _ l' ihl' => + rw [show (i + (l' + 1)) = (i + l') + 1 by omega] + obtain ⟨h1, h2, h3⟩ := hk + by_cases hle : l' + 1 < k + · rw [← ihl' (by omega)] + apply Eq.symm + apply h + simp_all + and_intros + · apply h3 + omega + · rw [show (i + l') + 1 = (i + (l' + 1)) by omega] + apply h3 + assumption + · have : l' + 1 = k := by omega + specialize ihl' (by omega) + rw [← ihl'] + apply Eq.symm + apply h + and_intros + · apply h3 + assumption + · rw [show k = l' + 1 by omega, show (i + (l' + 1)) = (i + l') + 1 by omega] at h2 + assumption + · simp [show k = 0 by omega, htrue] + · simp [show vld i = 0#1 by grind] + + + +theorem not_exists_transmitted_element + (hv : ∀ i, vld i = 0#1) + (hx : x = toStream rdy vld data) : + ∀ k, x k = none := by + unfold toStream at hx + simp at hx + intros k + have hkx := congr_fun hx k + simp [show vld k = 0#1 by grind] at hkx + simp [hkx] + +theorem not_exists_transmitted_element_before + (hv : ∀ i (_ : i < limit), vld i = 0#1) + (hx : x = toStream rdy vld data) : + ∀ k (_ : k < limit), x k = none := by + intros k hk + unfold toStream at hx + simp at hx + have hkx := congr_fun hx k + simp [show vld k = 0#1 by grind] at hkx + simp [hkx] + +theorem if_exists_first_exists {st : Stream' (BitVec 1)} (h : ∃ k , st k = 1#1) : + ∃ j, (st j = 1#1 ∧ ∀ n (_ : n < j), st n = 0#1) := by + suffices key : ∀ k, st k = 1#1 → ∃ j, st j = 1#1 ∧ ∀ n < j, st n = 0#1 by + obtain ⟨k, hk⟩ := h; exact key k hk + intro k + induction k using Nat.strongRecOn with + | _ k ih => + intro hk + by_cases h0 : ∃ m < k, st m = 1#1 + · obtain ⟨m, hm, hms⟩ := h0 + exact ih m hm hms + · refine ⟨k, hk, fun n hn => ?_⟩ + by_contra hc + have hst : st n = 1#1 := by grind + exact h0 ⟨n, hn, hst⟩ + +theorem exists_first_transmitted_element + (hv : ∃ i, vld i = 1#1) + (hgf : globallyValidUntilReady vld rdy) + (hx : x = toStream rdy vld data) : + ∃ k, (x k = some (data k) ∧ ∀ j (_ : j < k), x j = none) := by + obtain ⟨i, hi⟩ := hv + obtain ⟨k, hkr, hkv, -⟩ := hgf i hi + let combined := fun n => if rdy n == 1#1 && vld n == 1#1 then 1#1 else (0#1 : BitVec 1) + have hex : ∃ n, combined n = 1#1 := ⟨i + k, by simp [combined, hkr, hkv]⟩ + obtain ⟨j, hjfire, hjmin⟩ := if_exists_first_exists hex + refine ⟨j, ?_, ?_⟩ + · simp [combined] at hjfire + rw [hx, toStream] + simp [hjfire.1, hjfire.2] + · intro l hl + rw [hx, toStream] + have h0 := hjmin l hl + simp [combined] at h0 + grind + +theorem exists_first_received_element + (hv : ∃ i, rdy i = 1#1 ∧ vld i = 1#1) + (hx : x = toStream rdy vld data) : + ∃ k, (x k = some (data k) ∧ ∀ j (_ : j < k), x j = none) := by + obtain ⟨fst, hfst_fire, hfst_min⟩ := if_exists_first_exists + (st := fun n => if ((rdy n == 1#1) && (vld n == 1#1)) then 1#1 else 0#1) + (by + obtain ⟨k, hk⟩ := hv + exists k + simp [hk]) + refine ⟨fst, ?_, ?_⟩ + · rw [hx, toStream] + have : ((rdy fst == 1#1) && (vld fst == 1#1))= true := by + by_contra hc; simp [hc] at hfst_fire + simp only [Bool.and_eq_true, beq_iff_eq] at this + simp [this.1, this.2] + · intro j hj + rw [hx, toStream] + have hj_not := hfst_min j hj + by_cases hrdy : rdy j == 1#1 && vld j == 1#1 + · simp [hrdy] at hj_not + · simp only [Bool.and_eq_true, beq_iff_eq, not_and] at hrdy + by_cases hr : rdy j = 1#1 + · have hvj := hrdy (by simpa using hr) + simp [show (rdy j == 1#1) = true by simpa, show (vld j == 1#1) = false by simpa] + · simp [show (rdy j == 1#1) = false by simpa] + + +theorem exists_transmitted_element + (h : globallyValidUntilReady vld rdy) + (hx : x = toStream rdy vld data) : + ∃ k, x k = some (data k) ∨ ∀ k, x k = none := by + by_cases hexists : ∃ i, vld i = 1#1 + · unfold toStream at hx + unfold globallyValidUntilReady at h + obtain ⟨i, hi⟩ := hexists + specialize h i (by omega) + obtain ⟨k, hk1, hk2, hk3⟩ := h + exists (i + k) + have hkx := congr_fun hx (i + k) + simp [hk1, hk2] at hkx + simp [hkx] + · simp [not_exists_transmitted_element (x := x) (data := data) (rdy := rdy) (vld := vld) (by grind) hx] + +theorem false_of_width_one (b : BitVec 1) (h : ¬ b = 1#1 ) : b = 0#1 := by grind + +theorem true_of_width_one (b : BitVec 1) (h : ¬ b = 0#1 ) : b = 1#1 := by grind + +theorem vldIn_and_eventually_ready_implies_vldOut1 + (hfork : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = + split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) + (hvldIn : globallyFinallyReady vldIn) : + ∃ k, vldOut1 k = 1#1 := by + obtain ⟨n, hvldn, hnmin⟩ := if_exists_first_exists (hvldIn 0 |>.imp (fun k hk => by simpa using hk)) + have hbefore : ∀ j < n, rdOut1 j = 0#1 ∨ vldOut1 j = 0#1 := by + intro j hj + right + have hvldj : vldIn j = 0#1 := hnmin j hj + by_contra hc + have : vldIn j = 1#1 := vldOut1_implies_vldIn hfork (by grind) + rw [this] at hvldj + simp at hvldj + exact ⟨n, vldOut_eq_vldIn_of_fork_unitl_sent hfork hbefore |>.symm ▸ hvldn⟩ + +theorem vldIn_and_ready_implies_vldOut1 + (hfork : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = + split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) + (hvldIn : ∃ j, vldIn j = 1#1) : + ∃ k, vldOut1 k = 1#1 := by + obtain ⟨n, hvldn, hnmin⟩ := if_exists_first_exists (st := vldIn) (by grind) + have hbefore : ∀ j < n, rdOut1 j = 0#1 ∨ vldOut1 j = 0#1 := by + intro j hj + right + have hvldj : vldIn j = 0#1 := hnmin j hj + by_contra hc + have : vldIn j = 1#1 := vldOut1_implies_vldIn hfork (by grind) + rw [this] at hvldj + simp at hvldj + exact ⟨n, vldOut_eq_vldIn_of_fork_unitl_sent hfork hbefore |>.symm ▸ hvldn⟩ + +theorem vldIn_and_ready_implies_vldOut2 + (hfork : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = + split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) + (hvldIn : ∃ j, vldIn j = 1#1) : + ∃ k, vldOut2 k = 1#1 := by + obtain ⟨n, hvldn, hnmin⟩ := if_exists_first_exists (st := vldIn) (by grind) + have hbefore : ∀ j < n, rdOut2 j = 0#1 ∨ vldOut2 j = 0#1 := by + intro j hj + right + have hvldj : vldIn j = 0#1 := hnmin j hj + by_contra hc + have : vldIn j = 1#1 := vldOut2_implies_vldIn hfork (by grind) + rw [this] at hvldj + simp at hvldj + exact ⟨n, vldOut_eq_vldIn_of_fork_unitl_sent2 hfork hbefore |>.symm ▸ hvldn⟩ + +lemma fork_globallyValidAndData_out1 + (hfork : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = + split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) + (hgv : globallyValidAndData vldIn dataIn) : + globallyValidAndData vldOut1 dataOut1 := by + intro i ⟨hi1, hi2⟩ + have hdata := hw_fork_out0 hfork + rw [← hdata i, ← hdata (i+1)] + apply hgv + exact ⟨vldOut1_implies_vldIn hfork hi1, vldOut1_implies_vldIn hfork hi2⟩ + + +lemma globallyValidAndData_stable (hgv : globallyValidAndData vld data) + (hrange : ∀ j, m ≤ j → j ≤ n → vld j = 1#1) (h : m ≤ n) : + data m = data n := by + induction h with + | refl => rfl + | step h ih => + rw [ih (fun j hj1 hj2 => hrange j hj1 (Nat.le_succ_of_le hj2))] + apply hgv + exact ⟨hrange _ (by omega) (by omega), + hrange _ (Nat.le_succ_of_le h) (Nat.le_refl _)⟩ + +theorem data_remains_constant_until_first + (h : globallyValidAndData vld data) + (h' : globallyValidUntilReady vld rdy) + (hi : vld i = 1#1) : + ∃ k, rdy (i + k) = 1#1 ∧ vld (i + k) = 1#1 ∧ + (∀ j (_hj : j ≤ k), vld (i + j) = 1#1) ∧ + (∀ j (_hj : j ≤ k), data (i + j) = data i) ∧ + (∀ m (_hm : m < k), rdy (i + m) = 0#1) := by + -- get any witness first + obtain ⟨k, hkrd, hkvld, hkvldall, hkdata⟩ := data_remains_constant_if h h' i hi + -- find the minimum via if_exists_first_exists + obtain ⟨kMin, hkMin_fire, hkMin_min⟩ := if_exists_first_exists + (st := fun m => if rdy (i + m) == 1#1 && vld (i + m) == 1#1 then 1#1 else 0#1) + ⟨k, by simp [hkrd, hkvld]⟩ + simp only [ite_eq_left_iff, Bool.and_eq_true, beq_iff_eq, not_and] at hkMin_fire hkMin_min + -- extract rdy and vld at kMin + have hkMinrd : rdy (i + kMin) = 1#1 := by + by_contra hc + simp [show rdy (i + kMin) ≠ 1#1 from hc] at hkMin_fire + have hkMinvld : vld (i + kMin) = 1#1 := by + by_contra hc + grind + -- kMin ≤ k + have hkMinlek : kMin ≤ k := by + by_contra hlt; push_neg at hlt + have := hkMin_min k hlt + simp [hkrd, hkvld] at this + refine ⟨kMin, hkMinrd, hkMinvld, ?_, ?_, ?_⟩ + · -- vld stays 1 for j ≤ kMin + intro j hj + exact hkvldall j (by omega) + · -- data stays constant for j ≤ kMin + intro j hj + exact hkdata j (by omega) + · -- rdy = 0 before kMin + intro m hm + by_contra hc + have hrdm : rdy (i + m) = 1#1 := by grind + -- vld (i + m) = 1 since m < kMin ≤ k + have hvldm : vld (i + m) = 1#1 := hkvldall m (by omega) + have := hkMin_min m hm + simp [hrdm, hvldm] at this + + +def readyOut1UntilAllReceiversAre(rdOut1 rdOut2 : Stream' (BitVec 1)) := + ∀ i, + rdOut1 i = 1#1 → + ∀ j, rdOut2 (i + j) = 0#1 → rdOut1 (i + j) = 1#1 + +def readyOut2UntilAllReceiversAre (rdOut1 rdOut2 : Stream' (BitVec 1)) := + ∀ i, + rdOut2 i = 1#1 → + ∀ j, rdOut1 (i + j) = 0#1 → rdOut2 (i + j) = 1#1 + +/-- the standard implementation of the fork refines the handshake fork (`TRY2.hw_fork`) -/ +theorem hw_fork_refines1_with_fork: + /- Given a handshake fork taking `a` as input and returning `(a, a)`, we take + its lowering (with input a bisimilar ready-valid wrapped stream) -/ + (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn) → + /- We want to make sure that stalling is correctly modeled for `a` (input). + We constrain the input and prove that if the input behaves properly, + the output will. -/ + globallyValidUntilReady vldOut1 rdOut1 → + globallyValidUntilReady vldOut2 rdOut2 → + globallyValidUntilReady vldIn rdIn → + readyOut1UntilAllReceiversAre (rdOut1 := rdOut1) (rdOut2 := rdOut2) → + readyOut2UntilAllReceiversAre (rdOut1 := rdOut1) (rdOut2 := rdOut2) → + globallyValidAndData vldOut1 dataOut1 → + globallyValidAndData vldOut2 dataOut2 → + globallyValidAndData vldIn dataIn → + /- we assume no deadlock -/ + globallyFinallyReady rdIn → + globallyFinallyReady rdOut1 → + globallyFinallyReady rdOut2 → + /- if we know that the hshake input stream is bisimilar to the ready-valid input of the hw fork (`a ~ rdy vld i`), meaning that the two outputs are also bisimilar by transitivity-/ + /- we want to prove that the outputs of the handshake fork are respectively + bisimilar to the ready-valid wrapping of the output of the hardware fork -/ + (toStream rdIn vldIn dataIn) ~ (toStream rdOut1 vldOut1 dataOut1) := by + intros hfork hgvurOutt1 hvgurOut2 hgvurIn hout1 hout2 hgvdOut1 hgvdOut2 hgvdIn hgfrIn hgfrOut1 hgfrOut2 + /- if 0, 0 works we don't need bisimilarity -/ + /- the high-level fork will never wait for anything (whenever an input is available), + while the low-level one might have to, and depends on the `rd1` signal eventually being true. + if we choose `pred := Eq` the relation is too strong, the second goal is not provable. + -/ + apply Bisim.coinduct (pred := relation_fork) + · intros sin sout hrel + /- `sin` and `sout` exist at the handshake level of the design -/ + rcases hrel + expose_names + by_cases hvldExists : ∃ k, vldIn_1 k = 1#1 + · have := if_exists_first_exists hvldExists + obtain ⟨fstVldTrue, hfstVldTrue1, hfstVldTrue2⟩ := this + /- we need to find the first element that is transmitted -/ + have hfstSent := exists_first_transmitted_element + (data := dataIn_1) (vld := vldIn_1) (rdy := rdIn_1) (x := sin) + (by grind) (by assumption) (by assumption) + have ⟨fstRdyOut, hfstRdyOut⟩ := if_exists_first_exists (h_4 fstVldTrue) + have ⟨fstRdyOut2, hfstRdyOut2⟩ := if_exists_first_exists (h_5 fstVldTrue) + unfold globallyFinallyReady at h_4 + have hvldinout := vldIn_and_ready_implies_vldOut1 + (dataIn := dataIn_1) (vldIn := vldIn_1) (rdIn := rdIn_1) + (rdOut1 := rdOut1_1) (rdOut2 := rdOut2_1) (vldOut1 := vldOut1_1) (vldOut2 := vldOut2_1) + (dataOut1 := dataOut1_1) (dataOut2 := dataOut2_1) (by grind) (by grind) + have hvldinout2 := vldIn_and_ready_implies_vldOut2 + (dataIn := dataIn_1) (vldIn := vldIn_1) (rdIn := rdIn_1) + (rdOut1 := rdOut1_1) (rdOut2 := rdOut2_1) (vldOut1 := vldOut1_1) (vldOut2 := vldOut2_1) + (dataOut1 := dataOut1_1) (dataOut2 := dataOut2_1) (by grind) (by grind) + have hfstRec := exists_first_received_element + (data := dataOut1_1) (vld := vldOut1_1) (rdy := rdOut1_1) (x := sout) (hx := h_8) + have ⟨fstSentIdx, hfstSentIdx⟩ := hfstSent + exists fstSentIdx, (fstVldTrue + fstRdyOut) + and_intros + · apply relation_fork.intro + (Stream'.drop (fstSentIdx + 1) sin) (Stream'.drop (fstVldTrue + fstRdyOut + 1) sout) + (dataIn := Stream'.drop (fstSentIdx + 1) dataIn_1) + (rdIn := Stream'.drop (fstSentIdx + 1) rdIn_1) + (vldIn := Stream'.drop (fstSentIdx + 1) vldIn_1) + (vldOut1 := Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut1_1) + (vldOut2 := Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut2_1) + (dataOut1 := Stream'.drop (fstVldTrue + fstRdyOut + 1) dataOut1_1) + (dataOut2 := Stream'.drop (fstSentIdx + 1) dataOut2_1) + (rdOut1 := Stream'.drop (fstVldTrue + fstRdyOut + 1) rdOut1_1) + (rdOut2 := Stream'.drop (fstVldTrue + fstRdyOut + 1) rdOut2_1) + · simp_all + rfl + · simp_all + rfl + · unfold globallyValidUntilReady at ⊢ h + intro j hj + specialize h (j + fstSentIdx + 1) hj + obtain ⟨k, hk1, hk2, hk3⟩ := h + exists k + have hv : Stream'.drop (fstSentIdx + 1) vldIn_1 j = vldIn_1 (j + fstSentIdx + 1) := by rfl + rw [hv] at hj + have hv : Stream'.drop (fstSentIdx + 1) vldIn_1 (j + k) = vldIn_1 (j + k + fstSentIdx + 1) := by rfl + have hr : Stream'.drop (fstSentIdx + 1) rdIn_1 (j + k) = rdIn_1 (j + k + fstSentIdx + 1) := by rfl + simp [hv, hr, show j + k + fstSentIdx + 1 = j + fstSentIdx + 1 + k by omega, hk1, hk2] + intros n hn + have hn : Stream'.drop (fstSentIdx + 1) vldIn_1 (j + n) = vldIn_1 (j + n + fstSentIdx + 1) := by rfl + simp [hn] + specialize hk3 n (by omega) + simp [show j + n + fstSentIdx + 1 = j + fstSentIdx + 1 + n by omega, hk3] + · unfold globallyValidUntilReady at ⊢ h_1 + intro j hj + have hj2 : Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut1_1 j = vldOut1_1 (j + fstVldTrue + fstRdyOut + 1) := by + simp [Stream'.drop, Stream'.get] + congr 1 + omega + rw [hj2] at hj + specialize h_1 (j + fstVldTrue + fstRdyOut + 1) hj + obtain ⟨k, hk1, hk2, hk3⟩ := h_1 + exists k + have hv : Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut1_1 (j + k) = vldOut1_1 (j + k + fstVldTrue + fstRdyOut + 1) := by + simp [Stream'.drop, Stream'.get] + congr 1 + omega + have hr : Stream'.drop (fstVldTrue + fstRdyOut + 1) rdOut1_1 (j + k) = rdOut1_1 (j + k + fstVldTrue + fstRdyOut + 1) := by + simp [Stream'.drop, Stream'.get] + congr 1 + omega + simp [hv, hr, show j + k + fstVldTrue + fstRdyOut + 1 = j + fstVldTrue + fstRdyOut + 1 + k by omega, hk1, hk2] + intros n hn + have hn : Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut1_1 (j + n) = vldOut1_1 (j + n + fstVldTrue + fstRdyOut + 1) := by + simp [Stream'.drop, Stream'.get] + congr 1 + omega + simp [hn] + specialize hk3 n (by omega) + simp [show j + n + fstVldTrue + fstRdyOut + 1 = j + fstVldTrue + fstRdyOut + 1 + n by omega, hk3] + · unfold globallyValidUntilReady at ⊢ h_2 + intro j hj + have hj2 : Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut2_1 j = vldOut2_1 (j + fstVldTrue + fstRdyOut + 1) := by + simp [Stream'.drop, Stream'.get] + congr 1 + omega + rw [hj2] at hj + specialize h_2 (j + fstVldTrue + fstRdyOut + 1) hj + obtain ⟨k, hk1, hk2, hk3⟩ := h_2 + exists k + have hv : Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut2_1 (j + k) = vldOut2_1 (j + k + fstVldTrue + fstRdyOut + 1) := by + simp [Stream'.drop, Stream'.get] + congr 1 + omega + have hr : Stream'.drop (fstVldTrue + fstRdyOut + 1) rdOut2_1 (j + k) = rdOut2_1 (j + k + fstVldTrue + fstRdyOut + 1) := by + simp [Stream'.drop, Stream'.get] + congr 1 + omega + simp [hv, hr, show j + k + fstVldTrue + fstRdyOut + 1 = j + fstVldTrue + fstRdyOut + 1 + k by omega, hk1, hk2] + intros n hn + have hn : Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut2_1 (j + n) = vldOut2_1 (j + n + fstVldTrue + fstRdyOut + 1) := by + simp [Stream'.drop, Stream'.get] + congr 1 + omega + simp [hn] + specialize hk3 n (by omega) + simp [show j + n + fstVldTrue + fstRdyOut + 1 = j + fstVldTrue + fstRdyOut + 1 + n by omega, hk3] + · unfold globallyValidAndData at ⊢ h_3 + intro j + specialize h_3 (j + fstSentIdx + 1) + have hr : Stream'.drop (fstSentIdx + 1) dataIn_1 j = dataIn_1 (j + fstSentIdx + 1) := by rfl + have hr' : Stream'.drop (fstSentIdx + 1) dataIn_1 (j + 1) = dataIn_1 (j + 1 + fstSentIdx + 1) := by rfl + simp [hr, hr'] + simp [show j + 1 + fstSentIdx + 1 = j + fstSentIdx + 1 + 1 by omega] + intro h1 h2 + apply h_3 + have htmp : Stream'.drop (fstSentIdx + 1) vldIn_1 j = vldIn_1 (j + fstSentIdx + 1) := by rfl + rw [htmp] at h1 + simp [h1] + have htmp : Stream'.drop (fstSentIdx + 1) vldIn_1 (j + 1) = vldIn_1 (j + 1 + fstSentIdx + 1) := by rfl + simp [show j + 1 + fstSentIdx + 1 = j + fstSentIdx + 1 + 1 by omega, htmp] at h2 + simp [h2] + · unfold globallyFinallyReady + intros i + specialize h_4 (i + fstVldTrue + fstRdyOut + 1) + obtain ⟨k, hk⟩ := h_4 + exists k + have htmp : Stream'.drop (fstVldTrue + fstRdyOut + 1) rdOut1_1 (i + k) = rdOut1_1 (i + k + fstVldTrue + fstRdyOut + 1) := by + simp [Stream'.drop, Stream'.get] + congr 1 + omega + simp [htmp, show i + k + fstVldTrue + fstRdyOut + 1 = i + fstVldTrue + fstRdyOut + 1 + k by omega, hk] + · unfold globallyFinallyReady at h_5 ⊢ + intro j + specialize h_5 (fstVldTrue + fstRdyOut + 1 + j) + obtain ⟨k, hk⟩ := h_5 + exists k + have h : Stream'.drop (fstVldTrue + fstRdyOut + 1) rdOut2_1 (j + k) = rdOut2_1 (fstVldTrue + fstRdyOut + 1 + j + k) := by + simp [Stream'.drop, Stream'.get] + congr 1 + omega + simp [h, hk] + · have : fstVldTrue ≤ fstSentIdx := by + simp_all + apply Classical.byContradiction + intro hcontra + specialize hfstVldTrue2 fstSentIdx (by omega) + simp [toStream, hfstVldTrue2] at hfstSentIdx + by_cases fstRecfst : fstRdyOut ≤ fstRdyOut2 + · /- first receiver comes first -/ + by_cases fstRecBeforeSent : fstVldTrue + fstRdyOut ≤ fstSentIdx + · /- first receiver before sent -/ + by_cases sndRecBeforeSent : fstVldTrue + fstRdyOut2 ≤ fstSentIdx + · /- second receiver before sent -/ + simp [split_stream2] + and_intros + · funext i + have := rdOut1_before_allDone (hfork := h_6) (n := i) + /- what happens to `rdOut1` after data is dispatched? -/ + have heq : Stream'.drop (fstSentIdx + 1) rdIn_1 i = rdIn_1 (fstSentIdx + 1 + i) := by + simp [Stream'.drop] + congr 1 + grind + rw [heq] + by_cases hfalse : rdIn_1 (fstSentIdx + 1 + i) = 0#1 + · have := congr_fun h_7 (fstSentIdx + 1 + i) + unfold toStream at this + simp [hfalse] at * + rw [hw_fork_eq] + + have : ∀ k, ∀ i, Stream'.drop k rdOut1_1 i = rdOut1_1 (i + k) := by + intros + simp [Stream'.drop, Stream'.get] + simp [hw_fork', Stream'.corec'] + unfold fork_corec + simp [comb_and, comb_xor, comb_or, hw_constant] + + sorry + · sorry + · sorry + · sorry + · sorry + · sorry + · /- first receiver after sent -/ + sorry + · /- first receiver after sent, implies second receiver after sent -/ + have : fstSentIdx ≤ fstVldTrue + fstRdyOut2 := by omega + sorry + · /- second receiver comes first -/ + by_cases fstRecBeforeSent : fstVldTrue + fstRdyOut ≤ fstSentIdx + · /- first receiver before sent, implies second receiver before sent -/ + have : fstVldTrue + fstRdyOut2 ≤ fstSentIdx := by omega + sorry + · /- first receiver after sent -/ + by_cases sndRecBeforeSent : fstVldTrue + fstRdyOut2 ≤ fstSentIdx + · /- second receiver before sent -/ + sorry + · /- first receiver after sent -/ + sorry + · simp [Stream'.get, h_8, h_7, toStream] + have hdataeq := hw_fork_out0 (h := h_6) + by_cases hle : fstVldTrue ≤ fstSentIdx + · have hreadyIn : rdIn_1 fstSentIdx = 1#1 := by + unfold toStream at h_7 + have h_6sent := congr_fun h_7 fstSentIdx + simp [hfstSentIdx] at h_6sent + simp [h_6sent] + have hvalidIn: vldIn_1 fstSentIdx = 1#1 := by + unfold toStream at h_7 + have h_6sent := congr_fun h_7 fstSentIdx + simp [hfstSentIdx] at h_6sent + simp [h_6sent] + have hrdout : rdOut1_1 (fstVldTrue + fstRdyOut) = 1#1 := by + simp [hfstRdyOut] + have hvldout : vldOut1_1 (fstVldTrue + fstRdyOut) = 1#1 := by + have hbefore : ∀ j < fstVldTrue + fstRdyOut, rdOut1_1 j = 0#1 ∨ vldOut1_1 j = 0#1 := by + intro j hj + by_cases hjlt : j < fstVldTrue + · right; by_contra hc + have : vldOut1_1 j = 1#1 := by grind + have := vldOut1_implies_vldIn h_6 (n := j) (by assumption) + specialize hfstVldTrue2 j hjlt + simp [this] at hfstVldTrue2 + · left + have := hfstRdyOut.2 (j - fstVldTrue) (by omega) + rwa [Nat.add_sub_cancel' (by omega)] at this + rw [vldOut_eq_vldIn_of_fork_unitl_sent h_6 hbefore] + obtain ⟨k, hkrd, hkvld, hkall⟩ := h fstVldTrue hfstVldTrue1 + by_contra hlt; push_neg at hlt + have hrda : rdOut1_1 (fstVldTrue + k) = 0#1 := by + have := hfstRdyOut.2 k (by grind) + simpa using this + -- rdIn fires at fstVldTrue + k with k < fstRdyOut, but rdOut1 hasn't fired + have hh5 := h_6 + rw [hw_fork_eq] at h_6 + simp [split_stream2] at h_6 + obtain ⟨hrdin, -⟩ := h_6 + have hcirc := congr_fun hrdin (fstVldTrue + k) + unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hcirc + generalize hst : Stream'.iterate + (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) + (fstVldTrue + k) = s at hcirc + obtain ⟨a, b, c⟩ := s + dsimp [fork_corec, comb_and, comb_xor, comb_or, hw_constant] at hcirc + have ha : a = fstVldTrue + k := by + have := @fork_corec1 rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 (fstVldTrue + k) + simp [hst] at this + simp [this] + have hb0 : b = 0#1 := by + suffices key : ∀ m, (∀ j < m, rdOut1_1 j = 0#1 ∨ vldOut1_1 j = 0#1) → + (Stream'.iterate (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) + (0, 0#1, 0#1) m).2.1 = 0#1 by + have := key (fstVldTrue + k) (by + intro j hj + by_cases hjlt : j < fstVldTrue + · right; by_contra hc + have : vldOut1_1 j = 1#1 := true_of_width_one (b := vldOut1_1 j) hc + have := vldOut1_implies_vldIn hh5 (n := j) (by assumption) + specialize hfstVldTrue2 j hjlt + simp [this] at hfstVldTrue2 + · have hklt : k < fstRdyOut := by + by_contra hkge; push_neg at hkge + rcases Nat.lt_or_eq_of_le hkge with hlt' | rfl + · exact hlt (hkall fstRdyOut hlt') + · exact hlt hkvld + have hklt : k < fstRdyOut := by + by_contra hkge; push_neg at hkge + exact hlt (hkall fstRdyOut (by omega)) + left + have := hfstRdyOut.2 (j - fstVldTrue) (by omega) + rwa [Nat.add_sub_cancel' (by omega)] at this + ) + rw [hst] at this; simpa using this + intro m; induction m with + | zero => simp [Stream'.iterate] + | succ km ihkm => + intro hbef + have hbk := ihkm (fun j hj => hbef j (Nat.lt_succ_of_lt hj)) + generalize hsk : Stream'.iterate + (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) km = sk + obtain ⟨ak, bk, ck⟩ := sk + simp [hsk] at hbk; subst hbk + have hak : ak = km := by + have := @fork_corec1 rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 km + simp [hsk] at this; omega + have hvldk : vldOut1_1 km = vldIn_1 ak := by + rw [hw_fork_eq] at hh5; simp [split_stream2] at hh5 + obtain ⟨-, hvldout1, -⟩ := hh5 + have hn := congr_fun hvldout1 km + unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn + simp_rw [hsk] at hn + dsimp [fork_corec, comb_and, comb_xor, hw_constant] at hn + simp [hn] + ext k hk + simp [show k = 0 by omega] + have hkbef := hbef km (Nat.lt_succ_self km) + rw [iterate_back_succ, hsk]; simp only [Function.comp] + dsimp [fork_corec, comb_and, comb_xor, comb_or, hw_constant] + subst hak + rcases hkbef with hh | hh + · simp [hh] + · rw [hvldk] at hh; simp [hh] + rw [hkrd, hb0, ha] at hcirc + simp [hrda] at hcirc + simp [hvalidIn, hreadyIn, hrdout, hvldout] + rw [← hdataeq] + let diff := fstSentIdx - fstVldTrue + have hdiff : fstSentIdx = fstVldTrue + diff := by omega + have hdatain : dataIn_1 fstSentIdx = dataIn_1 fstVldTrue := by + rw [hdiff] + have := data_remains_constant_if (i := fstVldTrue) (rdy := rdIn_1) (vld := vldIn_1) (data := dataIn_1) + (by assumption) (by assumption) (by assumption) + obtain ⟨kd, hkd1, hkd2, hkd3, hkd4⟩ := this + by_cases hle : diff ≤ kd + · specialize hkd4 diff hle + apply hkd4 + · /- contra -/ + exfalso + have hkdlt : fstVldTrue + kd < fstSentIdx := by omega + have := hfstSentIdx.2 (fstVldTrue + kd) hkdlt + rw [h_7, toStream] at this + simp [hkd1, hkd2] at this + rw [hdatain] + symm + have := data_remains_constant_until_first (i := fstVldTrue) + (data := dataIn_1) (rdy := rdIn_1) (vld := vldIn_1) (by assumption) + (by assumption) (by assumption) + obtain ⟨k, hk1, hk2, hk3, hk4, hk5⟩ := this + have hkeqdiff : k = diff := by + apply Nat.le_antisymm + · by_contra hlt; push_neg at hlt + -- hlt : diff < k + have := hk5 diff (by omega) + rw [← hdiff] at this + simp [hreadyIn] at this + · by_contra hlt; push_neg at hlt + have := hfstSentIdx.2 (fstVldTrue + k) (by omega) + rw [h_7, toStream] at this + simp [hk1, hk2] at this + subst hkeqdiff + apply hk4 fstRdyOut + -- fstRdyOut ≤ diff, i.e., fstVldTrue + fstRdyOut ≤ fstSentIdx + -- proved by contradiction: if fstSentIdx < fstVldTrue + fstRdyOut, + -- allDone fires but rdOut1 hasn't, contradicting the circuit + have hrdyOutLe : fstVldTrue + fstRdyOut ≤ fstSentIdx := by + by_contra hlt; push_neg at hlt + have hh5 := h_6 + rw [hw_fork_eq] at h_6 + simp [split_stream2] at h_6 + obtain ⟨hrdin, -⟩ := h_6 + have hcirc2 := congr_fun hrdin fstSentIdx + unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hcirc2 + generalize hst2 : Stream'.iterate + (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) + fstSentIdx = s2 at hcirc2 + obtain ⟨a2, b2, c2⟩ := s2 + dsimp [fork_corec, comb_and, comb_xor, comb_or, hw_constant] at hcirc2 + have ha2 : a2 = fstSentIdx := by + have := @fork_corec1 rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 fstSentIdx + simp [hst2] at this; omega + have hb02 : b2 = 0#1 := by + suffices key2 : ∀ m, (∀ j < m, rdOut1_1 j = 0#1 ∨ vldOut1_1 j = 0#1) → + (Stream'.iterate (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) + (0, 0#1, 0#1) m).2.1 = 0#1 by + have := key2 fstSentIdx (by + intro j hj + by_cases hjlt : j < fstVldTrue + · right; by_contra hc + have : vldOut1_1 j = 1#1 := by grind + have := vldOut1_implies_vldIn hh5 (n := j) this + exact absurd (hfstVldTrue2 j hjlt) (by grind) + · left + have := hfstRdyOut.2 (j - fstVldTrue) (by omega) + rwa [Nat.add_sub_cancel' (by omega)] at this) + rw [hst2] at this; simpa using this + intro m; induction m with + | zero => simp [Stream'.iterate] + | succ km ihkm => + intro hbef + have hbk := ihkm (fun j hj => hbef j (Nat.lt_succ_of_lt hj)) + generalize hsk : Stream'.iterate + (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) km = sk + obtain ⟨ak, bk, ck⟩ := sk + simp [hsk] at hbk; subst hbk + have hak : ak = km := by + have := @fork_corec1 rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 km + simp [hsk] at this; omega + have hvldk2 : vldOut1_1 km = vldIn_1 ak := by + rw [hw_fork_eq] at hh5; simp [split_stream2] at hh5 + obtain ⟨-, hvldout1, -⟩ := hh5 + have hn := congr_fun hvldout1 km + unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn + simp_rw [hsk] at hn + dsimp [fork_corec, comb_and, comb_xor, hw_constant] at hn + simp [hn] + ext k + simp [show k = 0 by omega] + rw [iterate_back_succ, hsk]; simp only [Function.comp] + dsimp [fork_corec, comb_and, comb_xor, comb_or, hw_constant] + subst hak + rcases hbef ak (Nat.lt_succ_self ak) with hh | hh + · simp [hh] + · rw [hvldk2] at hh; simp [hh] + have hrda2 : rdOut1_1 fstSentIdx = 0#1 := by + have := hfstRdyOut.2 (fstSentIdx - fstVldTrue) (by omega) + rwa [Nat.add_sub_cancel' (by omega)] at this + rw [hreadyIn, hb02, ha2, hrda2] at hcirc2 + simp at hcirc2 + omega + · /- contradiction: nothing can be sent before `fstSentIdx` -/ + simp_all + intro hcontra + specialize hfstVldTrue2 fstSentIdx hle + simp [toStream, hfstVldTrue2] at hfstSentIdx + · intro i hi + exact hfstSentIdx.2 i hi + · intros j hj + by_cases hj' : j < fstVldTrue + · simp [Stream'.get, h_8, toStream] + intro hvld + have := vldOut1_implies_vldIn h_6 (n := j) + have := hfstVldTrue2 j hj' + grind + · simp [h_8, toStream, Stream'.get] + let diff := j - fstVldTrue + have : j = fstVldTrue + diff := by omega + rw [this] + obtain ⟨h1,h2⟩ := hfstRdyOut + specialize h2 diff (by omega) + intro hc + simp [hc] at h2 + · /- if we never have a valid signal, all streams are empty and the relation holds trivially -/ + have hnonein := not_exists_transmitted_element (x := sin) (data := dataIn_1) (rdy := rdIn_1) + (vld := vldIn_1) (by grind) h_7 + /- the fork module will never transmit anything meaningful -/ + rw [hw_fork_eq] at h_6 + unfold split_stream2 at h_6 + simp at h_6 + have hhfork1 := h_6 + obtain ⟨hrd', hvld1', hvld2', hdata1', hdata2'⟩ := hhfork1 + rw [h_7, h_8] + have hnoneout : ∀ k, vldOut1_1 k = 0#1 := by + unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hvld1' + intros k + generalize hst : Stream'.iterate + (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) k = s at hvld1' + simp [fork_corec] at hvld1' + have hk := congr_fun hvld1' k + simp [comb_and, hw_constant] at hk + simp_all + + have : vldIn_1 (Stream'.iterate (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) k).1 = 0#1 := by + grind + simp [this] + have hnoneout2 : ∀ k, vldOut2_1 k = 0#1 := by + unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hvld2' + intros k + generalize hst : Stream'.iterate + (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) k = s at hvld2' + simp [fork_corec] at hvld2' + have hk := congr_fun hvld2' k + simp [comb_and, hw_constant] at hk + simp_all + have : vldIn_1 (Stream'.iterate (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) k).1 = 0#1 := by + grind + simp [this] + have hnevldin : ∀ k, vldIn_1 k = 0#1 := by grind + have hnonet := not_exists_transmitted_element (x := sout) (data := dataOut1_1) (rdy := rdOut1_1) + (vld := vldOut1_1) (by grind) h_8 + exists 0, 0 + and_intros + · simp + generalize hxgen : Stream'.drop 1 (toStream rdIn_1 vldIn_1 dataIn_1) = y' + generalize hygen : Stream'.drop 1 (toStream rdOut1_1 vldOut1_1 dataOut1_1) = x' + apply relation_fork.intro (x := y') (y := x') + (dataIn := Stream'.drop 1 dataIn_1) + (rdIn := Stream'.drop 1 rdIn_1) + (vldIn := Stream'.drop 1 vldIn_1) + (vldOut1 := Stream'.drop 1 vldOut1_1) + (vldOut2 := Stream'.drop 1 vldOut2_1) + (dataOut1 := Stream'.drop 1 dataOut1_1) + (dataOut2 := Stream'.drop 1 dataOut2_1) + (rdOut1 := Stream'.drop 1 rdOut1_1) + (rdOut2 := Stream'.drop 1 rdOut2_1) + · rw [← hxgen] + rfl + · rw [← hygen] + rfl + · /- contra in hj: there is no i such that vldIn' = 1#1 -/ + unfold globallyValidUntilReady + intros j hj + specialize hnevldin (j + 1) + have : Stream'.drop 1 vldIn_1 j = vldIn_1 (j + 1) := by rfl + simp [this, hnevldin] at hj + · unfold globallyValidUntilReady + intros j hj + apply Classical.byContradiction + simp [Stream'.drop] at hj + have := hnoneout (1 + j) + simp [show vldOut1_1.get (j + 1) = vldOut1_1 (j + 1) by rfl] at hj + simp [Nat.add_comm (n := j), this] at hj + · unfold globallyValidUntilReady + intros j hj + apply Classical.byContradiction + simp [Stream'.drop] at hj + have := hnoneout2 (1 + j) + simp [show vldOut2_1.get (j + 1) = vldOut2_1 (j + 1) by rfl] at hj + simp [Nat.add_comm (n := j), this] at hj + · /- contra in hj: there is no i such that vldIn' = 1#1 -/ + unfold globallyValidAndData + intros j hj + have : Stream'.drop 1 vldIn_1 j = vldIn_1 (j + 1) := by rfl + specialize hnevldin (j + 1) + simp [this, hnevldin] at hj + · /- follows from `hgfrOut1'` -/ + unfold globallyFinallyReady at h_4 ⊢ + intros i + specialize h_4 (i + 1) + obtain ⟨j, hj⟩ := h_4 + exists j + have : Stream'.drop 1 rdOut1_1 (i + j) = rdOut1_1 ((i + j) + 1) := by rfl + rw [this, show i + j + 1 = i + 1 + j by omega, hj] + · unfold globallyFinallyReady at h_5 ⊢ + intros i + specialize h_5 (i + 1) + obtain ⟨j, hj⟩ := h_5 + exists j + have : Stream'.drop 1 rdOut2_1 (i + j) = rdOut2_1 ((i + j) + 1) := by rfl + rw [this, show i + j + 1 = i + 1 + j by omega, hj] + · /- after dropping one element, all the relations defined by the fork module remain. + We see this by unfolding the fork hypotheses -/ + unfold split_stream2 + simp + have h1 := hw_fork'_of_all_none + (dataIn := Stream'.drop 1 dataIn_1) + (vldIn := Stream'.drop 1 vldIn_1) + (rdOut1 := Stream'.drop 1 rdOut1_1) + (rdOut2 := Stream'.drop 1 rdOut2_1) + (by + intro k + specialize hnevldin (k + 1) + simp [show Stream'.drop 1 vldIn_1 k = vldIn_1 (k + 1) by rfl, hnevldin] + ) + have h2 := hw_fork'_of_all_none + (dataIn := dataIn_1) + (vldIn := vldIn_1) + (rdOut1 := rdOut1_1) + (rdOut2 := rdOut2_1) + (by grind) + rw [hw_fork_eq] + simp_all + and_intros + · rfl + · ext l n + have hlhs := hw_fork_out0 + (data_in := dataIn_1) + (vld_in := vldIn_1) + (rd0_in := rdOut1_1) + (rd1_in := rdOut2_1) + (rdy_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).1) + (vld0_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.1) + (vld1_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.1) + (data0_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) + (data1_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) + (by rw [← hw_fork_eq]; simp [split_stream2]) (1 + l) + have hrhs := hw_fork_out0 + (rdy_out := fun i => + (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).1) + (vld0_out := fun i => + (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.1) + (vld1_out := fun i => + (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.1) + (data0_out := fun i => + (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.1) + (data1_out := fun i => + (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.2) + (by rw [← hw_fork_eq]; simp [split_stream2]) l + simp [Stream'.drop] at hrhs + have h1 : Stream'.get (fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) (1 + l) = + (fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) (1 + l) := by rfl + simp [h1] + have h2 : (Stream'.get (fun i => + (hw_fork' (Stream'.drop 1 rdOut1_1) + (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) + (Stream'.drop 1 dataIn_1) i).2.2.2.1) l) = + (fun i => + (hw_fork' (Stream'.drop 1 rdOut1_1) + (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) + (Stream'.drop 1 dataIn_1) i).2.2.2.1) l := by rfl + simp [h2] + simp [← hrhs, ← hlhs] + simp [show dataIn_1.get (l + 1) = dataIn_1 (l + 1) by rfl, Nat.add_comm] + · ext l n + have hlhs := hw_fork_out1 + (data_in := dataIn_1) + (vld_in := vldIn_1) + (rd0_in := rdOut1_1) + (rd1_in := rdOut2_1) + (rdy_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).1) + (vld0_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.1) + (vld1_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.1) + (data0_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) + (data1_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) + (by rw [← hw_fork_eq]; simp [split_stream2]) (1 + l) + have hrhs := hw_fork_out1 + (rdy_out := fun i => + (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).1) + (vld0_out := fun i => + (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.1) + (vld1_out := fun i => + (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.1) + (data0_out := fun i => + (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.1) + (data1_out := fun i => + (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.2) + (by rw [← hw_fork_eq]; simp [split_stream2]) l + simp [Stream'.drop] at hrhs + + have h1 : Stream'.get (fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) (1 + l) = + (fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) (1 + l) := by rfl + simp [h1] + have h2 : (Stream'.get (fun i => + (hw_fork' (Stream'.drop 1 rdOut1_1) + (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) + (Stream'.drop 1 dataIn_1) i).2.2.2.2) l) = + (fun i => + (hw_fork' (Stream'.drop 1 rdOut1_1) + (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) + (Stream'.drop 1 dataIn_1) i).2.2.2.2) l := by rfl + simp [h2] + simp [← hrhs, ← hlhs] + simp [show dataIn_1.get (l + 1) = dataIn_1 (l + 1) by rfl, Nat.add_comm] + · unfold toStream + congr + have : (fun i => if rdIn_1 i = 1#1 ∧ vldIn_1 i = 1#1 then some (dataIn_1 i) else none) = + fun i => none := by + ext k hk + grind + simp [this] + have : (fun i => if rdOut1_1 i = 1#1 ∧ vldOut1_1 i = 1#1 then some (dataOut1_1 i) else none) = + fun i => none := by + ext k hk + grind + simp [this] + · simp + · simp + · apply relation_fork.intro (toStream rdIn vldIn dataIn) (toStream rdOut1 vldOut1 dataOut1) + (dataOut2 := dataOut2) (vldOut2 := vldOut2) + · rfl + · rfl + · assumption + · assumption + · assumption + · congr + · assumption + · assumption + · assumption + + +theorem hw_fork_refines': + /- Given a handshake fork -/ + (x, y) = TRY2.hw_fork a → + /- we get the output of the corresponding lowered fork -/ + (rdy, vld1, vld2, o1, o2) = split_stream2 (a := BitVec 1) (rtl.fork rd1 rd2 vld data) → + /- if we know that the hshake input stream is bisimilar to the ready-valid input of the hw fork -/ + a ~ (toStream rdy vld data) → + /- We want to make sure that stalling is correctly modeled for `a` (input). + We constrain the input and prove that if the input behaves properly, + the output will. -/ + globallyValidUntilReady vld rdy → + globallyValidAndData vld data → + /- we assume no deadlock -/ + globallyFinallyReady rd1 → + globallyFinallyReady rd2 → + /- we want to prove that the outputs of the handshake fork are respectively + bisimilar to the ready-valid wrapping of the output of the hardware fork -/ + x ~ (toStream rd1 vld1 o1) ∧ y ~ (toStream rd2 vld2 o2) := by + intros handshake_fork hardware_fork inputs_bisim valready_ valdata_a finready1 finready2 + · unfold handshake.fork at handshake_fork + have heq : x = a := by + simp at handshake_fork + exact handshake_fork.1 + have heq' : y = a := by + simp at handshake_fork + exact handshake_fork.2 + rw [heq, heq'] + and_intros + · sorry + · sorry + +end HWComponents From 84d9b446d2bd04e72b9da7c3307f1a35d65f98f9 Mon Sep 17 00:00:00 2001 From: luisacicolini Date: Thu, 30 Apr 2026 13:58:10 +0100 Subject: [PATCH 04/13] first set of comments --- .../CIRCT/HandshakeToHW/fork_lowering.lean | 354 +++++++++--------- 1 file changed, 167 insertions(+), 187 deletions(-) diff --git a/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean b/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean index ca62d028c6..16b3412e5c 100644 --- a/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean +++ b/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean @@ -24,7 +24,7 @@ def handshake.fork (in0 : Stream (BitVec 32)) : Stream (BitVec 32) × Stream (Bi (in0, in0) -/- +/-! RTL-level definitions of circuit components -/ def hw_constant (b : Bool) : BitVec 1 := if b then 1#1 else 0#1 @@ -70,7 +70,11 @@ def rtl.fork (_ready _ready_1 _valid : Stream' (BitVec 1)) (_in0 : Stream' (BitV ((_12, _3, _9, _rawOutput, _rawOutput), (i + 1, _1, _7)) ) (0, 0#1, 0#1) -def split_stream2 : +/-- + Split a stream containing the product of 5 objects into a product of 5 streams, + each representing a stream of single objects. +-/ +def project_stream : Stream' (a × b × c × d × e) → Stream' a × Stream' b × Stream' c × Stream' d × Stream' e := fun g => (fun i => (g i).1, @@ -79,118 +83,81 @@ def split_stream2 : fun i => (g i).2.2.2.1, fun i => (g i).2.2.2.2) - -/-- At the handshake level: (manual) delayed fork ~ normal fork: the outputs of the fork are bisimilar - for any delay (up to any numbers of `none` inserted, anywhere). -/ -theorem fork_refines {a x y x' y'} : - (x, y) = handshake.fork a → - x ~ x' → - y ~ y' → - x ~ x' ∧ y ~ y' := by grind - -/-- Stream := Stream' (Option α) -/ +/-- + Define the relation between a latency-insensitive `Stream := Stream' (Option α)` + and three concrete `Stream'` (representingready, valid, data signal). +-/ def toStream {α} (rdy : Stream' (BitVec 1)) (vld : Stream' (BitVec 1)) (data : Stream' α) : Stream α := fun i => if rdy i == 1#1 && vld i == 1#1 then .some (data i) else .none -/- the standard implementation of the fork refines the handshake fork (`TRY2.hw_fork`) -/ -/-- weaker def where we do not assume that rdy is by default 0#1 -/ +/-- + For every valid signal at any point in time `vld i = 1#1`, + there is a later point in time `i + k` where the ready signal is true (`rdy (i + k) = 1#1`), + and the valid signal remains constantly true until then. +-/ def globallyValidUntilReady (vld rdy : Stream' (BitVec 1)) : Prop := - ∀ (i : Nat), - (vld i = 1#1) → - ∃ (k : Nat), - rdy (i + k) = 1#1 ∧ vld (i + k) = 1#1 ∧ - ∀ (j : Nat) (_hj : j < k), - vld (i + j) = 1#1 - -/-- This def is stronger than the one above -/ -def globallyValidUntilReady' (vld rdy : Stream' (BitVec 1)) : Prop := - ∀ (i : Nat), - (vld i = 1#1) → - ∃ (k : Nat), - rdy (i + k) = 1#1 ∧ vld (i + k) = 1#1 ∧ - ∀ (j : Nat) (_hj : j < k), - vld (i + j) = 1#1 ∧ rdy (i + j) = 0#1 - -- we should add sth like vld (i + k + 1) = 0#1? + ∀ (i : Nat), (vld i = 1#1) → + ∃ (k : Nat), rdy (i + k) = 1#1 ∧ vld (i + k) = 1#1 ∧ + ∀ (j : Nat) (_hj : j < k), vld (i + j) = 1#1 +/-- + Given a couple of consecutive valid signals (`vld i = 1#1 ∧ vld (i + 1) = 1#1`), + the `data` stream at both points in time remains constant. +-/ def globallyValidAndData (vld : Stream' (BitVec 1)) (data : Stream' (BitVec w)) : Prop := - ∀ (i : Nat), - (vld i = 1#1 ∧ vld (i + 1) = 1#1) → - data i = data (i + 1) - -def relation : Stream (BitVec w) → Stream (BitVec w) → Prop := fun x y => - ∃ (rd1 vld1 : Stream' (BitVec 1)) (data1 : Stream' (BitVec w)) - (rd2 vld2 : Stream' (BitVec 1)) (data2 : Stream' (BitVec w)), - x = toStream rd1 vld1 data1 ∧ - globallyValidUntilReady rd1 vld1 ∧ - globallyValidAndData vld1 data1 ∧ - y = toStream rd2 vld2 data2 ∧ - globallyValidUntilReady rd2 vld2 ∧ - globallyValidAndData vld2 data2 - /- we need to say something about `x` and `y`. -/ - -/-- G(F(val = 1))-/ -def globallyFinallyReady (x : Stream' (BitVec 1)) := - ∀ (i : Nat), - ∃ (k : Nat), - x (i + k) = 1#1 - -inductive relation' : Stream (BitVec w) → Stream (BitVec w) → Prop where - | intro x y rd vld data rd1 vld1 o1 : /- same as `∀ x y` -/ - /- x is the high-level (input), y is the low-level (output) -/ - x = toStream rd vld data → - y = toStream rd1 vld1 o1 → - (∀ j, (rd j = 1#1 ∧ vld j = 1#1) ↔ rd1 j = 1#1 ∧ vld1 j = 1#1) → - -- (∃ k, rd k = 1#1 ∧ vld k = 1) → /- at least one transition happens frfr -/ - globallyValidUntilReady vld rd → - globallyValidAndData vld data → - globallyFinallyReady rd1 → - (∀ n, vld n = 1#1 → data n = o1 n) → /- when the signal is valid, data and output are the same -/ - relation' x y /- defining the type of the relation -/ + ∀ (i : Nat), (vld i = 1#1 ∧ vld (i + 1) = 1#1) → data i = data (i + 1) +/-- + For every point in time `i` of the ready signal, there exists a later (or simultaneous) + point in time `i + k` where the signal is true. +-/ +def globallyFinallyReady (rdy : Stream' (BitVec 1)) := + ∀ (i : Nat), ∃ (k : Nat), rdy (i + k) = 1#1 + +/-- + We propose a bisimilarity relation between latency-insensitive streams at the input and + output of a `fork` circuit. +-/ inductive relation_fork : Stream (BitVec w) → Stream (BitVec w) → Prop where | intro x y rdIn vldIn dataIn rdOut1 vldOut1 dataOut1 rdOut2 vldOut2 dataOut2 : /- same as `∀ x y` -/ - /- x is the high-level (input), y is the low-level (output) -/ + /- *If* x is the input stream, encoded via 3-way-handshake of streams rdIn, vldIn, dataIn -/ x = toStream rdIn vldIn dataIn → + /- *If* y is either of output streams of the fork, + encoded via 3-way-handshake of streams rdOut1, vldOut1, dataOut1 -/ y = toStream rdOut1 vldOut1 dataOut1 → - /- if a signal in `x` is valid (`vldIn i = 1#1`), it will remain valid (at least) until a - ready signal is received (`rdIn (i + k) = 1#1`). A ready signal is eventually definitely received. -/ + /- *If* when a signal in `x` is valid (`vldIn i = 1#1`), it will remain valid (at least) until a + ready signal is received (`rdIn (i + k) = 1#1`). + A ready signal is eventually definitely received. -/ globallyValidUntilReady vldIn rdIn → + /- *If* when a signal in `y` is valid (`vldOut1 i = 1#1`), it will remain valid (at least) until a + ready signal is received (`rdOut1 (i + k) = 1#1`). + A ready signal is eventually definitely received. -/ globallyValidUntilReady vldOut1 rdOut1 → + /- *If* when a signal in `y` is valid (`vldOut2 i = 1#1`), it will remain valid (at least) until a + ready signal is received (`rdOut2 (i + k) = 1#1`). + A ready signal is eventually definitely received. -/ globallyValidUntilReady vldOut2 rdOut2 → - /- if a signal in `x` is valid for more than one cycle (`vldIn i = 1#1 ∧ vldIn (i + 1) = 1#1`), - the data does not change (`dataIn i = dataIn (i + 1)`) -/ + /- *If* when a signal in `x` is valid for more than one cycle (`vldIn i = 1#1 ∧ vldIn (i + 1) = 1#1`), + the data stream at those points in time remains constant (`dataIn i = dataIn (i + 1)`). -/ globallyValidAndData vldIn dataIn → - /- eventually a ready signal arrives from both receivers (`rdOut1 i = 1#1`), (`rdOut2 i = 1#1`) -/ + /- *If* eventually, + a ready signal arrives from both receivers (`rdOut1 i = 1#1`), (`rdOut2 i = 1#1`). -/ globallyFinallyReady rdOut1 → globallyFinallyReady rdOut2 → - /- input/output relationship around the `fork` module -/ - - (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn) → + /- *If* the relations between the input and output ready, valid, data signals + are given by the `rtl.fork` component. -/ + (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = project_stream (rtl.fork rdOut1 rdOut2 vldIn dataIn) → + /- The relation holds. -/ relation_fork x y -/- - our implementation of `fork` should not allow this, assuming that the input is - well-formed (including its ready signals!). - - val1 = 1 1 1 - data1 = 2 3 4 - rd1 = 1 1 1 - out1: 2 3 4 - - val2 = 1 1 1 - data2 = 2 3 4 - rd2 = 0 1 1 - out2: - 3 4 - +/-- + Define the unfolding of one step of the corecursive definition of `fork`. -/ - - -/-- We unfold one step of the corecursive definition of `fork` -/ def fork_corec (_ready _ready_1 _valid : Stream' (BitVec 1)) (_in0 : Stream' (BitVec 32)) := fun (i, _emitted_0, _emitted_1) => let _true := hw_constant true @@ -211,8 +178,10 @@ def fork_corec (_ready _ready_1 _valid : Stream' (BitVec 1)) (_in0 : Stream' (Bi let _7 := comb_and _11 _6 ((_12, _3, _9, _rawOutput, _rawOutput), (i+1, _1, _7)) -/-- We re-define the fork circuit in terms of `fork_corec` -/ -def hw_fork' (_ready _ready_1 _valid : Stream' (BitVec 1)) (_in0 : Stream' (BitVec 32)) +/-- + Define the fork circuit in terms of `fork_corec`. +-/ +def rtl.fork' (_ready _ready_1 _valid : Stream' (BitVec 1)) (_in0 : Stream' (BitVec 32)) : Stream' ( BitVec 1 -- ready (_12) × BitVec 1 -- valid_0 (_3) × BitVec 1 -- valid_1 (_9) @@ -221,11 +190,11 @@ def hw_fork' (_ready _ready_1 _valid : Stream' (BitVec 1)) (_in0 : Stream' (BitV ) := Stream'.corec' (α := Nat × BitVec 1 × BitVec 1) (fork_corec _ready _ready_1 _valid _in0) (0, 0#1, 0#1) - - - -/-- Prove that iterating `n` times starting from the `m`-th index of the stream yields the `n + m`-th index-/ -theorem fork_corec1 : +/-- + Prove that iterating `n` times starting from the `m`-th index of the stream + yields the `n + m`-th index. +-/ +theorem fork_corec_iter : (Stream'.iterate (Prod.snd ∘ fork_corec rd0_in rd1_in vld_in data_in) (m, x, y) n).1 = n + m := by induction n generalizing m x y with | zero => grind [Stream'.iterate] @@ -235,9 +204,13 @@ theorem fork_corec1 : dsimp [fork_corec] grind -theorem hw_fork'_vldOut1_of_none (h : ∀ k, vldIn k = 0#1) : - ((hw_fork' rdOut1 rdOut2 vldIn dataIn) k).2.1 = 0#1 := by - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get +/-- + If the valid input stream is false at all points in time (`vldIn k = 0#1`), + the first valid output stream of the fork component is also false at all times. +-/ +theorem fork'_vldOut1_of_none (h : ∀ k, vldIn k = 0#1) : + ((rtl.fork' rdOut1 rdOut2 vldIn dataIn) k).2.1 = 0#1 := by + unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get generalize hst : Stream'.iterate (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) k = s obtain ⟨a, b, c⟩ := s @@ -245,9 +218,13 @@ theorem hw_fork'_vldOut1_of_none (h : ∀ k, vldIn k = 0#1) : specialize h a simp [h] -theorem hw_fork'_vldOut2_of_none (h : ∀ k, vldIn k = 0#1) : - ((hw_fork' rdOut1 rdOut2 vldIn dataIn) k).2.2.1 = 0#1 := by - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get +/-- + If the valid input stream is false at all points in time (`vldIn k = 0#1`), + the second valid output stream of the fork component is also false at all times. +-/ +theorem fork'_vldOut2_of_none (h : ∀ k, vldIn k = 0#1) : + ((rtl.fork' rdOut1 rdOut2 vldIn dataIn) k).2.2.1 = 0#1 := by + unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get generalize hst : Stream'.iterate (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) k = s obtain ⟨a, b, c⟩ := s @@ -255,6 +232,9 @@ theorem hw_fork'_vldOut2_of_none (h : ∀ k, vldIn k = 0#1) : specialize h a simp [h] +/-- + Applying a function `f` to +-/ lemma iterate_back_succ (f : α → α) (s : α) (n : ℕ) : Stream'.iterate f s (n + 1) = f (Stream'.iterate f s n) := by induction n generalizing s with @@ -279,11 +259,11 @@ lemma fork_emitted_zero_of_all_none (h : ∀ k, vldIn k = 0#1) : simp [h a] -- when vld is always 0, all signal outputs (not data) are 0 -theorem hw_fork'_of_all_none (h : ∀ k, vldIn k = 0#1) : - ∀ k, ((hw_fork' rdOut1 rdOut2 vldIn dataIn) k).1 = 0#1 ∧ - ((hw_fork' rdOut1 rdOut2 vldIn dataIn) k).2.1 = 0#1 ∧ - ((hw_fork' rdOut1 rdOut2 vldIn dataIn) k).2.2.1 = 0#1 := by - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get +theorem rtl.fork'_of_all_none (h : ∀ k, vldIn k = 0#1) : + ∀ k, ((rtl.fork' rdOut1 rdOut2 vldIn dataIn) k).1 = 0#1 ∧ + ((rtl.fork' rdOut1 rdOut2 vldIn dataIn) k).2.1 = 0#1 ∧ + ((rtl.fork' rdOut1 rdOut2 vldIn dataIn) k).2.2.1 = 0#1 := by + unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get intro k and_intros · generalize hst : Stream'.iterate @@ -310,15 +290,15 @@ theorem hw_fork'_of_all_none (h : ∀ k, vldIn k = 0#1) : simp [h] /-- Prove that (at RTL level) the input and output data at the `n`-th position are the same. - This is possible because `hw_fork'` does not introduce any delay, and there is no transformation + This is possible because `rtl.fork'` does not introduce any delay, and there is no transformation happening on the data. -/ theorem hw_fork_out0 - (h : ⟨rdy_out, vld0_out, vld1_out, data0_out, data1_out⟩ = split_stream2 (hw_fork' rd0_in rd1_in vld_in data_in)) : + (h : ⟨rdy_out, vld0_out, vld1_out, data0_out, data1_out⟩ = project_stream (rtl.fork' rd0_in rd1_in vld_in data_in)) : (∀ n, data_in n = data0_out n) := by intro n - simp [split_stream2] at h + simp [project_stream] at h simp [h] - unfold hw_fork'; clear h + unfold rtl.fork'; clear h unfold Stream'.corec' Stream'.corec Stream'.map Stream'.get generalize h: (Stream'.iterate (Prod.snd ∘ fork_corec rd0_in rd1_in vld_in data_in) (0, 0#1, 0#1) n) = y obtain ⟨a, b, c⟩ := y @@ -327,12 +307,12 @@ theorem hw_fork_out0 theorem hw_fork_out1 (h : ⟨rdy_out, vld0_out, vld1_out, data0_out, data1_out⟩ = - split_stream2 (hw_fork' rd0_in rd1_in vld_in data_in)) : + project_stream (rtl.fork' rd0_in rd1_in vld_in data_in)) : (∀ n, data_in n = data1_out n) := by intro n - simp [split_stream2] at h + simp [project_stream] at h simp [h] - unfold hw_fork'; clear h + unfold rtl.fork'; clear h unfold Stream'.corec' Stream'.corec Stream'.map Stream'.get generalize h: (Stream'.iterate (Prod.snd ∘ fork_corec rd0_in rd1_in vld_in data_in) (0, 0#1, 0#1) n) = y obtain ⟨a, b, c⟩ := y @@ -352,20 +332,20 @@ theorem fork_corec1bis : dsimp [fork_corec] grind -theorem hw_fork_eq : rtl.fork rd0 rd1 vld data = hw_fork' rd0 rd1 vld data := by - unfold rtl.fork hw_fork' +theorem hw_fork_eq : rtl.fork rd0 rd1 vld data = rtl.fork' rd0 rd1 vld data := by + unfold rtl.fork rtl.fork' congr 1 theorem vldOut1_implies_vldIn (h : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = - split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) + project_stream (rtl.fork rdOut1 rdOut2 vldIn dataIn)) (hvld : vldOut1 n = 1#1) : vldIn n = 1#1 := by rw [hw_fork_eq] at h - simp [split_stream2] at h + simp [project_stream] at h obtain ⟨-, hvldout1, -⟩ := h have hn := congr_fun hvldout1 n rw [hvld] at hn - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn + unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn generalize hst : Stream'.iterate (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) n = s at hn obtain ⟨a, b, c⟩ := s @@ -383,14 +363,14 @@ theorem vldOut1_implies_vldIn theorem vldOut2_implies_vldIn (h : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = - split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) + project_stream (rtl.fork rdOut1 rdOut2 vldIn dataIn)) (hvld : vldOut2 n = 1#1) : vldIn n = 1#1 := by rw [hw_fork_eq] at h - simp [split_stream2] at h + simp [project_stream] at h obtain ⟨-, -, hvldout2, -⟩ := h have hn := congr_fun hvldout2 n rw [hvld] at hn - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn + unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn generalize hst : Stream'.iterate (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) n = s at hn obtain ⟨a, b, c⟩ := s @@ -408,7 +388,7 @@ theorem vldOut2_implies_vldIn theorem rdOut1_before_allDone (hfork : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = - split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) (hvldOut1 : vldOut1 n = 1#1) + project_stream (rtl.fork rdOut1 rdOut2 vldIn dataIn)) (hvldOut1 : vldOut1 n = 1#1) (hgvurIn : globallyValidUntilReady vldIn rdIn) : ∃ k, rdIn (n + k) = 1#1 ∧ vldIn (n + k) = 1#1 := by have hvldIn := vldOut1_implies_vldIn hfork hvldOut1 @@ -430,15 +410,15 @@ lemma iterate_succ_apply (f : α → α) (s : α) (n : ℕ) : theorem vldOut_eq_vldIn_of_fork_unitl_sent (hfork : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = - split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) + project_stream (rtl.fork rdOut1 rdOut2 vldIn dataIn)) /- nothing is emitted before `n`, as emission occurs if `rdOut1 j ∧ vldOut1 j` -/ (hbefore : ∀ j < n, rdOut1 j = 0#1 ∨ vldOut1 j = 0#1) : vldOut1 n = vldIn n := by rw [hw_fork_eq] at hfork - simp [split_stream2] at hfork + simp [project_stream] at hfork obtain ⟨-, hvldout1, -⟩ := hfork have hn := congr_fun hvldout1 n - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn + unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn generalize hst : Stream'.iterate (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) n = s at hn obtain ⟨a, b, c⟩ := s @@ -472,7 +452,7 @@ theorem vldOut_eq_vldIn_of_fork_unitl_sent simp only [Function.comp] have hvldk : vldOut1 k = vldIn ak := by have h := congr_fun hvldout1 k - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at h + unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at h simp_rw [hsk] at h dsimp [fork_corec, comb_and, comb_xor, hw_constant] at h simp_all @@ -527,7 +507,7 @@ theorem vldOut_eq_vldIn_of_fork_unitl_sent theorem vldOut_of_vldIn_rdy (hfork : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = - split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) + project_stream (rtl.fork rdOut1 rdOut2 vldIn dataIn)) /- nothing has been accepted so far -/ (hbefore : ∀ l < j, rdOut1 l = 0#1 ∨ vldOut1 l = 0#1) (hin : vldIn j = 1#1 ∧ rdIn j = 1#1) : @@ -537,15 +517,15 @@ theorem vldOut_of_vldIn_rdy theorem vldOut_eq_vldIn_of_fork_unitl_sent2 (hfork : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = - split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) + project_stream (rtl.fork rdOut1 rdOut2 vldIn dataIn)) /- nothing is emitted before `n`, as emission occurs if `rdOut1 j ∧ vldOut1 j` -/ (hbefore : ∀ j < n, rdOut2 j = 0#1 ∨ vldOut2 j = 0#1) : vldOut2 n = vldIn n := by rw [hw_fork_eq] at hfork - simp [split_stream2] at hfork + simp [project_stream] at hfork obtain ⟨-, -, hvldout2, -⟩ := hfork have hn := congr_fun hvldout2 n - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn + unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn generalize hst : Stream'.iterate (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) n = s at hn obtain ⟨a, b, c⟩ := s @@ -571,7 +551,7 @@ theorem vldOut_eq_vldIn_of_fork_unitl_sent2 grind have hvldk : vldOut2 k = vldIn ak := by have h := congr_fun hvldout2 k - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at h + unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at h simp_rw [hsk] at h dsimp [fork_corec, comb_and, comb_xor, hw_constant] at h simp_all @@ -763,7 +743,7 @@ theorem true_of_width_one (b : BitVec 1) (h : ¬ b = 0#1 ) : b = 1#1 := by grind theorem vldIn_and_eventually_ready_implies_vldOut1 (hfork : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = - split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) + project_stream (rtl.fork rdOut1 rdOut2 vldIn dataIn)) (hvldIn : globallyFinallyReady vldIn) : ∃ k, vldOut1 k = 1#1 := by obtain ⟨n, hvldn, hnmin⟩ := if_exists_first_exists (hvldIn 0 |>.imp (fun k hk => by simpa using hk)) @@ -779,7 +759,7 @@ theorem vldIn_and_eventually_ready_implies_vldOut1 theorem vldIn_and_ready_implies_vldOut1 (hfork : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = - split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) + project_stream (rtl.fork rdOut1 rdOut2 vldIn dataIn)) (hvldIn : ∃ j, vldIn j = 1#1) : ∃ k, vldOut1 k = 1#1 := by obtain ⟨n, hvldn, hnmin⟩ := if_exists_first_exists (st := vldIn) (by grind) @@ -795,7 +775,7 @@ theorem vldIn_and_ready_implies_vldOut1 theorem vldIn_and_ready_implies_vldOut2 (hfork : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = - split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) + project_stream (rtl.fork rdOut1 rdOut2 vldIn dataIn)) (hvldIn : ∃ j, vldIn j = 1#1) : ∃ k, vldOut2 k = 1#1 := by obtain ⟨n, hvldn, hnmin⟩ := if_exists_first_exists (st := vldIn) (by grind) @@ -811,7 +791,7 @@ theorem vldIn_and_ready_implies_vldOut2 lemma fork_globallyValidAndData_out1 (hfork : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = - split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn)) + project_stream (rtl.fork rdOut1 rdOut2 vldIn dataIn)) (hgv : globallyValidAndData vldIn dataIn) : globallyValidAndData vldOut1 dataOut1 := by intro i ⟨hi1, hi2⟩ @@ -890,7 +870,7 @@ def readyOut2UntilAllReceiversAre (rdOut1 rdOut2 : Stream' (BitVec 1)) := theorem hw_fork_refines1_with_fork: /- Given a handshake fork taking `a` as input and returning `(a, a)`, we take its lowering (with input a bisimilar ready-valid wrapped stream) -/ - (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = split_stream2 (rtl.fork rdOut1 rdOut2 vldIn dataIn) → + (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = project_stream (rtl.fork rdOut1 rdOut2 vldIn dataIn) → /- We want to make sure that stalling is correctly modeled for `a` (input). We constrain the input and prove that if the input behaves properly, the output will. -/ @@ -1075,7 +1055,7 @@ theorem hw_fork_refines1_with_fork: · /- first receiver before sent -/ by_cases sndRecBeforeSent : fstVldTrue + fstRdyOut2 ≤ fstSentIdx · /- second receiver before sent -/ - simp [split_stream2] + simp [project_stream] and_intros · funext i have := rdOut1_before_allDone (hfork := h_6) (n := i) @@ -1094,7 +1074,7 @@ theorem hw_fork_refines1_with_fork: have : ∀ k, ∀ i, Stream'.drop k rdOut1_1 i = rdOut1_1 (i + k) := by intros simp [Stream'.drop, Stream'.get] - simp [hw_fork', Stream'.corec'] + simp [rtl.fork', Stream'.corec'] unfold fork_corec simp [comb_and, comb_xor, comb_or, hw_constant] @@ -1156,10 +1136,10 @@ theorem hw_fork_refines1_with_fork: -- rdIn fires at fstVldTrue + k with k < fstRdyOut, but rdOut1 hasn't fired have hh5 := h_6 rw [hw_fork_eq] at h_6 - simp [split_stream2] at h_6 + simp [project_stream] at h_6 obtain ⟨hrdin, -⟩ := h_6 have hcirc := congr_fun hrdin (fstVldTrue + k) - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hcirc + unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hcirc generalize hst : Stream'.iterate (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) (fstVldTrue + k) = s at hcirc @@ -1207,10 +1187,10 @@ theorem hw_fork_refines1_with_fork: have := @fork_corec1 rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 km simp [hsk] at this; omega have hvldk : vldOut1_1 km = vldIn_1 ak := by - rw [hw_fork_eq] at hh5; simp [split_stream2] at hh5 + rw [hw_fork_eq] at hh5; simp [project_stream] at hh5 obtain ⟨-, hvldout1, -⟩ := hh5 have hn := congr_fun hvldout1 km - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn + unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn simp_rw [hsk] at hn dsimp [fork_corec, comb_and, comb_xor, hw_constant] at hn simp [hn] @@ -1269,10 +1249,10 @@ theorem hw_fork_refines1_with_fork: by_contra hlt; push_neg at hlt have hh5 := h_6 rw [hw_fork_eq] at h_6 - simp [split_stream2] at h_6 + simp [project_stream] at h_6 obtain ⟨hrdin, -⟩ := h_6 have hcirc2 := congr_fun hrdin fstSentIdx - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hcirc2 + unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hcirc2 generalize hst2 : Stream'.iterate (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) fstSentIdx = s2 at hcirc2 @@ -1309,10 +1289,10 @@ theorem hw_fork_refines1_with_fork: have := @fork_corec1 rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 km simp [hsk] at this; omega have hvldk2 : vldOut1_1 km = vldIn_1 ak := by - rw [hw_fork_eq] at hh5; simp [split_stream2] at hh5 + rw [hw_fork_eq] at hh5; simp [project_stream] at hh5 obtain ⟨-, hvldout1, -⟩ := hh5 have hn := congr_fun hvldout1 km - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn + unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn simp_rw [hsk] at hn dsimp [fork_corec, comb_and, comb_xor, hw_constant] at hn simp [hn] @@ -1357,13 +1337,13 @@ theorem hw_fork_refines1_with_fork: (vld := vldIn_1) (by grind) h_7 /- the fork module will never transmit anything meaningful -/ rw [hw_fork_eq] at h_6 - unfold split_stream2 at h_6 + unfold project_stream at h_6 simp at h_6 have hhfork1 := h_6 obtain ⟨hrd', hvld1', hvld2', hdata1', hdata2'⟩ := hhfork1 rw [h_7, h_8] have hnoneout : ∀ k, vldOut1_1 k = 0#1 := by - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hvld1' + unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hvld1' intros k generalize hst : Stream'.iterate (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) k = s at hvld1' @@ -1376,7 +1356,7 @@ theorem hw_fork_refines1_with_fork: grind simp [this] have hnoneout2 : ∀ k, vldOut2_1 k = 0#1 := by - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hvld2' + unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hvld2' intros k generalize hst : Stream'.iterate (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) k = s at hvld2' @@ -1452,9 +1432,9 @@ theorem hw_fork_refines1_with_fork: rw [this, show i + j + 1 = i + 1 + j by omega, hj] · /- after dropping one element, all the relations defined by the fork module remain. We see this by unfolding the fork hypotheses -/ - unfold split_stream2 + unfold project_stream simp - have h1 := hw_fork'_of_all_none + have h1 := rtl.fork'_of_all_none (dataIn := Stream'.drop 1 dataIn_1) (vldIn := Stream'.drop 1 vldIn_1) (rdOut1 := Stream'.drop 1 rdOut1_1) @@ -1464,7 +1444,7 @@ theorem hw_fork_refines1_with_fork: specialize hnevldin (k + 1) simp [show Stream'.drop 1 vldIn_1 k = vldIn_1 (k + 1) by rfl, hnevldin] ) - have h2 := hw_fork'_of_all_none + have h2 := rtl.fork'_of_all_none (dataIn := dataIn_1) (vldIn := vldIn_1) (rdOut1 := rdOut1_1) @@ -1480,34 +1460,34 @@ theorem hw_fork_refines1_with_fork: (vld_in := vldIn_1) (rd0_in := rdOut1_1) (rd1_in := rdOut2_1) - (rdy_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).1) - (vld0_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.1) - (vld1_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.1) - (data0_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) - (data1_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) - (by rw [← hw_fork_eq]; simp [split_stream2]) (1 + l) + (rdy_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).1) + (vld0_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.1) + (vld1_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.1) + (data0_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) + (data1_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) + (by rw [← hw_fork_eq]; simp [project_stream]) (1 + l) have hrhs := hw_fork_out0 (rdy_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).1) + (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).1) (vld0_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.1) + (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.1) (vld1_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.1) + (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.1) (data0_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.1) + (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.1) (data1_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.2) - (by rw [← hw_fork_eq]; simp [split_stream2]) l + (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.2) + (by rw [← hw_fork_eq]; simp [project_stream]) l simp [Stream'.drop] at hrhs - have h1 : Stream'.get (fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) (1 + l) = - (fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) (1 + l) := by rfl + have h1 : Stream'.get (fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) (1 + l) = + (fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) (1 + l) := by rfl simp [h1] have h2 : (Stream'.get (fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) + (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.1) l) = (fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) + (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.1) l := by rfl simp [h2] @@ -1519,35 +1499,35 @@ theorem hw_fork_refines1_with_fork: (vld_in := vldIn_1) (rd0_in := rdOut1_1) (rd1_in := rdOut2_1) - (rdy_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).1) - (vld0_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.1) - (vld1_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.1) - (data0_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) - (data1_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) - (by rw [← hw_fork_eq]; simp [split_stream2]) (1 + l) + (rdy_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).1) + (vld0_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.1) + (vld1_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.1) + (data0_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) + (data1_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) + (by rw [← hw_fork_eq]; simp [project_stream]) (1 + l) have hrhs := hw_fork_out1 (rdy_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).1) + (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).1) (vld0_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.1) + (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.1) (vld1_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.1) + (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.1) (data0_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.1) + (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.1) (data1_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.2) - (by rw [← hw_fork_eq]; simp [split_stream2]) l + (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.2) + (by rw [← hw_fork_eq]; simp [project_stream]) l simp [Stream'.drop] at hrhs - have h1 : Stream'.get (fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) (1 + l) = - (fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) (1 + l) := by rfl + have h1 : Stream'.get (fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) (1 + l) = + (fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) (1 + l) := by rfl simp [h1] have h2 : (Stream'.get (fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) + (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.2) l) = (fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) + (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.2) l := by rfl simp [h2] @@ -1582,9 +1562,9 @@ theorem hw_fork_refines1_with_fork: theorem hw_fork_refines': /- Given a handshake fork -/ - (x, y) = TRY2.hw_fork a → + (x, y) = handshake.fork a → /- we get the output of the corresponding lowered fork -/ - (rdy, vld1, vld2, o1, o2) = split_stream2 (a := BitVec 1) (rtl.fork rd1 rd2 vld data) → + (rdy, vld1, vld2, o1, o2) = project_stream (a := BitVec 1) (rtl.fork rd1 rd2 vld data) → /- if we know that the hshake input stream is bisimilar to the ready-valid input of the hw fork -/ a ~ (toStream rdy vld data) → /- We want to make sure that stalling is correctly modeled for `a` (input). From 1deafa746906b66d0b557230c498873afb294f1e Mon Sep 17 00:00:00 2001 From: luisacicolini Date: Thu, 30 Apr 2026 14:07:25 +0100 Subject: [PATCH 05/13] wip --- .../CIRCT/HandshakeToHW/fork_lowering.lean | 64 +++++++++++-------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean b/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean index 16b3412e5c..93a757cc12 100644 --- a/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean +++ b/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean @@ -233,7 +233,7 @@ theorem fork'_vldOut2_of_none (h : ∀ k, vldIn k = 0#1) : simp [h] /-- - Applying a function `f` to + TODO: Luisa does not understand what the gist of this lemma is. -/ lemma iterate_back_succ (f : α → α) (s : α) (n : ℕ) : Stream'.iterate f s (n + 1) = f (Stream'.iterate f s n) := by @@ -241,8 +241,11 @@ lemma iterate_back_succ (f : α → α) (s : α) (n : ℕ) : | zero => simp [Stream'.iterate_eq, Stream'.cons] | succ k ih => rw [Stream'.iterate_eq, Stream'.cons, ih]; rfl +/-- + TODO: Luisa does not understand what the gist of this lemma is. +-/ lemma fork_emitted_zero_of_all_none (h : ∀ k, vldIn k = 0#1) : - ∀ k, (Stream'.iterate (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) + ∀ k, (Stream'.iterate (Prod.snd ∘ (fork_corec rdOut1 rdOut2 vldIn dataIn)) (0, 0#1, 0#1) k).2 = (0#1, 0#1) := by intro k induction k with @@ -258,8 +261,12 @@ lemma fork_emitted_zero_of_all_none (h : ∀ k, vldIn k = 0#1) : dsimp [fork_corec, comb_and, comb_xor, comb_or, hw_constant] simp [h a] --- when vld is always 0, all signal outputs (not data) are 0 -theorem rtl.fork'_of_all_none (h : ∀ k, vldIn k = 0#1) : +/-- + If the input's valid signal is always false, + for every point in time `k` the ready signal of the input and valid signals of the outputs of + a fork circuit are false as well. +-/ +theorem fork'_of_all_none (h : ∀ k, vldIn k = 0#1) : ∀ k, ((rtl.fork' rdOut1 rdOut2 vldIn dataIn) k).1 = 0#1 ∧ ((rtl.fork' rdOut1 rdOut2 vldIn dataIn) k).2.1 = 0#1 ∧ ((rtl.fork' rdOut1 rdOut2 vldIn dataIn) k).2.2.1 = 0#1 := by @@ -289,10 +296,12 @@ theorem rtl.fork'_of_all_none (h : ∀ k, vldIn k = 0#1) : specialize h a simp [h] -/-- Prove that (at RTL level) the input and output data at the `n`-th position are the same. - This is possible because `rtl.fork'` does not introduce any delay, and there is no transformation - happening on the data. -/ -theorem hw_fork_out0 +/-- + We prove that, at RTL level, the input and first output data stream at the `n`-th position are the same. + This is possible because `rtl.fork'` does not introduce any delay nor buffering, + and there is no transformation happening on the data. +-/ +theorem fork_dataIn_eq_dataOut1 (h : ⟨rdy_out, vld0_out, vld1_out, data0_out, data1_out⟩ = project_stream (rtl.fork' rd0_in rd1_in vld_in data_in)) : (∀ n, data_in n = data0_out n) := by intro n @@ -303,9 +312,14 @@ theorem hw_fork_out0 generalize h: (Stream'.iterate (Prod.snd ∘ fork_corec rd0_in rd1_in vld_in data_in) (0, 0#1, 0#1) n) = y obtain ⟨a, b, c⟩ := y dsimp [fork_corec] - rw [show a = (a, b, c).1 by rfl, ←h, fork_corec1]; rfl + rw [show a = (a, b, c).1 by rfl, ← h, fork_corec_iter]; rfl -theorem hw_fork_out1 +/-- + We prove that, at RTL level, the input and second output data stream at the `n`-th position are the same. + This is possible because `rtl.fork'` does not introduce any delay nor buffering, + and there is no transformation happening on the data. +-/ +theorem fork_dataIn_eq_dataOut2 (h : ⟨rdy_out, vld0_out, vld1_out, data0_out, data1_out⟩ = project_stream (rtl.fork' rd0_in rd1_in vld_in data_in)) : (∀ n, data_in n = data1_out n) := by @@ -317,25 +331,19 @@ theorem hw_fork_out1 generalize h: (Stream'.iterate (Prod.snd ∘ fork_corec rd0_in rd1_in vld_in data_in) (0, 0#1, 0#1) n) = y obtain ⟨a, b, c⟩ := y dsimp [fork_corec] - rw [show a = (a, b, c).1 by rfl, ←h, fork_corec1]; rfl - - - - -theorem fork_corec1bis : - (Stream'.iterate (Prod.snd ∘ fork_corec rd0_in rd1_in vld_in data_in) (m, x, y) n).1 = n + m := by - induction n generalizing m x y with - | zero => grind [Stream'.iterate] - | succ x h => - rw [Stream'.iterate_eq] - dsimp [Stream'.cons] - dsimp [fork_corec] - grind + rw [show a = (a, b, c).1 by rfl, ← h, fork_corec_iter]; rfl +/-- + Prove the equivalence of the two definitions of `rtl.fork`. +-/ theorem hw_fork_eq : rtl.fork rd0 rd1 vld data = rtl.fork' rd0 rd1 vld data := by unfold rtl.fork rtl.fork' congr 1 +/-- + If at a certain point in time `n` the first output valid signal is true, + then the input valid signal at that point in time is also true. +-/ theorem vldOut1_implies_vldIn (h : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = project_stream (rtl.fork rdOut1 rdOut2 vldIn dataIn)) @@ -351,7 +359,7 @@ theorem vldOut1_implies_vldIn obtain ⟨a, b, c⟩ := s dsimp [fork_corec, comb_and, comb_xor, hw_constant] at hn have heq : a = n := by - have := @fork_corec1 rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 n + have := @fork_corec_iter rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 n rw [hst] at this simp at this assumption @@ -361,6 +369,10 @@ theorem vldOut1_implies_vldIn have : vldIn a = 0#1 := by grind simp [this] at hn +/-- + If at a certain point in time `n` the second output valid signal is true, + then the input valid signal at that point in time is also true. +-/ theorem vldOut2_implies_vldIn (h : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = project_stream (rtl.fork rdOut1 rdOut2 vldIn dataIn)) @@ -376,7 +388,7 @@ theorem vldOut2_implies_vldIn obtain ⟨a, b, c⟩ := s dsimp [fork_corec, comb_and, comb_xor, hw_constant] at hn have heq : a = n := by - have := @fork_corec1 rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 n + have := @fork_corec_iter rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 n rw [hst] at this simp at this assumption From a47417b5e6ac04b67f68c4dcc7054ceb6169a15e Mon Sep 17 00:00:00 2001 From: luisacicolini Date: Thu, 30 Apr 2026 18:18:32 +0100 Subject: [PATCH 06/13] more polishing --- .../CIRCT/HandshakeToHW/fork_lowering.lean | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean b/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean index 93a757cc12..8eeaa79fba 100644 --- a/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean +++ b/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean @@ -398,6 +398,11 @@ theorem vldOut2_implies_vldIn have : vldIn a = 0#1 := by grind simp [this] at hn +/-- + In a fork component with no-deadlock guarantees, there always exists a point in time + when both the ready and the valid input signals are true, and therefore a valid input + data signal arrives. +-/ theorem rdOut1_before_allDone (hfork : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = project_stream (rtl.fork rdOut1 rdOut2 vldIn dataIn)) (hvldOut1 : vldOut1 n = 1#1) @@ -410,16 +415,10 @@ theorem rdOut1_before_allDone exists k simp [hk] -lemma iterate_succ_apply (f : α → α) (s : α) (n : ℕ) : - Stream'.iterate f s (n + 1) = f (Stream'.iterate f s n) := by - induction n generalizing s with - | zero => simp [Stream'.iterate] - | succ k ih => - rw [Stream'.iterate_eq, Stream'.cons] - exact ih _ - - - +/-- + In a fork circuit, at all points in time that come before the first element is transmitted, + the input and output valid signal have the same value. +-/ theorem vldOut_eq_vldIn_of_fork_unitl_sent (hfork : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = project_stream (rtl.fork rdOut1 rdOut2 vldIn dataIn)) @@ -458,7 +457,7 @@ theorem vldOut_eq_vldIn_of_fork_unitl_sent simp [hsk] at hbk; subst hbk rw [iterate_back_succ, hsk] have hak : ak = k := by - have := @fork_corec1 rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 k + have := @fork_corec_iter rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 k simp [hsk] at this; omega have hk := hbef k (Nat.lt_succ_self k) simp only [Function.comp] @@ -508,7 +507,7 @@ theorem vldOut_eq_vldIn_of_fork_unitl_sent simp [h1] simp [hb] at hn have heq : a = n := by - have := @fork_corec1 rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 n + have := @fork_corec_iter rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 n rw [hst] at this simp at this assumption From aafba0ec5bebda5905fe5a2de3dbfb7f4d480356 Mon Sep 17 00:00:00 2001 From: luisacicolini Date: Thu, 16 Jul 2026 15:17:19 +0100 Subject: [PATCH 07/13] library --- SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean | 10 + .../CIRCT/HandshakeToHW/HWForkSampling.lean | 732 ++++++++++++++++++ .../CIRCT/HandshakeToHW/fork_lowering.lean | 39 +- 3 files changed, 771 insertions(+), 10 deletions(-) create mode 100644 SSA/Projects/CIRCT/HandshakeToHW/HWForkSampling.lean diff --git a/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean b/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean index c13b164b7e..c4367340b5 100644 --- a/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean +++ b/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean @@ -10,14 +10,19 @@ open HandshakeStream /- RTL-level definitions of circuit components -/ +@[bv_normalize, grind] def hw_constant (b : Bool) : BitVec 1 := if b then 1#1 else 0#1 +@[bv_normalize, grind] def comb_xor (x y : BitVec 1) : BitVec 1 := BitVec.xor x y +@[bv_normalize, grind] def comb_and (x y : BitVec 1) : BitVec 1 := BitVec.and x y +@[bv_normalize, grind] def comb_add (x y : BitVec 32) : BitVec 32 := BitVec.add x y +@[bv_normalize, grind] def comb_or (x y : BitVec 1) : BitVec 1 := BitVec.or x y namespace TRY1 @@ -270,6 +275,11 @@ inductive relation' : Stream (BitVec w) → Stream (BitVec w) → Prop where (∀ n, vld n = 1#1 → data n = o1 n) → /- when the signal is valid, data and output are the same -/ relation' x y /- defining the type of the relation -/ + +/- + `(rdIn, vldOut1, ...) = TRY3.split_stream2 (TRY3.hw_fork rdOut1 rdOut2 vldIn dataIn)` + and `TRY3.hw_fork` starts from `(0, 0#1, 0#1)`. In the coinductive step you must re-establish relation_fork for the dropped streams — which requires the dropped streams to again satisfy the fork equation from registers (0,0). That only holds if you cut at an instant where both emitted registers are actually 0, i.e. right after allDone fired. But the proof cuts at fstVldTrue + fstRdyOut + 1 — the instant out1 fired — and out2 may not have fired yet, so _emitted_0 = 1 at the cut and the restarted equation is false. The fix is to generalize the relation over register state: parameterize it by (e₀, e₁) (or quantify over a start state) and make hw_fork' take an initial state argument. Alternatively cut at the first allDone instant instead of the first out1 firing +-/ inductive relation_fork : Stream (BitVec w) → Stream (BitVec w) → Prop where | intro x y rdIn vldIn dataIn rdOut1 vldOut1 dataOut1 rdOut2 vldOut2 dataOut2 : /- same as `∀ x y` -/ /- x is the high-level (input), y is the low-level (output) -/ diff --git a/SSA/Projects/CIRCT/HandshakeToHW/HWForkSampling.lean b/SSA/Projects/CIRCT/HandshakeToHW/HWForkSampling.lean new file mode 100644 index 0000000000..f20a36a277 --- /dev/null +++ b/SSA/Projects/CIRCT/HandshakeToHW/HWForkSampling.lean @@ -0,0 +1,732 @@ +import SSA.Projects.CIRCT.HandshakeToHW.HWFork + +/-! +# Transaction-level sampling of the `fork` circuit — definitions + +Refactoring of the fork refinement around the *`allDone` sampling* idea: + +* The refinement theorem `toStream rdIn vldIn dataIn ~ toStream rdOut1 vldOut1 dataOut1` + is factored through a third, auxiliary stream: output 1 *sampled at `allDone`*, + i.e. observed only when **all** receivers have received the current token. +* Since `rdIn = allDone` and `dataOut1 = dataIn` hold pointwise in the circuit, + the sampled stream is *equal* to the input stream. All bisimulation content + is then concentrated in one lemma (`out1_sampling_bisim`): moving each token's + observation instant from receiver 1's accept (`fire1`) to the transaction's + completion (`allDone`) only changes the stream by finitely many `none`s. + The producer interprets rdIn = 1 as "this token is consumed — I may present the next one." + + +Layout: +1. register trajectory (`emitted`) as a plain recursion over time, and named + combinational signals (`fire1`, `done0`, `allDone`, ...); +2. pointwise characterization of `hw_fork'` (`hw_fork'_get`) — the only place + `Stream'.corec'` ever needs to be unfolded; +3. statements for the library of circuit facts (the intermediate predicates, + *derived* from the circuit rather than assumed); +4. the coinduction relation `SampleRel` and the statements of + `out1_sampling_bisim` and `hw_fork_refines_out1`. +-/ + +namespace HWComponents +namespace Fork + +open HandshakeStream + +/-! ## Boolean infrastructure on `BitVec 1` -/ + +theorem comb_and_eq_one_iff (a b : BitVec 1) : + comb_and a b = 1#1 ↔ a = 1#1 ∧ b = 1#1 := by + bv_decide + +theorem comb_and_eq_zero_iff (a b : BitVec 1) : + comb_and a b = 0#1 ↔ a = 0#1 ∨ b = 0#1 := by + bv_decide + +theorem comb_or_eq_one_iff (a b : BitVec 1) : + comb_or a b = 1#1 ↔ a = 1#1 ∨ b = 1#1 := by + bv_decide + +theorem comb_or_eq_zero_iff (a b : BitVec 1) : + comb_or a b = 0#1 ↔ a = 0#1 ∧ b = 0#1 := by + bv_decide + +theorem comb_not_eq_one_iff (a : BitVec 1) : + comb_xor a (hw_constant true) = 1#1 ↔ a = 0#1 := by + bv_decide + +theorem comb_not_eq_zero_iff (a : BitVec 1) : + comb_xor a (hw_constant true) = 0#1 ↔ a = 1#1 := by + bv_decide + +/-! ## The register trajectory, as a plain recursion over time + +Instead of reasoning through `Stream'.corec'`/`Stream'.iterate`, we define the +`emitted` registers as a recursive function of the cycle index. Every signal of +the circuit then becomes a pure function of the current cycle. -/ + +/-- One clock cycle of the fork's register update. `e.1`/`e.2` are the +`emitted` registers of output 1/output 2. This is (definitionally) the state +update performed by `fork_corec`. -/ +def stepRegs (rd1 rd2 vld : BitVec 1) (e : BitVec 1 × BitVec 1) : + BitVec 1 × BitVec 1 := + let fire1 := comb_and rd1 (comb_and (comb_xor e.1 (hw_constant true)) vld) + let fire2 := comb_and rd2 (comb_and (comb_xor e.2 (hw_constant true)) vld) + let done0 := comb_or fire1 e.1 + let done1 := comb_or fire2 e.2 + let allDone := comb_and done0 done1 -- `_12` in `hw_fork` + (comb_and done0 (comb_xor allDone (hw_constant true)), + comb_and done1 (comb_xor allDone (hw_constant true))) + +variable (rdOut1 rdOut2 vldIn : Stream' (BitVec 1)) + +/-- The trajectory of the fork's `emitted` registers over time. -/ +def emitted : Nat → BitVec 1 × BitVec 1 + | 0 => (0#1, 0#1) + | n + 1 => stepRegs (rdOut1 n) (rdOut2 n) (vldIn n) (emitted n) + +/-- `e0 n = 1` iff receiver 1 has already accepted the token of the transaction +that is still open at cycle `n`. -/ +def e0 (n : Nat) : BitVec 1 := (emitted rdOut1 rdOut2 vldIn n).1 + +/-- `e1 n = 1` iff receiver 2 has already accepted the token of the transaction +that is still open at cycle `n`. -/ +def e1 (n : Nat) : BitVec 1 := (emitted rdOut1 rdOut2 vldIn n).2 + +/-- The fork's `valid` signal on output 1 (`_3` in the MLIR output). -/ +def vldOut1 (n : Nat) : BitVec 1 := + comb_and (comb_xor (e0 rdOut1 rdOut2 vldIn n) (hw_constant true)) (vldIn n) + +/-- The fork's `valid` signal on output 2 (`_9` in the MLIR output). -/ +def vldOut2 (n : Nat) : BitVec 1 := + comb_and (comb_xor (e1 rdOut1 rdOut2 vldIn n) (hw_constant true)) (vldIn n) + +/-- Receiver 1 accepts a token at cycle `n` (`_4` in the MLIR output). -/ +def fire1 (n : Nat) : BitVec 1 := + comb_and (rdOut1 n) (vldOut1 rdOut1 rdOut2 vldIn n) + +/-- Receiver 2 accepts a token at cycle `n` (`_10` in the MLIR output). -/ +def fire2 (n : Nat) : BitVec 1 := + comb_and (rdOut2 n) (vldOut2 rdOut1 rdOut2 vldIn n) + +/-- Receiver 1 has received the current token, now or earlier (`done0`, `_5`). -/ +def done0 (n : Nat) : BitVec 1 := + comb_or (fire1 rdOut1 rdOut2 vldIn n) (e0 rdOut1 rdOut2 vldIn n) + +/-- Receiver 2 has received the current token, now or earlier (`done1`, `_11`). -/ +def done1 (n : Nat) : BitVec 1 := + comb_or (fire2 rdOut1 rdOut2 vldIn n) (e1 rdOut1 rdOut2 vldIn n) + +/-- All receivers have received the current token; this is also the fork's +`ready` signal towards the producer (`allDone`, `_12`). -/ +def allDone (n : Nat) : BitVec 1 := + comb_and (done0 rdOut1 rdOut2 vldIn n) (done1 rdOut1 rdOut2 vldIn n) + +/-! Definitional equations for the registers (all `rfl`). -/ + +@[simp] theorem e0_zero : e0 rdOut1 rdOut2 vldIn 0 = 0#1 := rfl +@[simp] theorem e1_zero : e1 rdOut1 rdOut2 vldIn 0 = 0#1 := rfl + +theorem e0_succ (n : Nat) : + e0 rdOut1 rdOut2 vldIn (n + 1) + = comb_and (done0 rdOut1 rdOut2 vldIn n) + (comb_xor (allDone rdOut1 rdOut2 vldIn n) (hw_constant true)) := rfl + +theorem e1_succ (n : Nat) : + e1 rdOut1 rdOut2 vldIn (n + 1) + = comb_and (done1 rdOut1 rdOut2 vldIn n) + (comb_xor (allDone rdOut1 rdOut2 vldIn n) (hw_constant true)) := rfl + +/-! Unfolding equations for the combinational signals (all `rfl`). These +signals have no state of their own, so their `_def` equations hold at *every* +cycle; use them with `rw`/`simp` instead of `unfold`. -/ + +theorem vldOut1_def (n : Nat) : + vldOut1 rdOut1 rdOut2 vldIn n + = comb_and (comb_xor (e0 rdOut1 rdOut2 vldIn n) (hw_constant true)) + (vldIn n) := rfl + +theorem vldOut2_def (n : Nat) : + vldOut2 rdOut1 rdOut2 vldIn n + = comb_and (comb_xor (e1 rdOut1 rdOut2 vldIn n) (hw_constant true)) + (vldIn n) := rfl + +theorem fire1_def (n : Nat) : + fire1 rdOut1 rdOut2 vldIn n + = comb_and (rdOut1 n) (vldOut1 rdOut1 rdOut2 vldIn n) := rfl + +theorem fire2_def (n : Nat) : + fire2 rdOut1 rdOut2 vldIn n + = comb_and (rdOut2 n) (vldOut2 rdOut1 rdOut2 vldIn n) := rfl + +theorem done0_def (n : Nat) : + done0 rdOut1 rdOut2 vldIn n + = comb_or (fire1 rdOut1 rdOut2 vldIn n) (e0 rdOut1 rdOut2 vldIn n) := rfl + +theorem done1_def (n : Nat) : + done1 rdOut1 rdOut2 vldIn n + = comb_or (fire2 rdOut1 rdOut2 vldIn n) (e1 rdOut1 rdOut2 vldIn n) := rfl + +theorem allDone_def (n : Nat) : + allDone rdOut1 rdOut2 vldIn n + = comb_and (done0 rdOut1 rdOut2 vldIn n) + (done1 rdOut1 rdOut2 vldIn n) := rfl + +/-! `_succ` forms (all `rfl`): the cycle-`n + 1` value of each signal with the +register occurrence expanded one step, i.e. in terms of cycle-`n` signals and +cycle-`n + 1` inputs. The combinational signals are stateless, so all the +`succ`-structure funnels through `e0_succ`/`e1_succ`; these lemmas just +pre-compose that register step with the `_def` equations, which is the shape an +`induction n` proof consumes. -/ + +theorem vldOut1_succ (n : Nat) : + vldOut1 rdOut1 rdOut2 vldIn (n + 1) + = comb_and + (comb_xor + (comb_and (done0 rdOut1 rdOut2 vldIn n) + (comb_xor (allDone rdOut1 rdOut2 vldIn n) (hw_constant true))) + (hw_constant true)) + (vldIn (n + 1)) := rfl + +theorem vldOut2_succ (n : Nat) : + vldOut2 rdOut1 rdOut2 vldIn (n + 1) + = comb_and + (comb_xor + (comb_and (done1 rdOut1 rdOut2 vldIn n) + (comb_xor (allDone rdOut1 rdOut2 vldIn n) (hw_constant true))) + (hw_constant true)) + (vldIn (n + 1)) := rfl + +theorem fire1_succ (n : Nat) : + fire1 rdOut1 rdOut2 vldIn (n + 1) + = comb_and (rdOut1 (n + 1)) + (comb_and + (comb_xor + (comb_and (done0 rdOut1 rdOut2 vldIn n) + (comb_xor (allDone rdOut1 rdOut2 vldIn n) (hw_constant true))) + (hw_constant true)) + (vldIn (n + 1))) := rfl + +theorem fire2_succ (n : Nat) : + fire2 rdOut1 rdOut2 vldIn (n + 1) + = comb_and (rdOut2 (n + 1)) + (comb_and + (comb_xor + (comb_and (done1 rdOut1 rdOut2 vldIn n) + (comb_xor (allDone rdOut1 rdOut2 vldIn n) (hw_constant true))) + (hw_constant true)) + (vldIn (n + 1))) := rfl + +theorem done0_succ (n : Nat) : + done0 rdOut1 rdOut2 vldIn (n + 1) + = comb_or (fire1 rdOut1 rdOut2 vldIn (n + 1)) + (comb_and (done0 rdOut1 rdOut2 vldIn n) + (comb_xor (allDone rdOut1 rdOut2 vldIn n) (hw_constant true))) := rfl + +theorem done1_succ (n : Nat) : + done1 rdOut1 rdOut2 vldIn (n + 1) + = comb_or (fire2 rdOut1 rdOut2 vldIn (n + 1)) + (comb_and (done1 rdOut1 rdOut2 vldIn n) + (comb_xor (allDone rdOut1 rdOut2 vldIn n) (hw_constant true))) := rfl + +theorem allDone_succ (n : Nat) : + allDone rdOut1 rdOut2 vldIn (n + 1) + = comb_and + (comb_or (fire1 rdOut1 rdOut2 vldIn (n + 1)) + (comb_and (done0 rdOut1 rdOut2 vldIn n) + (comb_xor (allDone rdOut1 rdOut2 vldIn n) (hw_constant true)))) + (comb_or (fire2 rdOut1 rdOut2 vldIn (n + 1)) + (comb_and (done1 rdOut1 rdOut2 vldIn n) + (comb_xor (allDone rdOut1 rdOut2 vldIn n) (hw_constant true)))) := rfl + +/-! ## `hw_fork'`, pointwise -/ + +/-- The iteration of `fork_corec`'s state update is `(n, emitted n)`. +Subsumes `fork_corec1`. (Induction on `n` via `iterate_back_succ`.) -/ +theorem iterate_eq_emitted (dataIn : Stream' (BitVec 32)) (n : Nat) : + Stream'.iterate (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) + (0, 0#1, 0#1) n + = (n, emitted rdOut1 rdOut2 vldIn n) := by + induction n + · simp [emitted, Stream'.iterate] + · case _ m ihm => + simp [Stream'.iterate, ihm] + unfold fork_corec + simp [emitted, stepRegs] + +/-- Pointwise characterization of the fork circuit: at each cycle the outputs +are the combinational signals computed from the current register state and the +current inputs. This is the only lemma that ever needs to unfold +`Stream'.corec'`; everything downstream uses it via `rw`/`simp`. -/ +theorem hw_fork'_get (dataIn : Stream' (BitVec 32)) (n : Nat) : + hw_fork' rdOut1 rdOut2 vldIn dataIn n + = (allDone rdOut1 rdOut2 vldIn n, + vldOut1 rdOut1 rdOut2 vldIn n, + vldOut2 rdOut1 rdOut2 vldIn n, + dataIn n, dataIn n) := by + unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get + rw [iterate_eq_emitted] + rfl + +/-! ## Library of circuit facts + +The intermediate predicates describing the fork's behaviour, stated as +*derived* facts about the circuit (not assumptions). -/ + +/-- `allDone` holds exactly when *every* receiver has received the current +token — accepting it this cycle (`fireᵢ`) or having accepted it earlier +(`emittedᵢ`). This is the circuit-level meaning of "allDone is such after all +receivers have received". -/ +theorem allDone_iff_all_received (n : Nat) : + allDone rdOut1 rdOut2 vldIn n = 1#1 + ↔ (fire1 rdOut1 rdOut2 vldIn n = 1#1 ∨ e0 rdOut1 rdOut2 vldIn n = 1#1) + ∧ (fire2 rdOut1 rdOut2 vldIn n = 1#1 ∨ e1 rdOut1 rdOut2 vldIn n = 1#1) := by + rw [allDone_def, done0_def, done1_def] + bv_decide + +/-- If receiver 1 accepts at cycle `n`, then the receiver is ready, output 1 is +valid, a token is being presented, and the receiver had not accepted the +current token before. -/ +theorem fire1_spec {n : Nat} (h : fire1 rdOut1 rdOut2 vldIn n = 1#1) : + rdOut1 n = 1#1 ∧ vldOut1 rdOut1 rdOut2 vldIn n = 1#1 + ∧ vldIn n = 1#1 ∧ e0 rdOut1 rdOut2 vldIn n = 0#1 := by + rw [fire1_def, vldOut1_def] at h + rw [vldOut1_def] + bv_decide + +/-- The fork does not offer the same token twice: output 1 is not valid while +its receiver has already accepted the current token. -/ +theorem vldOut1_zero_of_e0_one {n : Nat} + (h : e0 rdOut1 rdOut2 vldIn n = 1#1) : + vldOut1 rdOut1 rdOut2 vldIn n = 0#1 := by + rw [vldOut1_def] + bv_decide + +/-- Receiver 1 cannot accept while it has already accepted the current token. -/ +theorem fire1_zero_of_e0_one {n : Nat} (h : e0 rdOut1 rdOut2 vldIn n = 1#1) : + fire1 rdOut1 rdOut2 vldIn n = 0#1 := by + rw [fire1_def, vldOut1_def] + bv_decide + +/-- If output 1 is quiet (register clear, no accept), the transaction cannot +complete this cycle. -/ +theorem allDone_zero_of_quiet {n : Nat} + (he : e0 rdOut1 rdOut2 vldIn n = 0#1) + (hf : fire1 rdOut1 rdOut2 vldIn n = 0#1) : + allDone rdOut1 rdOut2 vldIn n = 0#1 := by + rw [allDone_def] + rw [fire1_def] at hf + rw [done0_def, fire1_def] + bv_decide + +/-- The `emitted` registers are mutually exclusive: at most one output can be +waiting for the other to catch up. (Case on `n`; for `n + 1` both registers +being set would require `allDone n = 1` and `allDone n = 0` at once.) -/ +theorem e0_e1_not_both {n : Nat} : + ¬(e0 rdOut1 rdOut2 vldIn n = 1#1 ∧ e1 rdOut1 rdOut2 vldIn n = 1#1) := by + induction n + · simp [e0_zero, e1_zero] + · simp [e0_succ, e1_succ, allDone_def] + bv_decide + +/-- `allDone` only fires while a token is actually being presented. +(Via `allDone_iff_all_received` and `e0_e1_not_both`.) -/ +theorem vldIn_of_allDone {n : Nat} + (h : allDone rdOut1 rdOut2 vldIn n = 1#1) : vldIn n = 1#1 := by + induction n + · simp [allDone_def, done0_def, done1_def, fire1_def, fire2_def, vldOut1_def] at h + bv_decide + · simp [allDone_succ, fire1_succ, fire2_succ, allDone_def] at h + bv_decide + +/-- Once the transaction completes, the register of output 1 is cleared. -/ +theorem e0_zero_of_allDone {n : Nat} + (h : allDone rdOut1 rdOut2 vldIn n = 1#1) : + e0 rdOut1 rdOut2 vldIn (n + 1) = 0#1 := by + simp [allDone_def, done0_def, done1_def, fire1_def, fire2_def, vldOut1_def, vldOut2_def] at h + simp [e0_succ, done0_def, allDone_def, fire1_def, vldOut1_def, done1_def, fire2_def, vldOut2_def] + bv_decide + +/-- While receiver 1 does not accept, its register stays clear. +(Induction via `Nat.le_induction`.) -/ +theorem e0_zero_of_no_fire {m n : Nat} (hmn : m ≤ n) + (h0 : e0 rdOut1 rdOut2 vldIn m = 0#1) + (hf : ∀ t, m ≤ t → t < n → fire1 rdOut1 rdOut2 vldIn t = 0#1) : + e0 rdOut1 rdOut2 vldIn n = 0#1 := by + induction n + · simp + · case _ t iht => + by_cases hle : m ≤ t + · specialize iht (by omega) (by intros; apply hf <;> omega) + specialize hf t + specialize hf hle (by omega) + simp [e0_succ, allDone_def, done0_def, done1_def] + simp [hf] + simp [comb_and, comb_or, comb_xor, hw_constant] + simp [fire2_def, comb_and, vldOut2, comb_xor, hw_constant] + simp [iht] + · have : m = t + 1 := by omega + subst this + simp [h0] + +/-- After receiver 1 accepts at `F`, its register stays set until the +transaction completes: `e0` is 1 on the whole window `(F, n]` as long as +`allDone` has not fired on `[F, n)`. (Induction via `Nat.le_induction`.) -/ +theorem e0_one_of_window {F n : Nat} (hFn : F < n) + (hF : fire1 rdOut1 rdOut2 vldIn F = 1#1) + (hAD : ∀ t, F ≤ t → t < n → allDone rdOut1 rdOut2 vldIn t = 0#1) : + e0 rdOut1 rdOut2 vldIn n = 1#1 := by + induction n + · omega -- contra + · case _ m ihm => + simp [e0_succ] + by_cases hlt : F < m + · specialize ihm hlt (by intros; apply hAD <;> omega) + specialize hAD m (by omega) (by omega) + simp [hAD] + simp [fire1, vldOut1_def, comb_and, comb_xor, hw_constant] at hF + simp [done0_def, fire1_def, vldOut1_def, ihm, + comb_and, comb_or, comb_xor, hw_constant] + · simp [show F = m by omega] at * + specialize hAD m (by omega) (by omega) + simp [hAD] + simp [done0, hF] + bv_decide + +/-- **Data is constant until all receivers have received.** Whenever a token is +presented, the transaction eventually completes (`allDone`), the token stays +valid throughout, and the data does not change until completion. This is the +predicate "data remains constant until all receivers have received", *derived* +from the handshake contracts and `data_remains_constant_until_first`. -/ +theorem dataIn_constant_until_allDone {dataIn : Stream' (BitVec 32)} + (hvr : globallyValidUntilReady vldIn (allDone rdOut1 rdOut2 vldIn)) + (hvd : globallyValidAndData vldIn dataIn) + {i : Nat} (hi : vldIn i = 1#1) : + ∃ k, allDone rdOut1 rdOut2 vldIn (i + k) = 1#1 ∧ vldIn (i + k) = 1#1 ∧ + (∀ j (_hj : j ≤ k), vldIn (i + j) = 1#1) ∧ + (∀ j (_hj : j ≤ k), dataIn (i + j) = dataIn i) ∧ + (∀ m (_hm : m < k), allDone rdOut1 rdOut2 vldIn (i + m) = 0#1) := + data_remains_constant_until_first hvd hvr hi + +/-! ## The two views of output 1 -/ + +/-- The *receiver-1 view* of output 1: a token is observed at the cycle where +receiver 1 accepts it (`fire1`). This is what receiver 1 actually sees on the +wires, waiting (`none`) included. -/ +def out1View (dataIn : Stream' (BitVec 32)) : Stream (BitVec 32) := + toStream rdOut1 (vldOut1 rdOut1 rdOut2 vldIn) dataIn + +/-- The *transaction-level view* of output 1: a token is observed only at the +cycle where the whole transaction completes (`allDone`), i.e. after **all** +receivers have received it. Note that, pointwise, this is exactly +`toStream rdIn vldIn dataIn` — the input stream — since `rdIn = allDone` and +`dataOut1 = dataIn` in the circuit (`hw_fork'_get`). -/ +def sampledView (dataIn : Stream' (BitVec 32)) : Stream (BitVec 32) := + toStream (allDone rdOut1 rdOut2 vldIn) vldIn dataIn + +/-! `get`-characterizations of the two views: each view is `some` exactly at +its observation instants (`fire1` resp. `allDone`). -/ + +theorem out1View_get_none {dataIn : Stream' (BitVec 32)} {t : Nat} + (h : fire1 rdOut1 rdOut2 vldIn t = 0#1) : + Stream'.get (out1View rdOut1 rdOut2 vldIn dataIn) t = none := by + rw [fire1_def, comb_and_eq_zero_iff] at h + rcases h with h | h <;> simp [out1View, toStream, Stream'.get, h] + +theorem out1View_get_some {dataIn : Stream' (BitVec 32)} {t : Nat} + (h : fire1 rdOut1 rdOut2 vldIn t = 1#1) : + Stream'.get (out1View rdOut1 rdOut2 vldIn dataIn) t = some (dataIn t) := by + obtain ⟨h1, h2, -, -⟩ := fire1_spec rdOut1 rdOut2 vldIn h + simp [out1View, toStream, Stream'.get, h1, h2] + +theorem sampledView_get_none {dataIn : Stream' (BitVec 32)} {t : Nat} + (h : allDone rdOut1 rdOut2 vldIn t = 0#1) : + Stream'.get (sampledView rdOut1 rdOut2 vldIn dataIn) t = none := by + simp [sampledView, toStream, Stream'.get, h] + +theorem sampledView_get_some {dataIn : Stream' (BitVec 32)} {t : Nat} + (h : allDone rdOut1 rdOut2 vldIn t = 1#1) : + Stream'.get (sampledView rdOut1 rdOut2 vldIn dataIn) t = some (dataIn t) := by + simp [sampledView, toStream, Stream'.get, h, + vldIn_of_allDone rdOut1 rdOut2 vldIn h] + +/-- If receiver 1 never accepts from cycle `m` on, the receiver-1 view is +silent from `m` on. -/ +theorem out1View_none_of_no_fire {dataIn : Stream' (BitVec 32)} {m : Nat} + (hf : ∀ t, m ≤ t → fire1 rdOut1 rdOut2 vldIn t = 0#1) : + ∀ t, m ≤ t → Stream'.get (out1View rdOut1 rdOut2 vldIn dataIn) t = none := + fun t ht => out1View_get_none rdOut1 rdOut2 vldIn (hf t ht) + +/-- If receiver 1 never accepts from cycle `m` on (and its register is clear +at `m`), then no transaction ever completes from `m` on: the handshake-level +(transaction-sampled) stream is silent forever. This is the "one stalled +receiver blocks the whole fork" behaviour. -/ +theorem sampledView_none_of_no_fire {dataIn : Stream' (BitVec 32)} {m : Nat} + (he : e0 rdOut1 rdOut2 vldIn m = 0#1) + (hf : ∀ t, m ≤ t → fire1 rdOut1 rdOut2 vldIn t = 0#1) : + ∀ t, m ≤ t → Stream'.get (sampledView rdOut1 rdOut2 vldIn dataIn) t = none := by + intro t ht + refine sampledView_get_none rdOut1 rdOut2 vldIn ?_ + refine allDone_zero_of_quiet rdOut1 rdOut2 vldIn ?_ (hf t ht) + exact e0_zero_of_no_fire rdOut1 rdOut2 vldIn ht he + (fun s hs1 _ => hf s hs1) + + +/-! ## The sampling bisimulation -/ + +/-- Coinduction relation for `out1_sampling_bisim`. Both streams are *tails of +one fixed run* of the circuit, cut at `tA` (receiver-1 view) and `tB` +(transaction-level view). The invariant ties the two cut points together +through the register: `e0` is set exactly on the skew window `[tA, tB)`, i.e. +receiver 1 has already been served the transaction that is still open at the +input side, and `tB` sits at a transaction boundary (`e0 tB = 0`). + +Keeping the *original* streams (cut, never restarted) means the circuit +equation and the handshake contracts never have to be re-established on +suffixes inside the coinduction. -/ +inductive SampleRel (rdOut1 rdOut2 vldIn : Stream' (BitVec 1)) + (dataIn : Stream' (BitVec 32)) : + Stream (BitVec 32) → Stream (BitVec 32) → Prop where + /-- Both streams are silent forever: no token will ever be exchanged again. + (Reached when no receiver-1 accept ever happens after the cut.) -/ + | stuck (a b : Stream (BitVec 32)) + (ha : ∀ i, Stream'.get a i = none) + (hb : ∀ j, Stream'.get b j = none) : + SampleRel rdOut1 rdOut2 vldIn dataIn a b + /-- Tails of one fixed run, with the `e0` window invariant. -/ + | cut (a b : Stream (BitVec 32)) (tA tB : Nat) + (ha : a = Stream'.drop tA (out1View rdOut1 rdOut2 vldIn dataIn)) + (hb : b = Stream'.drop tB (sampledView rdOut1 rdOut2 vldIn dataIn)) + (htAB : tA ≤ tB) + (hwin : ∀ t, tA ≤ t → t < tB → e0 rdOut1 rdOut2 vldIn t = 1#1) + (he0 : e0 rdOut1 rdOut2 vldIn tB = 0#1) : + SampleRel rdOut1 rdOut2 vldIn dataIn a b + + +theorem sampleRel_of_nones (hs1 : ∀ t, s1 t = none) (hs3 : ∀ t, s2 t = none) : + SampleRel rdOut1 rdOut2 vldIn dataIn s1 s2 := by + exact SampleRel.stuck s1 s2 hs1 hs3 + +/-- **Sampling output 1 when receiver 1 accepts, and sampling it when the whole +transaction completes (`allDone`), yield bisimilar streams.** Moving each +token's observation instant from `fire1` to `allDone` changes the stream only +by finitely many `none`s. This is the essential correctness content of the +fork: every presented token is delivered exactly once to receiver 1, with the +value it has at completion time. + +Proof plan (`Bisim.coinduct` with `pred := SampleRel ...`): +* `stuck` case: match `none` with `none` at `0`, stay `stuck`. +* `cut` case, no `fire1` at or after `tA`: both tails are all-`none` + (`e0_zero_of_no_fire` + `allDone_zero_of_quiet`); re-establish via `stuck`. +* `cut` case, first `fire1` at `F ≥ tA`: by the window invariant `F ≥ tB`; + the contract `hvr` yields the first completion `T ≥ F`; match + `some (dataIn F) = some (dataIn T)` (`globallyValidAndData_stable`), with + `none`s before on both sides (minimality of `F` and `T`); re-establish `cut` + at `(F + 1, T + 1)` — the new window is `e0_one_of_window`, the new boundary + is `e0_zero_of_allDone`. -/ +theorem out1_sampling_bisim (dataIn : Stream' (BitVec 32)) + (hvr : globallyValidUntilReady vldIn (allDone rdOut1 rdOut2 vldIn)) + (hvd : globallyValidAndData vldIn dataIn) : + out1View rdOut1 rdOut2 vldIn dataIn ~ sampledView rdOut1 rdOut2 vldIn dataIn := by + apply Bisim.coinduct (pred := SampleRel rdOut1 rdOut2 vldIn dataIn) + · intros s1 s2 hsample + rcases hsample + · case _ hs1 hs2 => + exists 0, 0 + simp + have hz1 := hs1 0 + have hz2 := hs2 0 + simp [hz1, hz2] + exact + SampleRel.stuck (Stream'.drop 1 s1) (Stream'.drop 1 s2) (fun i => hs1 (i + 1)) fun j => + hs2 (j + 1) + · case _ tA tB ha hb hAB hwin he0 => + by_cases hfire : ∃ t, fire1 rdOut1 rdOut2 vldIn (tA + t) = 1#1 + · /- + Next fires at tfst = tA + j + out1 | tA | ... | n | ... | | + out2 | tB | ... | | ... | m | + such that `out1 n = out2 m` and bisimilarity hold from then onwards. + * `n` is the first one to fire for the first stream, obtained from `fire1` + * `m` is the first one after `allDone` (at or after `tB`) + -/ + have hfirst := if_exists_first_exists hfire + obtain ⟨tdiff, htfst, htmin⟩ := hfirst + have hFtB : tB ≤ tA + tdiff := by + by_contra hcon + push_neg at hcon + have h1 := hwin (tA + tdiff) (by omega) hcon + simp [fire1, vldOut1_def, h1] at htfst + bv_decide + /- + out1 | tA | ... | tA + tdiff | ... | | | + out2 | ... | tB | ... | | ... | tA + tdiff + tbfst | + -/ + simp [globallyValidUntilReady] at hvr + specialize hvr (tA + tdiff) + (by simp [fire1, vldOut1_def] at htfst; bv_decide) + have hexists : ∃ k, allDone rdOut1 rdOut2 vldIn (tA + tdiff + k) = 1#1 := by grind + have ⟨tbfst, hbfst1, hbfst2⟩ := if_exists_first_exists hexists + exists tdiff, (tA + tdiff + tbfst - tB) + and_intros + · apply SampleRel.cut _ _ (tA + tdiff + 1) (tA + tdiff + tbfst + 1) + · simp [ha] + congr 1 + · simp [hb] + congr 1 + omega + · omega + · intro j hj hj2 + apply e0_one_of_window rdOut1 rdOut2 vldIn (by omega) htfst + intro jj hjj1 hjj2 + have := hbfst2 (jj - (tA + tdiff)) (by omega) + simp [show tA + tdiff + (jj - (tA + tdiff)) = jj by omega] at this + simp [this] + · exact e0_zero_of_allDone rdOut1 rdOut2 vldIn hbfst1 + · simp [ha, hb, Stream'.drop, show tA + tdiff + tbfst - tB + tB = tA + tdiff + tbfst by omega, Stream'.get] + simp [out1View, sampledView] + simp [fire1] at htfst + simp [toStream] + have hrd1 : rdOut1 (tA + tdiff) = 1#1 := by bv_decide + have hvldIn : vldIn (tA + tdiff + tbfst) = 1#1 := by grind + have hvld1 : vldOut1 rdOut1 rdOut2 vldIn (tA + tdiff) = 1#1 := by bv_decide + simp [show tdiff + tA = tA + tdiff by omega, hrd1, hvld1, hbfst1, hvldIn] + apply globallyValidAndData_stable (m := tA + tdiff) (n := tA + tdiff + tbfst) (data := dataIn) + (vld := vldIn) + · exact hvd + · intro k hk1 hk2 + obtain ⟨l, hl2, hl3, hl4⟩ := hvr + let jj := k - (tA + tdiff) + simp [show k = tA + tdiff + jj by omega] + have : jj ≤ l := by grind + by_cases hlt : jj < l + · apply hl4 + omega + · simp [show jj = l by omega] + exact hl3 + · omega + · simp [ha] + intro i hi + specialize htmin i hi + simp [fire1] at htmin + simp [Stream'.get, out1View, toStream] + bv_decide + · intro i hi + simp [hb] + simp [sampledView] + by_cases hlt : tB + i < tA + tdiff + · have hfire0 : ∀ s, tB ≤ s → s < tB + i + 1 → fire1 rdOut1 rdOut2 vldIn s = 0#1 := by + intro s hs1 hs2 + have := htmin (s - tA) (by omega) + simp [show tA + (s - tA) = s by omega] at this + exact this + have he0' : e0 rdOut1 rdOut2 vldIn (tB + i) = 0#1 := + e0_zero_of_no_fire rdOut1 rdOut2 vldIn (by omega) he0 (fun s h1 h2 => hfire0 s h1 (by omega)) + exact sampledView_get_none rdOut1 rdOut2 vldIn + (allDone_zero_of_quiet rdOut1 rdOut2 vldIn he0' (hfire0 _ (by omega) (by omega))) + · let jj := tB + i - tA - tdiff + simp [show tB + i = tA + tdiff + jj by omega] + specialize hbfst2 jj (by omega) + simp [Stream'.get, toStream, hbfst2] + · /- no fire ever again -/ + exists tA, tB + simp at hfire + have ha1 := out1View_none_of_no_fire rdOut1 rdOut2 vldIn + (m := tB) (dataIn := dataIn) + (by + intro t' ht' + specialize hfire (t' - tA) + simp [show tA + (t' - tA) = t' by omega] at hfire + bv_decide) + have ha2 := out1View_none_of_no_fire rdOut1 rdOut2 vldIn + (m := tA) (dataIn := dataIn) + (by + intro t' ht' + specialize hfire (t' - tA) + simp [show tA + (t' - tA) = t' by omega] at hfire + bv_decide) + simp [out1View] at ha2 + have hb2 := sampledView_none_of_no_fire rdOut1 rdOut2 vldIn (dataIn := dataIn) + (m := tB) he0 + (by + intro t' ht' + specialize hfire (t' - tA) + simp [show tA + (t' - tA) = t' by omega] at hfire + bv_decide) + simp [sampledView] at hb2 + simp [out1View] at ha + simp [sampledView] at hb + and_intros + · apply sampleRel_of_nones + · intro t + simp [ha] + apply ha2 + omega + · intro t + simp [hb] + apply hb2 + omega + · simp [ha, hb] + specialize ha2 (tA + tA) + specialize hb2 (tB + tB) + simp [ha2, hb2] + · simp [ha] + intro j hj + apply ha2 + omega + · simp [hb] + intro j hj + apply hb2 + omega + · apply SampleRel.cut _ _ 0 0 + · simp + · simp + · omega + · intros + simp at * + · simp [e0_zero] + +/-! ## Refinement of the handshake fork -/ + +/-- The components produced by `TRY3.hw_fork` are exactly the named signals of +this file. (Via `hw_fork_eq`, `split_stream2` and `hw_fork'_get`.) -/ +theorem hw_fork_components {dataIn : Stream' (BitVec 32)} + {rdIn vld1 vld2 : Stream' (BitVec 1)} {data1 data2 : Stream' (BitVec 32)} + (hfork : (rdIn, vld1, vld2, data1, data2) + = TRY3.split_stream2 (TRY3.hw_fork rdOut1 rdOut2 vldIn dataIn)) : + rdIn = allDone rdOut1 rdOut2 vldIn + ∧ vld1 = vldOut1 rdOut1 rdOut2 vldIn + ∧ vld2 = vldOut2 rdOut1 rdOut2 vldIn + ∧ data1 = dataIn ∧ data2 = dataIn := by + rw [hw_fork_eq] at hfork + simp only [TRY3.split_stream2, Prod.mk.injEq] at hfork + obtain ⟨hrdIn, hvld1, hvld2, hdata1, hdata2⟩ := hfork + and_intros + · simp [hrdIn, hw_fork'_get, vldOut2_def] + · simp [hvld1, hw_fork'_get] + · simp [hvld2, hw_fork'_get] + · simp [hdata1, hw_fork'_get] + · simp [hdata2, hw_fork'_get] + +/-- **The RTL fork refines the handshake fork on output 1**: under the +handshake contracts on the input (valid persists until acknowledged, data +stable while valid — no deadlock included), the stream of tokens seen by +receiver 1 is bisimilar to the input stream of tokens. + +(The transaction-level view is *pointwise equal* to the input stream by +`hw_fork_components`, so this is `out1_sampling_bisim` up to symmetry of `~`.) -/ +theorem hw_fork_refines_out1 {dataIn : Stream' (BitVec 32)} + {rdIn vld1 vld2 : Stream' (BitVec 1)} {data1 data2 : Stream' (BitVec 32)} + (hfork : (rdIn, vld1, vld2, data1, data2) + = TRY3.split_stream2 (TRY3.hw_fork rdOut1 rdOut2 vldIn dataIn)) + (hvr : globallyValidUntilReady vldIn rdIn) + (hvd : globallyValidAndData vldIn dataIn) : + toStream rdIn vldIn dataIn ~ toStream rdOut1 vld1 data1 := by + obtain ⟨h1, h2, -, h4, -⟩ := hw_fork_components rdOut1 rdOut2 vldIn hfork + subst h1 h2 h4 + apply HandshakeStream.symm + apply out1_sampling_bisim + · exact hvr + · exact hvd + +end Fork +end HWComponents diff --git a/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean b/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean index 8eeaa79fba..d099bdfd38 100644 --- a/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean +++ b/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean @@ -340,6 +340,20 @@ theorem hw_fork_eq : rtl.fork rd0 rd1 vld data = rtl.fork' rd0 rd1 vld data := b unfold rtl.fork rtl.fork' congr 1 +/-- Data passes unchanged through the fork's first output channel. -/ +private theorem hw_fork_out0 + (h : (rdy_out, vld0_out, vld1_out, data0_out, data1_out) = + project_stream (rtl.fork' rd0_in rd1_in vld_in data_in)) : + ∀ n, data_in n = data0_out n := + fork_dataIn_eq_dataOut1 h + +/-- Data passes unchanged through the fork's second output channel. -/ +private theorem hw_fork_out1 + (h : (rdy_out, vld0_out, vld1_out, data0_out, data1_out) = + project_stream (rtl.fork' rd0_in rd1_in vld_in data_in)) : + ∀ n, data_in n = data1_out n := + fork_dataIn_eq_dataOut2 h + /-- If at a certain point in time `n` the first output valid signal is true, then the input valid signal at that point in time is also true. @@ -558,7 +572,7 @@ theorem vldOut_eq_vldIn_of_fork_unitl_sent2 obtain ⟨ak, bk, ck⟩ := sk simp [hsk] at hck; subst hck have hak : ak = k := by - have := @fork_corec1 rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 k + have := @fork_corec_iter rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 k grind have hvldk : vldOut2 k = vldIn ak := by have h := congr_fun hvldout2 k @@ -579,7 +593,7 @@ theorem vldOut_eq_vldIn_of_fork_unitl_sent2 have hvldInA : vldIn ak = 0#1 := by grind simp [hvldInA]; have heq : a = n := by - have := @fork_corec1 rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 n + have := @fork_corec_iter rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 n rw [hst] at this simp at this assumption @@ -806,7 +820,9 @@ lemma fork_globallyValidAndData_out1 (hgv : globallyValidAndData vldIn dataIn) : globallyValidAndData vldOut1 dataOut1 := by intro i ⟨hi1, hi2⟩ - have hdata := hw_fork_out0 hfork + have hfork' : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = + project_stream (rtl.fork' rdOut1 rdOut2 vldIn dataIn) := by rw [← hw_fork_eq]; exact hfork + have hdata := hw_fork_out0 hfork' rw [← hdata i, ← hdata (i+1)] apply hgv exact ⟨vldOut1_implies_vldIn hfork hi1, vldOut1_implies_vldIn hfork hi2⟩ @@ -1112,7 +1128,10 @@ theorem hw_fork_refines1_with_fork: · /- first receiver after sent -/ sorry · simp [Stream'.get, h_8, h_7, toStream] - have hdataeq := hw_fork_out0 (h := h_6) + have h_6' : (rdIn_1, vldOut1_1, vldOut2_1, dataOut1_1, dataOut2_1) = + project_stream (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) := by + rw [← hw_fork_eq]; exact h_6 + have hdataeq := hw_fork_out0 (h := h_6') by_cases hle : fstVldTrue ≤ fstSentIdx · have hreadyIn : rdIn_1 fstSentIdx = 1#1 := by unfold toStream at h_7 @@ -1157,7 +1176,7 @@ theorem hw_fork_refines1_with_fork: obtain ⟨a, b, c⟩ := s dsimp [fork_corec, comb_and, comb_xor, comb_or, hw_constant] at hcirc have ha : a = fstVldTrue + k := by - have := @fork_corec1 rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 (fstVldTrue + k) + have := @fork_corec_iter rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 (fstVldTrue + k) simp [hst] at this simp [this] have hb0 : b = 0#1 := by @@ -1195,7 +1214,7 @@ theorem hw_fork_refines1_with_fork: obtain ⟨ak, bk, ck⟩ := sk simp [hsk] at hbk; subst hbk have hak : ak = km := by - have := @fork_corec1 rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 km + have := @fork_corec_iter rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 km simp [hsk] at this; omega have hvldk : vldOut1_1 km = vldIn_1 ak := by rw [hw_fork_eq] at hh5; simp [project_stream] at hh5 @@ -1270,7 +1289,7 @@ theorem hw_fork_refines1_with_fork: obtain ⟨a2, b2, c2⟩ := s2 dsimp [fork_corec, comb_and, comb_xor, comb_or, hw_constant] at hcirc2 have ha2 : a2 = fstSentIdx := by - have := @fork_corec1 rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 fstSentIdx + have := @fork_corec_iter rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 fstSentIdx simp [hst2] at this; omega have hb02 : b2 = 0#1 := by suffices key2 : ∀ m, (∀ j < m, rdOut1_1 j = 0#1 ∨ vldOut1_1 j = 0#1) → @@ -1297,7 +1316,7 @@ theorem hw_fork_refines1_with_fork: obtain ⟨ak, bk, ck⟩ := sk simp [hsk] at hbk; subst hbk have hak : ak = km := by - have := @fork_corec1 rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 km + have := @fork_corec_iter rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 km simp [hsk] at this; omega have hvldk2 : vldOut1_1 km = vldIn_1 ak := by rw [hw_fork_eq] at hh5; simp [project_stream] at hh5 @@ -1445,7 +1464,7 @@ theorem hw_fork_refines1_with_fork: We see this by unfolding the fork hypotheses -/ unfold project_stream simp - have h1 := rtl.fork'_of_all_none + have h1 := fork'_of_all_none (dataIn := Stream'.drop 1 dataIn_1) (vldIn := Stream'.drop 1 vldIn_1) (rdOut1 := Stream'.drop 1 rdOut1_1) @@ -1455,7 +1474,7 @@ theorem hw_fork_refines1_with_fork: specialize hnevldin (k + 1) simp [show Stream'.drop 1 vldIn_1 k = vldIn_1 (k + 1) by rfl, hnevldin] ) - have h2 := rtl.fork'_of_all_none + have h2 := fork'_of_all_none (dataIn := dataIn_1) (vldIn := vldIn_1) (rdOut1 := rdOut1_1) From 85e9ed7ce8ca1426b20d942dfe46ed23a618f770 Mon Sep 17 00:00:00 2001 From: luisacicolini Date: Thu, 16 Jul 2026 16:56:02 +0100 Subject: [PATCH 08/13] sorry free --- SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean | 734 --- .../CIRCT/HandshakeToHW/HWForkSampling.lean | 88 + SSA/Projects/LLVMRiscV/Evaluation/.gitignore | 17 - .../LLVM-bug-reports/issue_53252.lean | 47 - .../LLVM-bug-reports/issue_59876.lean | 48 - .../LLVM-bug-reports/thesis_ex.lean | 297 - .../Evaluation/LLVM-tests/add-imm.lean | 274 - .../LLVM-tests/add-imm64-to-sub.lean | 163 - .../LLVM-tests/add_sext_shl_constant.lean | 217 - .../Evaluation/LLVM-tests/alu16.lean | 525 -- .../Evaluation/LLVM-tests/alu32.lean | 591 -- .../Evaluation/LLVM-tests/alu64.lean | 649 -- .../benchmarks/MLIR_multi/output_3.mlir | 900 --- .../benchmarks/MLIR_multi/output_4.mlir | 1000 --- .../benchmarks/MLIR_multi/output_5.mlir | 1100 ---- .../benchmarks/MLIR_multi/output_6.mlir | 1200 ---- .../benchmarks/MLIR_multi/output_7.mlir | 1300 ---- .../benchmarks/MLIR_multi/output_8.mlir | 1400 ----- .../benchmarks/MLIR_multi/version_log.txt | 1 - .../LLVMRiscV/Evaluation/benchmarks/README.md | 60 - .../Evaluation/benchmarks/create_func.py | 58 - .../Evaluation/benchmarks/generate.py | 635 -- .../Evaluation/benchmarks/generate_multi.py | 91 - .../compare-lowering-patterns/README.md | 33 - .../compare_lowerings.py | 440 -- .../compare-lowering-patterns/comparison.log | 5370 ----------------- .../isolated_instructions/llvm_add.mlir | 21 - .../isolated_instructions/llvm_and.mlir | 7 - .../isolated_instructions/llvm_ashr.mlir | 7 - .../isolated_instructions/llvm_icmp.mlir | 70 - .../isolated_instructions/llvm_mul.mlir | 21 - .../isolated_instructions/llvm_or.mlir | 7 - .../isolated_instructions/llvm_rem.mlir | 7 - .../isolated_instructions/llvm_sdiv.mlir | 7 - .../isolated_instructions/llvm_select.mlir | 7 - .../isolated_instructions/llvm_sext.mlir | 28 - .../isolated_instructions/llvm_shl.mlir | 28 - .../isolated_instructions/llvm_srl.mlir | 7 - .../isolated_instructions/llvm_sub.mlir | 21 - .../isolated_instructions/llvm_trunc.mlir | 7 - .../isolated_instructions/llvm_udiv.mlir | 7 - .../isolated_instructions/llvm_urem.mlir | 7 - .../isolated_instructions/llvm_xor.mlir | 7 - .../isolated_instructions/llvm_zext.mlir | 28 - .../run_comparison.sh | 5 - .../Evaluation/mca-analysis/.python-version | 1 - .../Evaluation/mca-analysis/README.md | 42 - .../LLVMRiscV/Evaluation/mca-analysis/plot.py | 1043 ---- .../Evaluation/mca-analysis/pyproject.toml | 12 - .../Evaluation/mca-analysis/run_mca.py | 147 - .../Evaluation/mca-analysis/similarity.py | 72 - .../LLVMRiscV/Evaluation/mca-analysis/uv.lock | 46 - 52 files changed, 88 insertions(+), 18812 deletions(-) delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/.gitignore delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/issue_53252.lean delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/issue_59876.lean delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/thesis_ex.lean delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add-imm.lean delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add-imm64-to-sub.lean delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add_sext_shl_constant.lean delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu16.lean delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu32.lean delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu64.lean delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_3.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_4.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_5.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_6.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_7.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_8.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/version_log.txt delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/README.md delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/create_func.py delete mode 100755 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/generate.py delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/generate_multi.py delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/README.md delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/compare_lowerings.py delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/comparison.log delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_add.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_and.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_ashr.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_icmp.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_mul.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_or.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_rem.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sdiv.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_select.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sext.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_shl.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_srl.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sub.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_trunc.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_udiv.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_urem.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_xor.mlir delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_zext.mlir delete mode 100755 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/run_comparison.sh delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/.python-version delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/README.md delete mode 100755 SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/plot.py delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/pyproject.toml delete mode 100755 SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/run_mca.py delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/similarity.py delete mode 100644 SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/uv.lock diff --git a/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean b/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean index c4367340b5..87130f5a1e 100644 --- a/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean +++ b/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean @@ -1001,739 +1001,5 @@ theorem data_remains_constant_until_first simp [hrdm, hvldm] at this -def readyOut1UntilAllReceiversAre(rdOut1 rdOut2 : Stream' (BitVec 1)) := - ∀ i, - rdOut1 i = 1#1 → - ∀ j, rdOut2 (i + j) = 0#1 → rdOut1 (i + j) = 1#1 - -def readyOut2UntilAllReceiversAre (rdOut1 rdOut2 : Stream' (BitVec 1)) := - ∀ i, - rdOut2 i = 1#1 → - ∀ j, rdOut1 (i + j) = 0#1 → rdOut2 (i + j) = 1#1 - -/-- the standard implementation of the fork refines the handshake fork (`TRY2.hw_fork`) -/ -theorem hw_fork_refines1_with_fork: - /- Given a handshake fork taking `a` as input and returning `(a, a)`, we take - its lowering (with input a bisimilar ready-valid wrapped stream) -/ - (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = TRY3.split_stream2 (TRY3.hw_fork rdOut1 rdOut2 vldIn dataIn) → - /- We want to make sure that stalling is correctly modeled for `a` (input). - We constrain the input and prove that if the input behaves properly, - the output will. -/ - globallyValidUntilReady vldOut1 rdOut1 → - globallyValidUntilReady vldOut2 rdOut2 → - globallyValidUntilReady vldIn rdIn → - readyOut1UntilAllReceiversAre (rdOut1 := rdOut1) (rdOut2 := rdOut2) → - readyOut2UntilAllReceiversAre (rdOut1 := rdOut1) (rdOut2 := rdOut2) → - globallyValidAndData vldOut1 dataOut1 → - globallyValidAndData vldOut2 dataOut2 → - globallyValidAndData vldIn dataIn → - /- we assume no deadlock -/ - globallyFinallyReady rdIn → - globallyFinallyReady rdOut1 → - globallyFinallyReady rdOut2 → - /- if we know that the hshake input stream is bisimilar to the ready-valid input of the hw fork (`a ~ rdy vld i`), meaning that the two outputs are also bisimilar by transitivity-/ - /- we want to prove that the outputs of the handshake fork are respectively - bisimilar to the ready-valid wrapping of the output of the hardware fork -/ - (toStream rdIn vldIn dataIn) ~ (toStream rdOut1 vldOut1 dataOut1) := by - intros hfork hgvurOutt1 hvgurOut2 hgvurIn hout1 hout2 hgvdOut1 hgvdOut2 hgvdIn hgfrIn hgfrOut1 hgfrOut2 - /- if 0, 0 works we don't need bisimilarity -/ - /- the high-level fork will never wait for anything (whenever an input is available), - while the low-level one might have to, and depends on the `rd1` signal eventually being true. - if we choose `pred := Eq` the relation is too strong, the second goal is not provable. - -/ - apply Bisim.coinduct (pred := relation_fork) - · intros sin sout hrel - /- `sin` and `sout` exist at the handshake level of the design -/ - rcases hrel - expose_names - by_cases hvldExists : ∃ k, vldIn_1 k = 1#1 - · have := if_exists_first_exists hvldExists - obtain ⟨fstVldTrue, hfstVldTrue1, hfstVldTrue2⟩ := this - /- we need to find the first element that is transmitted -/ - have hfstSent := exists_first_transmitted_element - (data := dataIn_1) (vld := vldIn_1) (rdy := rdIn_1) (x := sin) - (by grind) (by assumption) (by assumption) - have ⟨fstRdyOut, hfstRdyOut⟩ := if_exists_first_exists (h_4 fstVldTrue) - have ⟨fstRdyOut2, hfstRdyOut2⟩ := if_exists_first_exists (h_5 fstVldTrue) - unfold globallyFinallyReady at h_4 - have hvldinout := vldIn_and_ready_implies_vldOut1 - (dataIn := dataIn_1) (vldIn := vldIn_1) (rdIn := rdIn_1) - (rdOut1 := rdOut1_1) (rdOut2 := rdOut2_1) (vldOut1 := vldOut1_1) (vldOut2 := vldOut2_1) - (dataOut1 := dataOut1_1) (dataOut2 := dataOut2_1) (by grind) (by grind) - have hvldinout2 := vldIn_and_ready_implies_vldOut2 - (dataIn := dataIn_1) (vldIn := vldIn_1) (rdIn := rdIn_1) - (rdOut1 := rdOut1_1) (rdOut2 := rdOut2_1) (vldOut1 := vldOut1_1) (vldOut2 := vldOut2_1) - (dataOut1 := dataOut1_1) (dataOut2 := dataOut2_1) (by grind) (by grind) - have hfstRec := exists_first_received_element - (data := dataOut1_1) (vld := vldOut1_1) (rdy := rdOut1_1) (x := sout) (hx := h_8) - have ⟨fstSentIdx, hfstSentIdx⟩ := hfstSent - exists fstSentIdx, (fstVldTrue + fstRdyOut) - and_intros - · apply relation_fork.intro - (Stream'.drop (fstSentIdx + 1) sin) (Stream'.drop (fstVldTrue + fstRdyOut + 1) sout) - (dataIn := Stream'.drop (fstSentIdx + 1) dataIn_1) - (rdIn := Stream'.drop (fstSentIdx + 1) rdIn_1) - (vldIn := Stream'.drop (fstSentIdx + 1) vldIn_1) - (vldOut1 := Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut1_1) - (vldOut2 := Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut2_1) - (dataOut1 := Stream'.drop (fstVldTrue + fstRdyOut + 1) dataOut1_1) - (dataOut2 := Stream'.drop (fstSentIdx + 1) dataOut2_1) - (rdOut1 := Stream'.drop (fstVldTrue + fstRdyOut + 1) rdOut1_1) - (rdOut2 := Stream'.drop (fstVldTrue + fstRdyOut + 1) rdOut2_1) - · simp_all - rfl - · simp_all - rfl - · unfold globallyValidUntilReady at ⊢ h - intro j hj - specialize h (j + fstSentIdx + 1) hj - obtain ⟨k, hk1, hk2, hk3⟩ := h - exists k - have hv : Stream'.drop (fstSentIdx + 1) vldIn_1 j = vldIn_1 (j + fstSentIdx + 1) := by rfl - rw [hv] at hj - have hv : Stream'.drop (fstSentIdx + 1) vldIn_1 (j + k) = vldIn_1 (j + k + fstSentIdx + 1) := by rfl - have hr : Stream'.drop (fstSentIdx + 1) rdIn_1 (j + k) = rdIn_1 (j + k + fstSentIdx + 1) := by rfl - simp [hv, hr, show j + k + fstSentIdx + 1 = j + fstSentIdx + 1 + k by omega, hk1, hk2] - intros n hn - have hn : Stream'.drop (fstSentIdx + 1) vldIn_1 (j + n) = vldIn_1 (j + n + fstSentIdx + 1) := by rfl - simp [hn] - specialize hk3 n (by omega) - simp [show j + n + fstSentIdx + 1 = j + fstSentIdx + 1 + n by omega, hk3] - · unfold globallyValidUntilReady at ⊢ h_1 - intro j hj - have hj2 : Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut1_1 j = vldOut1_1 (j + fstVldTrue + fstRdyOut + 1) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - rw [hj2] at hj - specialize h_1 (j + fstVldTrue + fstRdyOut + 1) hj - obtain ⟨k, hk1, hk2, hk3⟩ := h_1 - exists k - have hv : Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut1_1 (j + k) = vldOut1_1 (j + k + fstVldTrue + fstRdyOut + 1) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - have hr : Stream'.drop (fstVldTrue + fstRdyOut + 1) rdOut1_1 (j + k) = rdOut1_1 (j + k + fstVldTrue + fstRdyOut + 1) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - simp [hv, hr, show j + k + fstVldTrue + fstRdyOut + 1 = j + fstVldTrue + fstRdyOut + 1 + k by omega, hk1, hk2] - intros n hn - have hn : Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut1_1 (j + n) = vldOut1_1 (j + n + fstVldTrue + fstRdyOut + 1) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - simp [hn] - specialize hk3 n (by omega) - simp [show j + n + fstVldTrue + fstRdyOut + 1 = j + fstVldTrue + fstRdyOut + 1 + n by omega, hk3] - · unfold globallyValidUntilReady at ⊢ h_2 - intro j hj - have hj2 : Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut2_1 j = vldOut2_1 (j + fstVldTrue + fstRdyOut + 1) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - rw [hj2] at hj - specialize h_2 (j + fstVldTrue + fstRdyOut + 1) hj - obtain ⟨k, hk1, hk2, hk3⟩ := h_2 - exists k - have hv : Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut2_1 (j + k) = vldOut2_1 (j + k + fstVldTrue + fstRdyOut + 1) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - have hr : Stream'.drop (fstVldTrue + fstRdyOut + 1) rdOut2_1 (j + k) = rdOut2_1 (j + k + fstVldTrue + fstRdyOut + 1) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - simp [hv, hr, show j + k + fstVldTrue + fstRdyOut + 1 = j + fstVldTrue + fstRdyOut + 1 + k by omega, hk1, hk2] - intros n hn - have hn : Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut2_1 (j + n) = vldOut2_1 (j + n + fstVldTrue + fstRdyOut + 1) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - simp [hn] - specialize hk3 n (by omega) - simp [show j + n + fstVldTrue + fstRdyOut + 1 = j + fstVldTrue + fstRdyOut + 1 + n by omega, hk3] - · unfold globallyValidAndData at ⊢ h_3 - intro j - specialize h_3 (j + fstSentIdx + 1) - have hr : Stream'.drop (fstSentIdx + 1) dataIn_1 j = dataIn_1 (j + fstSentIdx + 1) := by rfl - have hr' : Stream'.drop (fstSentIdx + 1) dataIn_1 (j + 1) = dataIn_1 (j + 1 + fstSentIdx + 1) := by rfl - simp [hr, hr'] - simp [show j + 1 + fstSentIdx + 1 = j + fstSentIdx + 1 + 1 by omega] - intro h1 h2 - apply h_3 - have htmp : Stream'.drop (fstSentIdx + 1) vldIn_1 j = vldIn_1 (j + fstSentIdx + 1) := by rfl - rw [htmp] at h1 - simp [h1] - have htmp : Stream'.drop (fstSentIdx + 1) vldIn_1 (j + 1) = vldIn_1 (j + 1 + fstSentIdx + 1) := by rfl - simp [show j + 1 + fstSentIdx + 1 = j + fstSentIdx + 1 + 1 by omega, htmp] at h2 - simp [h2] - · unfold globallyFinallyReady - intros i - specialize h_4 (i + fstVldTrue + fstRdyOut + 1) - obtain ⟨k, hk⟩ := h_4 - exists k - have htmp : Stream'.drop (fstVldTrue + fstRdyOut + 1) rdOut1_1 (i + k) = rdOut1_1 (i + k + fstVldTrue + fstRdyOut + 1) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - simp [htmp, show i + k + fstVldTrue + fstRdyOut + 1 = i + fstVldTrue + fstRdyOut + 1 + k by omega, hk] - · unfold globallyFinallyReady at h_5 ⊢ - intro j - specialize h_5 (fstVldTrue + fstRdyOut + 1 + j) - obtain ⟨k, hk⟩ := h_5 - exists k - have h : Stream'.drop (fstVldTrue + fstRdyOut + 1) rdOut2_1 (j + k) = rdOut2_1 (fstVldTrue + fstRdyOut + 1 + j + k) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - simp [h, hk] - · have : fstVldTrue ≤ fstSentIdx := by - simp_all - apply Classical.byContradiction - intro hcontra - specialize hfstVldTrue2 fstSentIdx (by omega) - simp [toStream, hfstVldTrue2] at hfstSentIdx - by_cases fstRecfst : fstRdyOut ≤ fstRdyOut2 - · /- first receiver comes first -/ - by_cases fstRecBeforeSent : fstVldTrue + fstRdyOut ≤ fstSentIdx - · /- first receiver before sent -/ - by_cases sndRecBeforeSent : fstVldTrue + fstRdyOut2 ≤ fstSentIdx - · /- second receiver before sent -/ - simp [TRY3.split_stream2] - and_intros - · funext i - have := rdOut1_before_allDone (hfork := h_6) (n := i) - /- what happens to `rdOut1` after data is dispatched? -/ - have heq : Stream'.drop (fstSentIdx + 1) rdIn_1 i = rdIn_1 (fstSentIdx + 1 + i) := by - simp [Stream'.drop] - congr 1 - grind - rw [heq] - by_cases hfalse : rdIn_1 (fstSentIdx + 1 + i) = 0#1 - · have := congr_fun h_7 (fstSentIdx + 1 + i) - unfold toStream at this - simp [hfalse] at * - rw [hw_fork_eq] - - have : ∀ k, ∀ i, Stream'.drop k rdOut1_1 i = rdOut1_1 (i + k) := by - intros - simp [Stream'.drop, Stream'.get] - simp [hw_fork', Stream'.corec'] - unfold fork_corec - simp [comb_and, comb_xor, comb_or, hw_constant] - - sorry - · sorry - · sorry - · sorry - · sorry - · sorry - · /- first receiver after sent -/ - sorry - · /- first receiver after sent, implies second receiver after sent -/ - have : fstSentIdx ≤ fstVldTrue + fstRdyOut2 := by omega - sorry - · /- second receiver comes first -/ - by_cases fstRecBeforeSent : fstVldTrue + fstRdyOut ≤ fstSentIdx - · /- first receiver before sent, implies second receiver before sent -/ - have : fstVldTrue + fstRdyOut2 ≤ fstSentIdx := by omega - sorry - · /- first receiver after sent -/ - by_cases sndRecBeforeSent : fstVldTrue + fstRdyOut2 ≤ fstSentIdx - · /- second receiver before sent -/ - sorry - · /- first receiver after sent -/ - sorry - · simp [Stream'.get, h_8, h_7, toStream] - have hdataeq := hw_fork_out0 (h := h_6) - by_cases hle : fstVldTrue ≤ fstSentIdx - · have hreadyIn : rdIn_1 fstSentIdx = 1#1 := by - unfold toStream at h_7 - have h_6sent := congr_fun h_7 fstSentIdx - simp [hfstSentIdx] at h_6sent - simp [h_6sent] - have hvalidIn: vldIn_1 fstSentIdx = 1#1 := by - unfold toStream at h_7 - have h_6sent := congr_fun h_7 fstSentIdx - simp [hfstSentIdx] at h_6sent - simp [h_6sent] - have hrdout : rdOut1_1 (fstVldTrue + fstRdyOut) = 1#1 := by - simp [hfstRdyOut] - have hvldout : vldOut1_1 (fstVldTrue + fstRdyOut) = 1#1 := by - have hbefore : ∀ j < fstVldTrue + fstRdyOut, rdOut1_1 j = 0#1 ∨ vldOut1_1 j = 0#1 := by - intro j hj - by_cases hjlt : j < fstVldTrue - · right; by_contra hc - have : vldOut1_1 j = 1#1 := by grind - have := vldOut1_implies_vldIn h_6 (n := j) (by assumption) - specialize hfstVldTrue2 j hjlt - simp [this] at hfstVldTrue2 - · left - have := hfstRdyOut.2 (j - fstVldTrue) (by omega) - rwa [Nat.add_sub_cancel' (by omega)] at this - rw [vldOut_eq_vldIn_of_fork_unitl_sent h_6 hbefore] - obtain ⟨k, hkrd, hkvld, hkall⟩ := h fstVldTrue hfstVldTrue1 - by_contra hlt; push_neg at hlt - have hrda : rdOut1_1 (fstVldTrue + k) = 0#1 := by - have := hfstRdyOut.2 k (by grind) - simpa using this - -- rdIn fires at fstVldTrue + k with k < fstRdyOut, but rdOut1 hasn't fired - have hh5 := h_6 - rw [hw_fork_eq] at h_6 - simp [TRY3.split_stream2] at h_6 - obtain ⟨hrdin, -⟩ := h_6 - have hcirc := congr_fun hrdin (fstVldTrue + k) - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hcirc - generalize hst : Stream'.iterate - (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) - (fstVldTrue + k) = s at hcirc - obtain ⟨a, b, c⟩ := s - dsimp [fork_corec, comb_and, comb_xor, comb_or, hw_constant] at hcirc - have ha : a = fstVldTrue + k := by - have := @fork_corec1 rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 (fstVldTrue + k) - simp [hst] at this - simp [this] - have hb0 : b = 0#1 := by - suffices key : ∀ m, (∀ j < m, rdOut1_1 j = 0#1 ∨ vldOut1_1 j = 0#1) → - (Stream'.iterate (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) - (0, 0#1, 0#1) m).2.1 = 0#1 by - have := key (fstVldTrue + k) (by - intro j hj - by_cases hjlt : j < fstVldTrue - · right; by_contra hc - have : vldOut1_1 j = 1#1 := true_of_width_one (b := vldOut1_1 j) hc - have := vldOut1_implies_vldIn hh5 (n := j) (by assumption) - specialize hfstVldTrue2 j hjlt - simp [this] at hfstVldTrue2 - · have hklt : k < fstRdyOut := by - by_contra hkge; push_neg at hkge - rcases Nat.lt_or_eq_of_le hkge with hlt' | rfl - · exact hlt (hkall fstRdyOut hlt') - · exact hlt hkvld - have hklt : k < fstRdyOut := by - by_contra hkge; push_neg at hkge - exact hlt (hkall fstRdyOut (by omega)) - left - have := hfstRdyOut.2 (j - fstVldTrue) (by omega) - rwa [Nat.add_sub_cancel' (by omega)] at this - ) - rw [hst] at this; simpa using this - intro m; induction m with - | zero => simp [Stream'.iterate] - | succ km ihkm => - intro hbef - have hbk := ihkm (fun j hj => hbef j (Nat.lt_succ_of_lt hj)) - generalize hsk : Stream'.iterate - (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) km = sk - obtain ⟨ak, bk, ck⟩ := sk - simp [hsk] at hbk; subst hbk - have hak : ak = km := by - have := @fork_corec1 rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 km - simp [hsk] at this; omega - have hvldk : vldOut1_1 km = vldIn_1 ak := by - rw [hw_fork_eq] at hh5; simp [TRY3.split_stream2] at hh5 - obtain ⟨-, hvldout1, -⟩ := hh5 - have hn := congr_fun hvldout1 km - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn - simp_rw [hsk] at hn - dsimp [fork_corec, comb_and, comb_xor, hw_constant] at hn - simp [hn] - ext k hk - simp [show k = 0 by omega] - have hkbef := hbef km (Nat.lt_succ_self km) - rw [iterate_back_succ, hsk]; simp only [Function.comp] - dsimp [fork_corec, comb_and, comb_xor, comb_or, hw_constant] - subst hak - rcases hkbef with hh | hh - · simp [hh] - · rw [hvldk] at hh; simp [hh] - rw [hkrd, hb0, ha] at hcirc - simp [hrda] at hcirc - simp [hvalidIn, hreadyIn, hrdout, hvldout] - rw [← hdataeq] - let diff := fstSentIdx - fstVldTrue - have hdiff : fstSentIdx = fstVldTrue + diff := by omega - have hdatain : dataIn_1 fstSentIdx = dataIn_1 fstVldTrue := by - rw [hdiff] - have := data_remains_constant_if (i := fstVldTrue) (rdy := rdIn_1) (vld := vldIn_1) (data := dataIn_1) - (by assumption) (by assumption) (by assumption) - obtain ⟨kd, hkd1, hkd2, hkd3, hkd4⟩ := this - by_cases hle : diff ≤ kd - · specialize hkd4 diff hle - apply hkd4 - · /- contra -/ - exfalso - have hkdlt : fstVldTrue + kd < fstSentIdx := by omega - have := hfstSentIdx.2 (fstVldTrue + kd) hkdlt - rw [h_7, toStream] at this - simp [hkd1, hkd2] at this - rw [hdatain] - symm - have := data_remains_constant_until_first (i := fstVldTrue) - (data := dataIn_1) (rdy := rdIn_1) (vld := vldIn_1) (by assumption) - (by assumption) (by assumption) - obtain ⟨k, hk1, hk2, hk3, hk4, hk5⟩ := this - have hkeqdiff : k = diff := by - apply Nat.le_antisymm - · by_contra hlt; push_neg at hlt - -- hlt : diff < k - have := hk5 diff (by omega) - rw [← hdiff] at this - simp [hreadyIn] at this - · by_contra hlt; push_neg at hlt - have := hfstSentIdx.2 (fstVldTrue + k) (by omega) - rw [h_7, toStream] at this - simp [hk1, hk2] at this - subst hkeqdiff - apply hk4 fstRdyOut - -- fstRdyOut ≤ diff, i.e., fstVldTrue + fstRdyOut ≤ fstSentIdx - -- proved by contradiction: if fstSentIdx < fstVldTrue + fstRdyOut, - -- allDone fires but rdOut1 hasn't, contradicting the circuit - have hrdyOutLe : fstVldTrue + fstRdyOut ≤ fstSentIdx := by - by_contra hlt; push_neg at hlt - have hh5 := h_6 - rw [hw_fork_eq] at h_6 - simp [TRY3.split_stream2] at h_6 - obtain ⟨hrdin, -⟩ := h_6 - have hcirc2 := congr_fun hrdin fstSentIdx - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hcirc2 - generalize hst2 : Stream'.iterate - (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) - fstSentIdx = s2 at hcirc2 - obtain ⟨a2, b2, c2⟩ := s2 - dsimp [fork_corec, comb_and, comb_xor, comb_or, hw_constant] at hcirc2 - have ha2 : a2 = fstSentIdx := by - have := @fork_corec1 rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 fstSentIdx - simp [hst2] at this; omega - have hb02 : b2 = 0#1 := by - suffices key2 : ∀ m, (∀ j < m, rdOut1_1 j = 0#1 ∨ vldOut1_1 j = 0#1) → - (Stream'.iterate (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) - (0, 0#1, 0#1) m).2.1 = 0#1 by - have := key2 fstSentIdx (by - intro j hj - by_cases hjlt : j < fstVldTrue - · right; by_contra hc - have : vldOut1_1 j = 1#1 := by grind - have := vldOut1_implies_vldIn hh5 (n := j) this - exact absurd (hfstVldTrue2 j hjlt) (by grind) - · left - have := hfstRdyOut.2 (j - fstVldTrue) (by omega) - rwa [Nat.add_sub_cancel' (by omega)] at this) - rw [hst2] at this; simpa using this - intro m; induction m with - | zero => simp [Stream'.iterate] - | succ km ihkm => - intro hbef - have hbk := ihkm (fun j hj => hbef j (Nat.lt_succ_of_lt hj)) - generalize hsk : Stream'.iterate - (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) km = sk - obtain ⟨ak, bk, ck⟩ := sk - simp [hsk] at hbk; subst hbk - have hak : ak = km := by - have := @fork_corec1 rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 km - simp [hsk] at this; omega - have hvldk2 : vldOut1_1 km = vldIn_1 ak := by - rw [hw_fork_eq] at hh5; simp [TRY3.split_stream2] at hh5 - obtain ⟨-, hvldout1, -⟩ := hh5 - have hn := congr_fun hvldout1 km - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn - simp_rw [hsk] at hn - dsimp [fork_corec, comb_and, comb_xor, hw_constant] at hn - simp [hn] - ext k - simp [show k = 0 by omega] - rw [iterate_back_succ, hsk]; simp only [Function.comp] - dsimp [fork_corec, comb_and, comb_xor, comb_or, hw_constant] - subst hak - rcases hbef ak (Nat.lt_succ_self ak) with hh | hh - · simp [hh] - · rw [hvldk2] at hh; simp [hh] - have hrda2 : rdOut1_1 fstSentIdx = 0#1 := by - have := hfstRdyOut.2 (fstSentIdx - fstVldTrue) (by omega) - rwa [Nat.add_sub_cancel' (by omega)] at this - rw [hreadyIn, hb02, ha2, hrda2] at hcirc2 - simp at hcirc2 - omega - · /- contradiction: nothing can be sent before `fstSentIdx` -/ - simp_all - intro hcontra - specialize hfstVldTrue2 fstSentIdx hle - simp [toStream, hfstVldTrue2] at hfstSentIdx - · intro i hi - exact hfstSentIdx.2 i hi - · intros j hj - by_cases hj' : j < fstVldTrue - · simp [Stream'.get, h_8, toStream] - intro hvld - have := vldOut1_implies_vldIn h_6 (n := j) - have := hfstVldTrue2 j hj' - grind - · simp [h_8, toStream, Stream'.get] - let diff := j - fstVldTrue - have : j = fstVldTrue + diff := by omega - rw [this] - obtain ⟨h1,h2⟩ := hfstRdyOut - specialize h2 diff (by omega) - intro hc - simp [hc] at h2 - · /- if we never have a valid signal, all streams are empty and the relation holds trivially -/ - have hnonein := not_exists_transmitted_element (x := sin) (data := dataIn_1) (rdy := rdIn_1) - (vld := vldIn_1) (by grind) h_7 - /- the fork module will never transmit anything meaningful -/ - rw [hw_fork_eq] at h_6 - unfold TRY3.split_stream2 at h_6 - simp at h_6 - have hhfork1 := h_6 - obtain ⟨hrd', hvld1', hvld2', hdata1', hdata2'⟩ := hhfork1 - rw [h_7, h_8] - have hnoneout : ∀ k, vldOut1_1 k = 0#1 := by - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hvld1' - intros k - generalize hst : Stream'.iterate - (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) k = s at hvld1' - simp [fork_corec] at hvld1' - have hk := congr_fun hvld1' k - simp [comb_and, hw_constant] at hk - simp_all - - have : vldIn_1 (Stream'.iterate (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) k).1 = 0#1 := by - grind - simp [this] - have hnoneout2 : ∀ k, vldOut2_1 k = 0#1 := by - unfold hw_fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hvld2' - intros k - generalize hst : Stream'.iterate - (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) k = s at hvld2' - simp [fork_corec] at hvld2' - have hk := congr_fun hvld2' k - simp [comb_and, hw_constant] at hk - simp_all - have : vldIn_1 (Stream'.iterate (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) k).1 = 0#1 := by - grind - simp [this] - have hnevldin : ∀ k, vldIn_1 k = 0#1 := by grind - have hnonet := not_exists_transmitted_element (x := sout) (data := dataOut1_1) (rdy := rdOut1_1) - (vld := vldOut1_1) (by grind) h_8 - exists 0, 0 - and_intros - · simp - generalize hxgen : Stream'.drop 1 (toStream rdIn_1 vldIn_1 dataIn_1) = y' - generalize hygen : Stream'.drop 1 (toStream rdOut1_1 vldOut1_1 dataOut1_1) = x' - apply relation_fork.intro (x := y') (y := x') - (dataIn := Stream'.drop 1 dataIn_1) - (rdIn := Stream'.drop 1 rdIn_1) - (vldIn := Stream'.drop 1 vldIn_1) - (vldOut1 := Stream'.drop 1 vldOut1_1) - (vldOut2 := Stream'.drop 1 vldOut2_1) - (dataOut1 := Stream'.drop 1 dataOut1_1) - (dataOut2 := Stream'.drop 1 dataOut2_1) - (rdOut1 := Stream'.drop 1 rdOut1_1) - (rdOut2 := Stream'.drop 1 rdOut2_1) - · rw [← hxgen] - rfl - · rw [← hygen] - rfl - · /- contra in hj: there is no i such that vldIn' = 1#1 -/ - unfold globallyValidUntilReady - intros j hj - specialize hnevldin (j + 1) - have : Stream'.drop 1 vldIn_1 j = vldIn_1 (j + 1) := by rfl - simp [this, hnevldin] at hj - · unfold globallyValidUntilReady - intros j hj - apply Classical.byContradiction - simp [Stream'.drop] at hj - have := hnoneout (1 + j) - simp [show vldOut1_1.get (j + 1) = vldOut1_1 (j + 1) by rfl] at hj - simp [Nat.add_comm (n := j), this] at hj - · unfold globallyValidUntilReady - intros j hj - apply Classical.byContradiction - simp [Stream'.drop] at hj - have := hnoneout2 (1 + j) - simp [show vldOut2_1.get (j + 1) = vldOut2_1 (j + 1) by rfl] at hj - simp [Nat.add_comm (n := j), this] at hj - · /- contra in hj: there is no i such that vldIn' = 1#1 -/ - unfold globallyValidAndData - intros j hj - have : Stream'.drop 1 vldIn_1 j = vldIn_1 (j + 1) := by rfl - specialize hnevldin (j + 1) - simp [this, hnevldin] at hj - · /- follows from `hgfrOut1'` -/ - unfold globallyFinallyReady at h_4 ⊢ - intros i - specialize h_4 (i + 1) - obtain ⟨j, hj⟩ := h_4 - exists j - have : Stream'.drop 1 rdOut1_1 (i + j) = rdOut1_1 ((i + j) + 1) := by rfl - rw [this, show i + j + 1 = i + 1 + j by omega, hj] - · unfold globallyFinallyReady at h_5 ⊢ - intros i - specialize h_5 (i + 1) - obtain ⟨j, hj⟩ := h_5 - exists j - have : Stream'.drop 1 rdOut2_1 (i + j) = rdOut2_1 ((i + j) + 1) := by rfl - rw [this, show i + j + 1 = i + 1 + j by omega, hj] - · /- after dropping one element, all the relations defined by the fork module remain. - We see this by unfolding the fork hypotheses -/ - unfold TRY3.split_stream2 - simp - have h1 := hw_fork'_of_all_none - (dataIn := Stream'.drop 1 dataIn_1) - (vldIn := Stream'.drop 1 vldIn_1) - (rdOut1 := Stream'.drop 1 rdOut1_1) - (rdOut2 := Stream'.drop 1 rdOut2_1) - (by - intro k - specialize hnevldin (k + 1) - simp [show Stream'.drop 1 vldIn_1 k = vldIn_1 (k + 1) by rfl, hnevldin] - ) - have h2 := hw_fork'_of_all_none - (dataIn := dataIn_1) - (vldIn := vldIn_1) - (rdOut1 := rdOut1_1) - (rdOut2 := rdOut2_1) - (by grind) - rw [hw_fork_eq] - simp_all - and_intros - · rfl - · ext l n - have hlhs := hw_fork_out0 - (data_in := dataIn_1) - (vld_in := vldIn_1) - (rd0_in := rdOut1_1) - (rd1_in := rdOut2_1) - (rdy_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).1) - (vld0_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.1) - (vld1_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.1) - (data0_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) - (data1_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) - (by rw [← hw_fork_eq]; simp [TRY3.split_stream2]) (1 + l) - have hrhs := hw_fork_out0 - (rdy_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).1) - (vld0_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.1) - (vld1_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.1) - (data0_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.1) - (data1_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.2) - (by rw [← hw_fork_eq]; simp [TRY3.split_stream2]) l - simp [Stream'.drop] at hrhs - have h1 : Stream'.get (fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) (1 + l) = - (fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) (1 + l) := by rfl - simp [h1] - have h2 : (Stream'.get (fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) - (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) - (Stream'.drop 1 dataIn_1) i).2.2.2.1) l) = - (fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) - (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) - (Stream'.drop 1 dataIn_1) i).2.2.2.1) l := by rfl - simp [h2] - simp [← hrhs, ← hlhs] - simp [show dataIn_1.get (l + 1) = dataIn_1 (l + 1) by rfl, Nat.add_comm] - · ext l n - have hlhs := hw_fork_out1 - (data_in := dataIn_1) - (vld_in := vldIn_1) - (rd0_in := rdOut1_1) - (rd1_in := rdOut2_1) - (rdy_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).1) - (vld0_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.1) - (vld1_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.1) - (data0_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) - (data1_out := fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) - (by rw [← hw_fork_eq]; simp [TRY3.split_stream2]) (1 + l) - have hrhs := hw_fork_out1 - (rdy_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).1) - (vld0_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.1) - (vld1_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.1) - (data0_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.1) - (data1_out := fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.2) - (by rw [← hw_fork_eq]; simp [TRY3.split_stream2]) l - simp [Stream'.drop] at hrhs - - have h1 : Stream'.get (fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) (1 + l) = - (fun i => (hw_fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) (1 + l) := by rfl - simp [h1] - have h2 : (Stream'.get (fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) - (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) - (Stream'.drop 1 dataIn_1) i).2.2.2.2) l) = - (fun i => - (hw_fork' (Stream'.drop 1 rdOut1_1) - (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) - (Stream'.drop 1 dataIn_1) i).2.2.2.2) l := by rfl - simp [h2] - simp [← hrhs, ← hlhs] - simp [show dataIn_1.get (l + 1) = dataIn_1 (l + 1) by rfl, Nat.add_comm] - · unfold toStream - congr - have : (fun i => if rdIn_1 i = 1#1 ∧ vldIn_1 i = 1#1 then some (dataIn_1 i) else none) = - fun i => none := by - ext k hk - grind - simp [this] - have : (fun i => if rdOut1_1 i = 1#1 ∧ vldOut1_1 i = 1#1 then some (dataOut1_1 i) else none) = - fun i => none := by - ext k hk - grind - simp [this] - · simp - · simp - · apply relation_fork.intro (toStream rdIn vldIn dataIn) (toStream rdOut1 vldOut1 dataOut1) - (dataOut2 := dataOut2) (vldOut2 := vldOut2) - · rfl - · rfl - · assumption - · assumption - · assumption - · congr - · assumption - · assumption - · assumption - - -theorem hw_fork_refines': - /- Given a handshake fork -/ - (x, y) = TRY2.hw_fork a → - /- we get the output of the corresponding lowered fork -/ - (rdy, vld1, vld2, o1, o2) = TRY3.split_stream2 (a := BitVec 1) (TRY3.hw_fork rd1 rd2 vld data) → - /- if we know that the hshake input stream is bisimilar to the ready-valid input of the hw fork -/ - a ~ (toStream rdy vld data) → - /- We want to make sure that stalling is correctly modeled for `a` (input). - We constrain the input and prove that if the input behaves properly, - the output will. -/ - globallyValidUntilReady vld rdy → - globallyValidAndData vld data → - /- we assume no deadlock -/ - globallyFinallyReady rd1 → - globallyFinallyReady rd2 → - /- we want to prove that the outputs of the handshake fork are respectively - bisimilar to the ready-valid wrapping of the output of the hardware fork -/ - x ~ (toStream rd1 vld1 o1) ∧ y ~ (toStream rd2 vld2 o2) := by - intros handshake_fork hardware_fork inputs_bisim valready_ valdata_a finready1 finready2 - · unfold TRY2.hw_fork at handshake_fork - have heq : x = a := by - simp at handshake_fork - exact handshake_fork.1 - have heq' : y = a := by - simp at handshake_fork - exact handshake_fork.2 - rw [heq, heq'] - and_intros - · sorry - · sorry end HWComponents diff --git a/SSA/Projects/CIRCT/HandshakeToHW/HWForkSampling.lean b/SSA/Projects/CIRCT/HandshakeToHW/HWForkSampling.lean index f20a36a277..c9e8c8c0c3 100644 --- a/SSA/Projects/CIRCT/HandshakeToHW/HWForkSampling.lean +++ b/SSA/Projects/CIRCT/HandshakeToHW/HWForkSampling.lean @@ -728,5 +728,93 @@ theorem hw_fork_refines_out1 {dataIn : Stream' (BitVec 32)} · exact hvr · exact hvd +theorem emitted_swap (n : Nat) : emitted rdOut1 rdOut2 vldIn n = (emitted rdOut2 rdOut1 vldIn n).swap := by + induction n + · simp [emitted] + · case _ m ihm => + simp [emitted, ihm, stepRegs] + bv_decide + +/-! Transport of the signals along the swap (mechanical consequences of +`emitted_swap`): each out2 signal of this run is the corresponding out1 signal +of the run with the receivers' readies swapped, and `allDone` is invariant. -/ + +theorem e0_swap (n : Nat) : + e0 rdOut1 rdOut2 vldIn n = e1 rdOut2 rdOut1 vldIn n := by + unfold e0 e1 + rw [emitted_swap rdOut1 rdOut2 vldIn n] + simp + +theorem e1_swap (n : Nat) : + e1 rdOut1 rdOut2 vldIn n = e0 rdOut2 rdOut1 vldIn n := by + unfold e0 e1 + rw [emitted_swap rdOut1 rdOut2 vldIn n] + simp + +theorem vldOut2_swap : + vldOut2 rdOut1 rdOut2 vldIn = vldOut1 rdOut2 rdOut1 vldIn := by + funext n + rw [vldOut2_def, vldOut1_def, e1_swap rdOut1 rdOut2 vldIn n] + +theorem allDone_swap : + allDone rdOut1 rdOut2 vldIn = allDone rdOut2 rdOut1 vldIn := by + funext n + simp only [allDone_def, done0_def, done1_def, fire1_def, fire2_def, + vldOut1_def, vldOut2_def, + e0_swap rdOut1 rdOut2 vldIn, e1_swap rdOut1 rdOut2 vldIn] + bv_decide + +/-- Mirror of `hw_fork_refines_out1` for output 2. Provable without a second +coinduction: `stepRegs` is symmetric under swapping `(rd1, e.1) ↔ (rd2, e.2)`, +so `emitted rdOut1 rdOut2 vldIn n = (emitted rdOut2 rdOut1 vldIn n).swap` (one +induction over time), hence `vldOut2/fire2/e1` of this run are `vldOut1/fire1/e0` +of the swapped run and `allDone` is invariant under the swap (`comb_and` is +commutative). Transport `hw_fork_refines_out1 rdOut2 rdOut1` along these. -/ +theorem hw_fork_refines_out2 {dataIn : Stream' (BitVec 32)} + {rdIn vld1 vld2 : Stream' (BitVec 1)} {data1 data2 : Stream' (BitVec 32)} + (hfork : (rdIn, vld1, vld2, data1, data2) + = TRY3.split_stream2 (TRY3.hw_fork rdOut1 rdOut2 vldIn dataIn)) + (hvr : globallyValidUntilReady vldIn rdIn) + (hvd : globallyValidAndData vldIn dataIn) : + toStream rdIn vldIn dataIn ~ toStream rdOut2 vld2 data2 := by + obtain ⟨h1, -, h3, -, h5⟩ := hw_fork_components rdOut1 rdOut2 vldIn hfork + subst h1 h3 h5 + rw [allDone_swap rdOut1 rdOut2 vldIn] at hvr ⊢ + rw [vldOut2_swap rdOut1 rdOut2 vldIn] + apply HandshakeStream.symm + apply out1_sampling_bisim + · exact hvr + · exact hvd + + +/-- **The RTL fork refines the handshake fork** (`TRY2.hw_fork`), on both +outputs — the original goal of `HWComponents.hw_fork_refines'`, restated. + +Differences from the original statement, on purpose: +* the input is identified with the ready/valid-wrapped stream by *equality* + (`ha`), not by bisimilarity — composing through a `~`-hypothesis needs + transitivity of `~`, which is still `sorry` in `Stream/Basic.lean`; once + `Bisim.trans` is proven, the `a ~ toStream rdIn vldIn dataIn` version follows + immediately from this one; +* `globallyFinallyReady rd1/rd2` are gone: eventual readiness of the receivers + is subsumed by the no-deadlock contract `hvr` on the input channel, through + the circuit equation (`rdIn = allDone` only fires once both receivers have + received). -/ +theorem hw_fork_refines' {dataIn : Stream' (BitVec 32)} + {rdIn vld1 vld2 : Stream' (BitVec 1)} {data1 data2 : Stream' (BitVec 32)} + {x y a : Stream (BitVec 32)} + (hspec : (x, y) = TRY2.hw_fork a) + (hfork : (rdIn, vld1, vld2, data1, data2) + = TRY3.split_stream2 (TRY3.hw_fork rdOut1 rdOut2 vldIn dataIn)) + (ha : a = toStream rdIn vldIn dataIn) + (hvr : globallyValidUntilReady vldIn rdIn) + (hvd : globallyValidAndData vldIn dataIn) : + x ~ toStream rdOut1 vld1 data1 ∧ y ~ toStream rdOut2 vld2 data2 := by + simp only [TRY2.hw_fork, Prod.mk.injEq] at hspec + simp [hspec, ha] + and_intros + · apply hw_fork_refines_out1 (hfork := hfork) (hvr := hvr) (hvd := hvd) + · apply hw_fork_refines_out2 (hfork := hfork) (hvr := hvr) (hvd := hvd) + end Fork end HWComponents diff --git a/SSA/Projects/LLVMRiscV/Evaluation/.gitignore b/SSA/Projects/LLVMRiscV/Evaluation/.gitignore deleted file mode 100644 index f98b5e7882..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -benchmarks/MLIR_single -benchmarks/MLIR_bb0 -benchmarks/LEANMLIR_ASM -benchmarks/LEANMLIR_ASM_opt -benchmarks/LLC_ASM_globalisel -benchmarks/LLC_ASM_selectiondag -benchmarks/LLVM -benchmarks/LLVMIR -benchmarks/logs -benchmarks/XDSL_ASM -benchmarks/XDSL_FUNC -benchmarks/XDSL_FUNC_opt -benchmarks/XDSL_opt_ASM -mca-analysis/results -mca-analysis/data -mca-analysis/tables -mca-analysis/plots \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/issue_53252.lean b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/issue_53252.lean deleted file mode 100644 index 29cb72fca9..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/issue_53252.lean +++ /dev/null @@ -1,47 +0,0 @@ -import SSA.Projects.RISCV64.PrettyEDSL -import LeanMLIR.Framework -import SSA.Projects.LLVMRiscV.PeepholeRefine -import SSA.Projects.LLVMRiscV.Simpproc -import SSA.Projects.RISCV64.Tactic.SimpRiscV -import SSA.Projects.LLVMRiscV.Pipeline.mkRewrite - -/-! - Bug reported in https://github.com/llvm/llvm-project/issues/53252 - and fixed in https://github.com/llvm/llvm-project/commit/4041c44853588c1e4918ec4a160c053cf08432b5 --/ - -namespace BitVec -open LLVMRiscV - -@[simp_denote] -def original := [LV| { - ^entry (%x : i32, %replacement_low : i32, %replacement_high : i32): - %0 = llvm.mlir.constant (0) : i32 - %t0 = llvm.icmp.slt %x, %0 : i32 - %t1 = llvm.select %t0, %replacement_low, %replacement_high : i32 - %65536 = llvm.mlir.constant (65536) : i32 - %t2 = llvm.icmp.ult %x, %65536 : i32 - %true = llvm.mlir.constant (true) : i1 - %1 = llvm.xor %t2, %true : i1 - %r = llvm.select %1, %x, %t1 : i32 - llvm.return %r : i32 -}] - -@[simp_denote] -def optimized_incorrect := [LV| { - ^entry (%x : i32, %replacement_low : i32, %replacement_high : i32): - %0 = llvm.mlir.constant (0) : i32 - %1 = llvm.icmp.slt %x, %0 : i32 - %65535 = llvm.mlir.constant (65535) : i32 - %2 = llvm.icmp.sgt %x, %65535 : i32 - %3 = llvm.select %1, %replacement_low, %x : i32 - %4 = llvm.select %2, %replacement_high, %3 : i32 - llvm.return %4 : i32 - }] - -def bug : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where - lhs:= original - rhs:= optimized_incorrect - correct := by - simp_lowering - <;> sorry diff --git a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/issue_59876.lean b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/issue_59876.lean deleted file mode 100644 index 877a3acb45..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/issue_59876.lean +++ /dev/null @@ -1,48 +0,0 @@ -import SSA.Projects.RISCV64.PrettyEDSL -import LeanMLIR.Framework -import SSA.Projects.LLVMRiscV.PeepholeRefine -import SSA.Projects.LLVMRiscV.Simpproc -import SSA.Projects.RISCV64.Tactic.SimpRiscV -import SSA.Projects.LLVMRiscV.Pipeline.mkRewrite - -/-! - Bug reported in https://github.com/llvm/llvm-project/issues/59876 --/ - -namespace BitVec -open LLVMRiscV - -@[simp_denote] -def original := [LV| { - ^entry (%x : i1): - %1 = llvm.mlir.constant (1) : i1 - %0 = llvm.mul %x, %1 : i1 - llvm.return %0 : i1 -}] - -@[simp_denote] -def optimized_incorrect := [LV| { - ^entry (%x : i1): - %0 = llvm.mlir.constant (0) : i1 - llvm.return %0 : i1 - }] - -@[simp_denote] -def optimized_correct := [LV| { - ^entry (%x : i1): - llvm.return %x : i1 - }] - -def bug : LLVMPeepholeRewriteRefine 1 [Ty.llvm (.bitvec 1)] where - lhs:= original - rhs:= optimized_incorrect - correct := by - simp_lowering - <;> sorry - -def fix : LLVMPeepholeRewriteRefine 1 [Ty.llvm (.bitvec 1)] where - lhs:= original - rhs:= optimized_correct - correct := by - simp_lowering - bv_decide diff --git a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/thesis_ex.lean b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/thesis_ex.lean deleted file mode 100644 index 81ad3e1ea5..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/thesis_ex.lean +++ /dev/null @@ -1,297 +0,0 @@ -import SSA.Projects.RISCV64.PrettyEDSL -import LeanMLIR.Framework -import SSA.Projects.LLVMRiscV.PeepholeRefine -import SSA.Projects.LLVMRiscV.Simpproc -import SSA.Projects.RISCV64.Tactic.SimpRiscV -import SSA.Projects.LLVMRiscV.Pipeline.mkRewrite - -namespace BitVec -open LLVMRiscV --- background LEAN -theorem add_eq_sll (a : Nat) : a + a = a <<< 1 := by omega -- - --- implementing reported SelectionDAG bug -def original_sdiv_srem := [LV| { - ^entry (%a: i64, %b: i64): - %0= llvm.sdiv exact %a, %b : i64 - %1 = llvm.srem %a, %b : i64 - llvm.return %1 : i64 - }] - -def combined_sdiv_srem := [LV| { - ^entry (%a: i64, %b: i64): - %0= llvm.sdiv exact %a, %b : i64 - %1 = llvm.mul %b, %0 : i64 - %2 = llvm.sub %a, %1 : i64 - llvm.return %2 : i64 - }] - -theorem mul_sdiv_cancel_of_dvd_of_ne {w : Nat} {x y : BitVec w} - (h₁ : y.smod x = 0#_) - (h₂ : y ≠ intMin w ∨ x ≠ -1#w) : - x * y.sdiv x = y := by - apply eq_of_toInt_eq - simp only [toInt_mul] - rw [BitVec.toInt_sdiv_of_ne_or_ne _ _ h₂] - rw [← BitVec.toInt_inj, BitVec.toInt_smod, BitVec.toInt_zero] at h₁ - rw [Int.mul_tdiv_cancel' (Int.dvd_of_fmod_eq_zero h₁)] - exact toInt_bmod_cancel y - -theorem srem_eq_zero_of_smod {w : Nat} {x y : BitVec w} : - x.smod y = 0#_ → x.srem y = 0#_ := by - simp only [← toInt_inj, toInt_smod, toInt_zero, toInt_srem] - intro h - simp [Int.tmod_eq_fmod, Int.dvd_of_fmod_eq_zero h, h] - -def buggy_ISEL_pattern : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where - lhs:= original_sdiv_srem - rhs:= combined_sdiv_srem - correct := by - unfold original_sdiv_srem combined_sdiv_srem - simp_peephole - simp_alive_undef - simp_alive_ops - simp_alive_case_bash - intro x x1 - split - case value.value.isTrue ht => - simp [ht] - case value.value.isFalse hf => - simp - split - case isTrue ht => - simp [ht, hf] - simp at hf - obtain ⟨hf₁, hf₂⟩ := hf - replace hf₂ : x ≠ intMin _ ∨ x1 ≠ -1#64 := by - by_cases h : x = intMin _ - · exact .inr <| hf₂ h - · exact .inl h - simp only [mul_sdiv_cancel_of_dvd_of_ne ht hf₂, BitVec.sub_self] - apply srem_eq_zero_of_smod ht - case isFalse hf => - sorry - -- sorry -- this case shows how the pattern is wrong in the case of an exact flag. - -def original_sdiv_srem_correct := [LV| { - ^entry (%a: i64, %b: i64): - %0= llvm.sdiv %a, %b : i64 - %1 = llvm.srem %a, %b : i64 - llvm.return %1 : i64 - }] - -def combined_sdiv_srem_correct := [LV| { - ^entry (%a: i64, %b: i64): - %0= llvm.sdiv %a, %b : i64 - %1 = llvm.mul %b, %0 : i64 - %2 = llvm.sub %a, %1 : i64 - llvm.return %2 : i64 - }] - -theorem srem_eq_sub_sdiv (x y : BitVec w) (h1 : ¬y = 0#_ ) (hf₂ : x ≠ intMin w ∨ y ≠ -1#w) : - x.srem y = x - y * x.sdiv y := by - rw [← toInt_inj] - rw [BitVec.toInt_srem] - rw [BitVec.toInt_sub] - rw [BitVec.toInt_mul] - simp - rw [BitVec.toInt_sdiv_of_ne_or_ne x y (h:= hf₂)] - rw [ Int.bmod_eq_of_le (by sorry) (by sorry)] - rw [Int.tmod_def] --- x x1 : BitVec 64 --- hf₁ : ¬x1 = 0#64 --- hf₂ : x ≠ intMin 64 ∨ x1 ≠ sorry --- ⊢ x.srem x1 = x - x1 * x.sdiv x1 - - -def corrected_ISEL_pattern : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where - lhs:= original_sdiv_srem_correct - rhs:= combined_sdiv_srem_correct - correct := by - unfold original_sdiv_srem_correct combined_sdiv_srem_correct - simp_peephole - simp_alive_undef - simp_alive_ops - simp_alive_case_bash - intro x x1 - split - case value.value.isFalse hf => - simp at hf - obtain ⟨hf₁, hf₂⟩ := hf - replace hf₂ : x ≠ intMin _ ∨ x1 ≠ -1#64 := by - by_cases h : x = intMin _ - · exact .inr <| hf₂ h - · exact .inl h - simp only [PoisonOr.value_isRefinedBy_value, InstCombine.bv_isRefinedBy_iff] - --bv_decide - sorry - --simp [hf₁, hf₂] - case value.value.isTrue ht => - simp only [PoisonOr.isRefinedBy_self] - -def llvm_sub_self_ex := [LV| { - ^entry (%x: i64 ): - %1 = llvm.sub %x, %x : i64 - llvm.return %1 : i64 - }] - - -- simp riscv example - -@[simp_denote] -def sub_riscv_self_ex := [LV| { - ^entry (%x: i64): - %0 = "builtin.unrealized_conversion_cast"(%x) : (i64) -> (!i64) - %2 = sub %0, %0 : !i64 - %4 = sltu %0, %0 : !i64 - %3 = "builtin.unrealized_conversion_cast"(%2) : (!i64) -> (i64) - llvm.return %3 : i64 - }] - - - -def example00 := [RV64_com| { -^bb0(%0 : !riscv.reg, %1 : !riscv.reg): - %2 = "slt"(%0, %1) : (!riscv.reg, !riscv.reg) -> (!riscv.reg) - %3 = "andi" (%2){imm = 1 : !i64} : (!riscv.reg) -> (!riscv.reg) - %4 = "sra"(%0, %0) : (!riscv.reg, !riscv.reg) -> (!riscv.reg) - %5 = "add"(%0, %0) : (!riscv.reg, !riscv.reg) -> (!riscv.reg) - %6 = "sra"(%2, %5) : (!riscv.reg, !riscv.reg) -> (!riscv.reg) - "ret" (%0) : (!riscv.reg) -> () - }].denote - - -def example01 := [RV64_com| { -^bb0(%0 : !i64, %1 : !i64): - --%2 = "riscv.slt"(%0, %1) : (!riscv.reg, !riscv.reg) -> (!riscv.reg) - --%2 = "riscv.andi"(%2){immediate = 1 : i12 } : (!riscv.reg) -> (!riscv.reg) - -- %4 = "riscv.sra"(%0, %0) : (!riscv.reg, !riscv.reg) -> (!riscv.reg) - %5 = "add"(%0, %0) : (!i64, !i64) -> (!i64) - --%6 = "riscv.sra"(%2, %5) : (!riscv.reg, !riscv.reg) -> (!riscv.reg) - "ret" (%0) : (!i64) -> () - }] - - - -def llvm_sub_lower_riscv_no_flag_self: LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := llvm_sub_self_ex - rhs := sub_riscv_self_ex - correct := by - unfold llvm_sub_self_ex sub_riscv_self_ex - simp_peephole - simp_alive_undef - simp_alive_ops - simp_alive_case_bash - simp_riscv - simp_peephole - sorry - - -@[simp_denote] -def llvm_urem: Com LLVMPlusRiscV ⟨[.llvm (.bitvec 64), .llvm (.bitvec 64)]⟩ - .pure (.llvm (.bitvec 64)) := [LV| { - ^entry (%x: i64, %y: i64 ): - %1 = llvm.urem %x, %y : i64 - llvm.return %1 : i64 - }] -@[simp_denote] -def urem_riscv: Com LLVMPlusRiscV ⟨[.llvm (.bitvec 64), .llvm (.bitvec 64)]⟩ - .pure (.llvm (.bitvec 64)) := [LV| { - ^entry (%reg1: i64, %reg2: i64): - %0 = "builtin.unrealized_conversion_cast"(%reg1) : (i64) -> (!i64) - %1 = "builtin.unrealized_conversion_cast"(%reg2) : (i64) -> (!i64) - %2 = remu %0, %1 : !i64 - %3 = "builtin.unrealized_conversion_cast"(%2) : (!i64) -> (i64) - llvm.return %3 : i64 - }] - def llvm_urem_lower_riscv: LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] := - {lhs := llvm_urem, rhs := urem_riscv } - - -def intro_example_lhs := [LV| { - ^entry (%arg: i64, %amount: i64): - %0 = llvm.shl %arg, %amount : i64 - %1 = llvm.lshr %0, %amount : i64 - llvm.return %1 : i64 - }] - -def intro_example_rhs := [LV| { - ^entry (%arg: i64, %amount: i64): - llvm.return %arg : i64 - }] - -def rewrite00 : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where - lhs:= [LV| { - ^entry (%arg: i64, %amount: i64): - %0 = llvm.shl %arg, %amount : i64 - %1 = llvm.lshr %0, %amount : i64 - llvm.return %1 : i64 - }] - - rhs:= [LV| { - ^entry (%arg: i64, %amount: i64): - llvm.return %arg : i64 - }] - correct := by - simp_lowering - sorry - --bv_decide - -@[simp_denote] -def intro_example_correct_lhs := [LV| { - ^entry (%arg0: i64): - %c = llvm.mlir.constant (4) : i64 - %1 = llvm.mul %arg0, %c : i64 - llvm.return %1 : i64 - }] - -@[simp_denote] -def intro_example_correct_rhs := [LV| { - ^entry (%arg0: i64): - %r1 = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!riscv.reg) - %c = slli %r1, 2 : !riscv.reg - %rd = "builtin.unrealized_conversion_cast" (%c) : (!riscv.reg) -> (i64) - llvm.return %rd : i64 - }] - -def selection00 : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs:= [LV| { - ^entry (%arg0: i64): - %c = llvm.mlir.constant (4) : i64 - %1 = llvm.mul %arg0, %c : i64 - llvm.return %1 : i64 - }] - rhs:= [LV| { - ^entry (%arg0: i64): - %r1 = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!riscv.reg) - %c = slli %r1, 2 : !riscv.reg - %rd = "builtin.unrealized_conversion_cast" (%c) : (!riscv.reg) -> (i64) - llvm.return %rd : i64 - }] - - -/- Below are two example programs to test our instruction selector.-/ -def llvm00:= - [LV|{ - ^bb0(%X : i64, %Y : i64 ): - %1 = llvm.add %X, %Y : i64 - %2 = llvm.sub %X, %X : i64 - %3 = llvm.add %1, %Y : i64 - %4 = llvm.add %3, %Y : i64 - %5 = llvm.add %3, %4 : i64 - llvm.return %5 : i64 - }] -def llvm01:= - [LV|{ - ^bb0(%X : i64, %Y : i64 ): - %1 = llvm.icmp.eq %X, %Y : i64 - %2 = llvm.sub %X, %X : i64 - llvm.return %1 : i1 - }] - -def llvm02:= - [LV|{ - ^bb0(%X : i64, %Y : i64 ): - %1 = llvm.mlir.constant 9 : i64 - %2 = llvm.sub %X, %X : i64 - llvm.return %1 : i64 - }] diff --git a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add-imm.lean b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add-imm.lean deleted file mode 100644 index 23952ce1d0..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add-imm.lean +++ /dev/null @@ -1,274 +0,0 @@ -import SSA.Projects.LLVMRiscV.Pipeline.InstructionLowering - -open LLVMRiscV - -/-! - This file implements the `add-imm.ll` test case in the LLVM test suite: - https://github.com/llvm/llvm-project/blob/b424207cdddfa2cbfc9129bbe0a31e47cb04e6dc/llvm/test/CodeGen/RISCV/add-imm.ll --/ - - -/-- ### add_positive_low_bound_reject -/ -@[simp_denote] -def add_positive_low_bound_reject_llvm := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (2047) : i32 - %1 = llvm.add %a, %0 : i32 - llvm.return %1 :i32 - }] - -@[simp_denote] -def add_positive_low_bound_reject_riscv := - [LV| { - ^entry (%arg: i32): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %0 = addiw %a, 2047 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) - llvm.return %1 :i32 - }] - -def add_positive_low_bound_reject_test: LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := add_positive_low_bound_reject_llvm - rhs := add_positive_low_bound_reject_riscv - - -/-- ### add_positive_low_bound_accept -/ -@[simp_denote] -def add_positive_low_bound_accept_llvm := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (2048) : i32 - %1 = llvm.add %0, %a : i32 - llvm.return %1 :i32 - }] - -@[simp_denote] -def add_positive_low_bound_accept_riscv := - [LV| { - ^entry (%arg: i32): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %0 = addi %a, 2047 : !i64 - %1 = addiw %0, 1 : !i64 - %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) - llvm.return %2 :i32 - }] - -def add_positive_low_bound_accept_test: LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := add_positive_low_bound_accept_llvm - rhs := add_positive_low_bound_accept_riscv - -/-- ### add_positive_high_bound_accept -/ -@[simp_denote] -def add_positive_high_bound_accept_llvm := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (4094) : i32 - %1 = llvm.add %0, %a : i32 - llvm.return %1 :i32 - }] - -@[simp_denote] -def add_positive_high_bound_accept_riscv := - [LV| { - ^entry (%arg: i32): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %0 = addi %a, 2047 : !i64 - %1 = addiw %0, 2047 : !i64 - %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) - llvm.return %2 :i32 - }] - -def add_positive_high_bound_accept_test: LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := add_positive_high_bound_accept_llvm - rhs := add_positive_high_bound_accept_riscv - - -/-- ### add_positive_high_bound_reject -/ -@[simp_denote] -def add_positive_high_bound_reject_llvm := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (4095) : i32 - %1 = llvm.add %0, %a : i32 - llvm.return %1 :i32 - }] - -@[simp_denote] -def add_positive_high_bound_reject_riscv := - [LV| { - ^entry (%arg: i32): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %0 = li (843949575) : !i64 - %1 = "lui" (%0) {imm = 1 : !i64} : (!i64) -> (!i64) - %2 = "addi" (%1) {imm = -1 : !i64} : (!i64) -> (!i64) - %3 = addw %2, %a: !i64 - %4 = "builtin.unrealized_conversion_cast" (%3) : (!i64) -> (i32) - llvm.return %4 :i32 - }] - -def add_positive_high_bound_reject_test: LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := add_positive_high_bound_reject_llvm - rhs := add_positive_high_bound_reject_riscv - - -/-- ### add_negative_high_bound_reject -/ -@[simp_denote] -def add_negative_high_bound_reject_llvm := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (-2048) : i32 - %1 = llvm.add %a, %0 : i32 - llvm.return %1 :i32 - }] - -@[simp_denote] -def add_negative_high_bound_reject_riscv := - [LV| { - ^entry (%arg: i32): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %0 = "addiw" (%a) {imm = -2048 : !i64} : (!i64) -> (!i64) - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) - llvm.return %1 :i32 - }] - -def add_negative_high_bound_reject_test: LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := add_negative_high_bound_reject_llvm - rhs := add_negative_high_bound_reject_riscv - - -/-- ### add_negative_high_bound_accept -/ -@[simp_denote] -def add_negative_high_bound_accept_llvm := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (-2049) : i32 - %1 = llvm.add %a, %0 : i32 - llvm.return %1 : i32 -}] - -@[simp_denote] -def add_negative_high_bound_accept_riscv := [LV| { - ^entry (%arg: i32): - %0 = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %1 = "addiw" (%0) {imm = -2048 : !i64} : (!i64) -> (!i64) - %2 = "addiw" (%1) {imm = -1 : !i64} : (!i64) -> (!i64) - %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i32) - llvm.return %3 : i32 -}] - -def add_negative_high_bound_accept_test: LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := add_negative_high_bound_accept_llvm - rhs := add_negative_high_bound_accept_riscv - -/-- ### add_negative_low_bound_accept -/ -@[simp_denote] -def add_negative_low_bound_accept_llvm := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (-4096) : i32 - %1 = llvm.add %a, %0 : i32 - llvm.return %1 : i32 -}] - -@[simp_denote] -def add_negative_low_bound_accept_riscv := [LV| { - ^entry (%arg: i32): - %0 = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %1 = "addi" (%0) {imm = -2048 : !i64} : (!i64) -> (!i64) - %2 = "addiw" (%1) {imm = -2048 : !i64} : (!i64) -> (!i64) - %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i32) - llvm.return %3 : i32 -}] - -def add_negative_low_bound_accept_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := add_negative_low_bound_accept_llvm - rhs := add_negative_low_bound_accept_riscv - -/-- ### add_negative_low_bound_reject -/ -@[simp_denote] -def add_negative_low_bound_reject_llvm := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (-4097) : i32 - %1 = llvm.add %a, %0 : i32 - llvm.return %1 : i32 -}] - -@[simp_denote] -def add_negative_low_bound_reject_riscv := [LV| { - ^entry (%arg: i32): - %0 = li (843949575) : !i64 -- random value bc can make any assumption in the value of a1 - %1 = "lui" (%0) {imm = 1048575 : !i64} : (!i64) -> (!i64) - %2 = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %3 = "addi" (%1) {imm = -1 : !i64} : (!i64) -> (!i64) - %4 = addw %2, %3 : !i64 - %5 = "builtin.unrealized_conversion_cast" (%4) : (!i64) -> (i32) - llvm.return %5 : i32 -}] - -def add_negative_low_bound_reject_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := add_negative_low_bound_reject_llvm - rhs := add_negative_low_bound_reject_riscv - -/-- ### add32_accept -/ -@[simp_denote] -def add32_accept_llvm := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (2999) : i32 - %1 = llvm.add %a, %0 : i32 - llvm.return %1 : i32 -}] - -@[simp_denote] -def add32_accept_riscv := [LV| { - ^entry (%arg: i32): - %0 = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %1 = "addi" (%0) {imm = 2047 : !i64} : (!i64) -> (!i64) - %2 = addiw %1, 952 : !i64 - %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i32) - llvm.return %3 : i32 -}] - -def add32_accept_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := add32_accept_llvm - rhs := add32_accept_riscv - -/-- ### add32_sext_accept -/ -@[simp_denote] -def add32_sext_accept_llvm := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (2999) : i32 - %1 = llvm.add %a, %0 : i32 - llvm.return %1 : i32 -}] - -@[simp_denote] -def add32_sext_accept_riscv := [LV| { - ^entry (%arg: i32): - %0 = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64)-- sext performed here - %1 = "addi" (%0) {imm = 2047 : !i64} : (!i64) -> (!i64) - %2 = addiw %1, 952 : !i64 - %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i32) - llvm.return %3 : i32 -}] - -def add32_sext_accept_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := add32_sext_accept_llvm - rhs := add32_sext_accept_riscv - - -/-- ### add64_accept -/ -@[simp_denote] -def add64_accept_llvm := [LV| { - ^entry (%a: i64): - %0 = llvm.mlir.constant (2999) : i64 - %1 = llvm.add %a, %0 : i64 - llvm.return %1 : i64 -}] - -@[simp_denote] -def add64_accept_riscv := [LV| { - ^entry (%arg: i64): - %0 = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64)-- sext performed here - %1 = addi %0, 2047 : !i64 - %2 = addi %1, 952 : !i64 - %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i64) - llvm.return %3 : i64 -}] - -def add64_accept_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := add64_accept_llvm - rhs := add64_accept_riscv diff --git a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add-imm64-to-sub.lean b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add-imm64-to-sub.lean deleted file mode 100644 index 9d07cf8148..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add-imm64-to-sub.lean +++ /dev/null @@ -1,163 +0,0 @@ -import SSA.Projects.LLVMRiscV.Pipeline.InstructionLowering - -open LLVMRiscV - -/-! - This file implements the `add-imm.ll` test case in the LLVM test suite: - https://github.com/llvm/llvm-project/blob/b424207cdddfa2cbfc9129bbe0a31e47cb04e6dc/llvm/test/CodeGen/RISCV/add-imm64-to-sub.ll --/ - -/-- ### add_b31 -/ -@[simp_denote] -def add_b31_llvm_i64 := [LV| { - ^entry (%x: i64): - %0 = llvm.mlir.constant (2147483648) : i64 - %1 = llvm.add %x, %0 : i64 - llvm.return %1 : i64 - }] - -@[simp_denote] -def add_b31_riscv_i64 := - [LV| { - ^entry (%x: i64): - %random = li (574385585755) : !i64 - %0 = "lui" (%random) {imm = 524288 : !i64} : (!i64) -> (!i64) - %a0 = "builtin.unrealized_conversion_cast" (%x) : (i64) -> (!i64) - %1 = sub %a0, %0 : !i64 - %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i64) - llvm.return %2 : i64 - }] - -@[simp_denote] -def add_b31_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := add_b31_llvm_i64 - rhs := add_b31_riscv_i64 - - -/-- ### add_b32 -/ -@[simp_denote] -def add_b32_llvm_i64 := [LV| { - ^entry (%x: i64): - %0 = llvm.mlir.constant (-4294967296) : i64 - %1 = llvm.add %x, %0 : i64 - llvm.return %1 : i64 - }] - -@[simp_denote] -def add_b32_riscv_i64_no_ZBS := - [LV| { - ^entry (%x: i64): - %0 ="li"() {imm = -1 : !i64} : (!i64) -> (!i64) - %1 = slli %0, 32 : !i64 - %a0 = "builtin.unrealized_conversion_cast" (%x) : (i64) -> (!i64) - %2 = add %a0, %1 : !i64 - %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i64) - llvm.return %3 : i64 - }] - -@[simp_denote] -def add_b32_riscv_i64_ZBS := - [LV| { - ^entry (%x: i64): - %zero ="li"() {imm = 0 : !i64} : (!i64) -> (!i64) - %a1 = bseti %zero, 32 : !i64 - %a0 = "builtin.unrealized_conversion_cast" (%x) : (i64) -> (!i64) - %0 = sub %a0, %a1 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) - llvm.return %1 : i64 - }] - -def add_b32_test_no_ZBS_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := add_b32_llvm_i64 - rhs := add_b32_riscv_i64_no_ZBS - - -def add_b32_test_ZBS_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := add_b32_llvm_i64 - rhs := add_b32_riscv_i64_ZBS - - -/-- ### sub_0xffffffffff -/ -@[simp_denote] -def sub_0xffffffffff_llvm_i64 := [LV| { - ^entry (%x: i64): - %0 = llvm.mlir.constant (1099511627775) : i64 - %1 = llvm.sub %x, %0 : i64 - llvm.return %1 : i64 - }] - -@[simp_denote] -def sub_0xffffffffff_riscv_i64 := - [LV| { - ^entry (%x: i64): - %0 = "li"() {imm = -1 : !i64} : (!i64) -> (!i64) - %1 = srli %0, 24 : !i64 - %a0 = "builtin.unrealized_conversion_cast" (%x) : (i64) -> (!i64) - %2 = sub %a0, %1 : !i64 - %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i64) - llvm.return %3 : i64 - }] - -def sub_0xffffffffff_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := sub_0xffffffffff_llvm_i64 - rhs := sub_0xffffffffff_riscv_i64 - - -/-- ### add_multiuse -/ -@[simp_denote] -def add_multiuse_llvm_i64 := [LV| { - ^entry (%x: i64): - %0 = llvm.mlir.constant (-1099511627775) : i64 - %1 = llvm.add %x, %0 : i64 - %2 = llvm.and %1, %0 : i64 - llvm.return %2 : i64 - }] - -@[simp_denote] -def add_multiuse_riscv_i64 := - [LV| { - ^entry (%x: i64): - %0 = "li"() {imm = -1 : !i64} : (!i64) -> (!i64) - %1 = slli %0, 40 : !i64 - %2 = addi %1, 1 : !i64 - %a0 = "builtin.unrealized_conversion_cast" (%x) : (i64) -> (!i64) - %3 = add %a0, %2 : !i64 - %4 = and %3, %2 : !i64 - %5 = "builtin.unrealized_conversion_cast" (%4) : (!i64) -> (i64) - llvm.return %5 : i64 - }] - -def add_multiuse_riscv_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := add_multiuse_llvm_i64 - rhs := add_multiuse_riscv_i64 - - -/-- ### add_multiuse_const -/ -@[simp_denote] -def add_multiuse_const_llvm_i64 := [LV| { - ^entry (%x: i64, %y: i64): - %0 = llvm.mlir.constant (-1099511627775) : i64 - %1 = llvm.add %x, %0 : i64 - %2 = llvm.add %y, %0 : i64 - %3 = llvm.xor %1, %2 : i64 - llvm.return %3 : i64 - }] - -@[simp_denote] -def add_multiuse_const_riscv_i64 := - [LV| { - ^entry (%x: i64, %y: i64): - %0 = "li"() {imm = -1 : !i64} : (!i64) -> (!i64) - %1 = srli %0, 24 : !i64 - %a0 = "builtin.unrealized_conversion_cast" (%x) : (i64) -> (!i64) - %2 = sub %a0, %1 : !i64 - %a1 = "builtin.unrealized_conversion_cast" (%y) : (i64) -> (!i64) - %3 = sub %a1, %1 : !i64 - %4 = xor %2, %3 : !i64 - %5 = "builtin.unrealized_conversion_cast" (%4) : (!i64) -> (i64) - llvm.return %5 : i64 - }] - -def add_multiuse_const_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64) ] where - lhs := add_multiuse_const_llvm_i64 - rhs := add_multiuse_const_riscv_i64 diff --git a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add_sext_shl_constant.lean b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add_sext_shl_constant.lean deleted file mode 100644 index 89bbba9c9e..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add_sext_shl_constant.lean +++ /dev/null @@ -1,217 +0,0 @@ -import SSA.Projects.LLVMRiscV.Pipeline.InstructionLowering - -open LLVMRiscV - -/-! - This file implements the `add_sext_shl_constant.ll` test case in the LLVM test suite: - https://github.com/llvm/llvm-project/blob/b424207cdddfa2cbfc9129bbe0a31e47cb04e6dc/llvm/test/CodeGen/RISCV/add_sext_shl_constant.ll --/ - -/-- ### add_shl_moreOneUse_sh1add -/ -@[simp_denote] -def add_shl_moreOneUse_sh1add := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (1) : i32 - %1 = llvm.or %a, %0 : i32 - %2 = llvm.shl %1, %0 : i32 - %3 = llvm.add %2, %1 : i32 - llvm.return %3 : i32 - }] - -@[simp_denote] -def add_shl_moreOneUse_sh1add_riscv_no_ZBA := [LV| { - ^entry (%a: i32): - %a0 = "builtin.unrealized_conversion_cast" (%a) : (i32) -> (!i64) - %0 = ori %a0, 1 : !i64 - %1 = slli %a0, 1 : !i64 - %2 = ori %1, 2 : !i64 - %3 = add %2, %0 : !i64 - %4 = "builtin.unrealized_conversion_cast" (%3) : (!i64) -> (i32) - llvm.return %4 : i32 - }] - -@[simp_denote] -def add_shl_moreOneUse_sh1add_riscv_ZBA := [LV| { - ^entry (%a: i32): - %a0 = "builtin.unrealized_conversion_cast" (%a) : (i32) -> (!i64) - %0 = ori %a0, 1 : !i64 - %1 = sh1add %0, %0 : !i64 - %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) - llvm.return %2 : i32 - }] - -def add_shl_moreOneUse_sh1add_ZBA_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := add_shl_moreOneUse_sh1add - rhs := add_shl_moreOneUse_sh1add_riscv_ZBA - - -def add_shl_moreOneUse_sh1add_no_ZBA_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := add_shl_moreOneUse_sh1add - rhs := add_shl_moreOneUse_sh1add_riscv_no_ZBA - -/-- ### add_shl_moreOneUse_sh2add -/ -@[simp_denote] -def add_shl_moreOneUse_sh2add := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (1) : i32 - %c2 = llvm.mlir.constant (2) : i32 - %1 = llvm.or %a, %0 : i32 - %2 = llvm.shl %1, %c2 : i32 - %3 = llvm.add %2, %1 : i32 - llvm.return %3 : i32 - }] - -@[simp_denote] -def add_shl_moreOneUse_sh2add_riscv_no_ZBA := [LV| { - ^entry (%a: i32): - %a0 = "builtin.unrealized_conversion_cast" (%a) : (i32) -> (!i64) - %0 = ori %a0, 1 : !i64 - %1 = slli %a0, 2 : !i64 - %2 = ori %1, 4 : !i64 - %3 = add %2, %0 : !i64 - %4 = "builtin.unrealized_conversion_cast" (%3) : (!i64) -> (i32) - llvm.return %4 : i32 - }] - -@[simp_denote] -def add_shl_moreOneUse_sh2add_riscv_ZBA := [LV| { - ^entry (%a: i32): - %a0 = "builtin.unrealized_conversion_cast" (%a) : (i32) -> (!i64) - %0 = ori %a0, 1 : !i64 - %1 = sh2add %0, %0 : !i64 - %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) - llvm.return %2 : i32 - }] - -def add_shl_moreOneUse_sh2add_ZBA_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := add_shl_moreOneUse_sh2add - rhs := add_shl_moreOneUse_sh2add_riscv_ZBA - -def add_shl_moreOneUse_sh2add_no_ZBA_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := add_shl_moreOneUse_sh2add - rhs := add_shl_moreOneUse_sh2add_riscv_no_ZBA - -/-- ### add_shl_moreOneUse_sh3add -/ -@[simp_denote] -def add_shl_moreOneUse_sh3add := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (1) : i32 - %c2 = llvm.mlir.constant (3) : i32 - %1 = llvm.or %a, %0 : i32 - %2 = llvm.shl %1, %c2 : i32 - %3 = llvm.add %2, %1 : i32 - llvm.return %3 : i32 - }] - -@[simp_denote] -def add_shl_moreOneUse_sh3add_riscv_no_ZBA := [LV| { - ^entry (%a: i32): - %a0 = "builtin.unrealized_conversion_cast" (%a) : (i32) -> (!i64) - %0 = ori %a0, 1 : !i64 - %1 = slli %a0, 3 : !i64 - %2 = ori %1, 8 : !i64 - %3 = add %2, %0 : !i64 - %4 = "builtin.unrealized_conversion_cast" (%3) : (!i64) -> (i32) - llvm.return %4 : i32 - }] - -@[simp_denote] -def add_shl_moreOneUse_sh3add_riscv_ZBA := [LV| { - ^entry (%a: i32): - %a0 = "builtin.unrealized_conversion_cast" (%a) : (i32) -> (!i64) - %0 = ori %a0, 1 : !i64 - %1 = sh3add %0, %0 : !i64 - %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) - llvm.return %2 : i32 - }] - -def add_shl_moreOneUse_sh3add_ZBA_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := add_shl_moreOneUse_sh3add - rhs := add_shl_moreOneUse_sh3add_riscv_ZBA - -def add_shl_moreOneUse_sh3add_no_ZBA_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := add_shl_moreOneUse_sh3add - rhs := add_shl_moreOneUse_sh3add_riscv_no_ZBA - - -/-- ### add_shl_sext -/ -@[simp_denote] -def add_shl_sext_llvm := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (3) : i32 - %1 = llvm.add %a, %0 : i32 - %2 = llvm.shl %1, %a : i32 - %3 = llvm.sext %2 : i32 to i64 - llvm.return %3 : i64 - }] - -@[simp_denote] -def add_shl_sext_riscv := [LV| { - ^entry (%a: i32): - %a0 = "builtin.unrealized_conversion_cast" (%a) : (i32) -> (!i64) - %0 = addi %a0, 3 : !i64 - %1 = sllw %0, %a0 : !i64 - %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i64) - llvm.return %2 : i64 - }] - -def add_shl_sext_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 32)] where - lhs := add_shl_sext_llvm - rhs := add_shl_sext_riscv - -/-- ### add_shl_moreOneUse_sh4add -/ -@[simp_denote] -def add_shl_moreOneUse_sh4add_llvm := [LV| { - ^entry (%a: i64): - %0 = llvm.mlir.constant (1) : i64 - %c4 = llvm.mlir.constant (4) : i64 - %1 = llvm.or %a, %0 : i64 - %2 = llvm.shl %1, %c4 : i64 - %3 = llvm.add %1, %2 : i64 - llvm.return %3 : i64 - }] - -@[simp_denote] -def add_shl_moreOneUse_sh4add_riscv := [LV| { - ^entry (%a: i64): - %a0 = "builtin.unrealized_conversion_cast" (%a) : (i64) -> (!i64) - %0 = ori %a0, 1 : !i64 - %1 = slli %a0, 4 : !i64 - %2 = ori %1, 16 : !i64 - %3 = add %2, %0 : !i64 - %4 = "builtin.unrealized_conversion_cast" (%3) : (!i64) -> (i64) - llvm.return %4 : i64 - }] - -def add_shl_moreOneUse_sh4add_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := add_shl_moreOneUse_sh4add_llvm - rhs :=add_shl_moreOneUse_sh4add_riscv - -/-- ### add_shl_rhs_constant -/ -@[simp_denote] -def add_shl_rhs_constant_llvm := [LV| { - ^entry (%a0: i64, %a1: i64): - %0 = llvm.mlir.constant (1) : i64 - %c3 = llvm.mlir.constant (3) : i64 - %c8 = llvm.mlir.constant (-8) : i64 - %1 = llvm.add %a0, %0 : i64 - %2 = llvm.add %a1, %1 : i64 - %3 = llvm.shl %2, %c3 : i64 - %4 = llvm.add %3, %c8 : i64 - llvm.return %4 : i64 - }] - -@[simp_denote] -def add_shl_rhs_constant_riscv := [LV| { - ^entry (%a: i64, %b: i64): - %a0 = "builtin.unrealized_conversion_cast" (%a) : (i64) -> (!i64) - %a1 = "builtin.unrealized_conversion_cast" (%b) : (i64) -> (!i64) - %0 = add %a0, %a1 : !i64 - %1 = slli %0, 3 : !i64 - %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i64) - llvm.return %2 : i64 - }] - -def add_shl_rhs_constant_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64),Ty.llvm (.bitvec 64) ] where - lhs := add_shl_rhs_constant_llvm - rhs := add_shl_rhs_constant_riscv diff --git a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu16.lean b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu16.lean deleted file mode 100644 index 20d9c3afb1..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu16.lean +++ /dev/null @@ -1,525 +0,0 @@ -import SSA.Projects.LLVMRiscV.Pipeline.InstructionLowering - - -open LLVMRiscV - -/-! - This file implements the `alu16.ll` test case in the LLVM test suite: - https://github.com/llvm/llvm-project/blob/b424207cdddfa2cbfc9129bbe0a31e47cb04e6dc/llvm/test/CodeGen/RISCV/alu16.ll --/ - - -/-- ### addi -/ -@[simp_denote] -def addi_llvm := [LV| { - ^entry (%a: i16): - %0 = llvm.mlir.constant (1) : i16 - %1 = llvm.add %a, %0 : i16 - llvm.return %1 :i16 - }] - -@[simp_denote] -def addi_riscv := - [LV| { - ^entry (%arg: i16): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) - %0 = addi %a, 1 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) - llvm.return %1 :i16 - }] - -def addi_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where - lhs := addi_llvm - rhs := addi_riscv - - -/-- ### slti -/ -@[simp_denote] -def slti_llvm := [LV| { - ^entry (%a: i16): - %0 = llvm.mlir.constant (2) : i16 - %1 = llvm.icmp.slt %a, %0 : i16 - %2 = llvm.zext %1: i1 to i16 - llvm.return %2 :i16 - }] - -@[simp_denote] -def slti_riscv := - [LV| { - ^entry (%arg: i16): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) - %0 = slli %a, 48 : !i64 - %1 = srai %0, 48 : !i64 - %2 = slti %1, 2 : !i64 - %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i16) - llvm.return %3 :i16 - }] - -def slti_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where - lhs := slti_llvm - rhs := slti_riscv - - -/-- ### sltiu -/ -@[simp_denote] -def sltiu_llvm := [LV| { - ^entry (%a: i16): - %0 = llvm.mlir.constant (3) : i16 - %1 = llvm.icmp.ult %a, %0 : i16 - %2 = llvm.zext %1: i1 to i16 - llvm.return %2 :i16 - }] - -@[simp_denote] -def sltiu_riscv := - [LV| { - ^entry (%arg: i16): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) - %0 = slli %a, 48 : !i64 - %1 = srli %0, 48 : !i64 - %2 = sltiu %1, 3 : !i64 - %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i16) - llvm.return %3 :i16 - }] - -def sltiu_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where - lhs := sltiu_llvm - rhs := sltiu_riscv - - -/-- ### sltiu_signext -/ -@[simp_denote] -def sltiu_signext_llvm := [LV| { - ^entry (%a: i16): - %0 = llvm.mlir.constant (10) : i16 - %1 = llvm.icmp.ult %a, %0 : i16 - %2 = llvm.zext %1: i1 to i16 - llvm.return %2 :i16 - }] - -@[simp_denote] -def sltiu_signext_riscv := - [LV| { - ^entry (%arg: i16): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) - %0 = sltiu %a, 10 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) - llvm.return %1 :i16 - }] - -def sltiu_signext_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where - lhs := sltiu_signext_llvm - rhs := sltiu_signext_riscv - - -/-- ### xori -/ -@[simp_denote] -def xori_llvm := [LV| { - ^entry (%a: i16): - %0 = llvm.mlir.constant (4) : i16 - %1 = llvm.xor %a, %0 : i16 - llvm.return %1 :i16 - }] - -@[simp_denote] -def xori_riscv := - [LV| { - ^entry (%arg: i16): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) - %0 =xori %a, 4 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) - llvm.return %1 :i16 - }] - -def xori_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where - lhs := xori_llvm - rhs := xori_riscv - - -/-- ### ori -/ -@[simp_denote] -def ori_llvm := [LV| { - ^entry (%a: i16): - %0 = llvm.mlir.constant (5) : i16 - %1 = llvm.or %a, %0 : i16 - llvm.return %1 :i16 - }] - -@[simp_denote] -def ori_riscv := - [LV| { - ^entry (%arg: i16): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) - %0 =ori %a, 5 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) - llvm.return %1 :i16 - }] - -def ori_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where - lhs := ori_llvm - rhs := ori_riscv - - -/-- ### andi -/ -@[simp_denote] -def andi_llvm := [LV| { - ^entry (%a: i16): - %0 = llvm.mlir.constant (6) : i16 - %1 = llvm.and %a, %0 : i16 - llvm.return %1 :i16 - }] - -@[simp_denote] -def andi_riscv := - [LV| { - ^entry (%arg: i16): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) - %0 =andi %a, 6 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) - llvm.return %1 :i16 - }] - -def andi_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where - lhs := andi_llvm - rhs := andi_riscv - - -/-- ### slli -/ -@[simp_denote] -def slli_llvm := [LV| { - ^entry (%a: i16): - %0 = llvm.mlir.constant (7) : i16 - %1 = llvm.shl %a, %0 : i16 - llvm.return %1 :i16 - }] - -@[simp_denote] -def slli_riscv := - [LV| { - ^entry (%arg: i16): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) - %0 =slli %a, 7 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) - llvm.return %1 :i16 - }] - -def slli_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where - lhs := slli_llvm - rhs := slli_riscv - - -/-- ### srli -/ -@[simp_denote] -def srli_llvm := [LV| { - ^entry (%a: i16): - %0 = llvm.mlir.constant (6) : i16 - %1 = llvm.lshr %a, %0 : i16 - llvm.return %1 :i16 - }] - -@[simp_denote] -def srli_riscv := - [LV| { - ^entry (%arg: i16): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) - %0 =slli %a, 48 : !i64 - %1 =srli %0, 54 : !i64 - %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i16) - llvm.return %2 :i16 - }] - -def srli_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where - lhs := srli_llvm - rhs := srli_riscv - - -/-- ### srai -/ -@[simp_denote] -def srai_llvm := [LV| { - ^entry (%a: i16): - %0 = llvm.mlir.constant (9) : i16 - %1 = llvm.ashr %a, %0 : i16 - llvm.return %1 :i16 - }] - -@[simp_denote] -def srai_riscv := - [LV| { - ^entry (%arg: i16): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) - %0 =slli %a, 48 : !i64 - %1 =srai %0, 57 : !i64 - %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i16) - llvm.return %2 :i16 - }] - -def srai_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where - lhs := srai_llvm - rhs := srai_riscv - - -/-- ### add -/ -@[simp_denote] -def add_llvm_i16:= [LV| { - ^entry (%a: i16,%b: i16 ): - %0 = llvm.add %a, %b : i16 - llvm.return %0 :i16 - }] - -@[simp_denote] -def add_riscv_i16 := - [LV| { - ^entry (%arg0: i16, %arg1: i16 ): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) - %0 =add %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) - llvm.return %1 :i16 - }] - -def add_i16_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where - lhs := add_llvm_i16 - rhs := add_riscv_i16 - - -/-- ### sub -/ -@[simp_denote] -def sub_llvm_i16:= [LV| { - ^entry (%a: i16,%b: i16 ): - %0 = llvm.sub %a, %b : i16 - llvm.return %0 :i16 - }] - -@[simp_denote] -def sub_riscv_i16 := - [LV| { - ^entry (%arg0: i16, %arg1: i16 ): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) - %0 =sub %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) - llvm.return %1 :i16 - }] - -def sub_i16_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where - lhs := sub_llvm_i16 - rhs := sub_riscv_i16 - correct := by - unfold sub_llvm_i16 sub_riscv_i16 - simp_peephole - simp_riscv - simp_alive_undef - simp_alive_case_bash - simp_alive_split - all_goals simp; bv_decide - - -/-- ### sll -/ -@[simp_denote] -def sll_llvm_i16:= [LV| { - ^entry (%a: i16,%b: i16 ): - %0 = llvm.shl %a, %b : i16 - llvm.return %0 :i16 - }] - -@[simp_denote] -def sll_riscv_i16 := - [LV| { - ^entry (%arg0: i16, %arg1: i16 ): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) - %0 =sll %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) - llvm.return %1 :i16 - }] - -def sll_i16_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where - lhs := sll_llvm_i16 - rhs := sll_riscv_i16 - correct := by - unfold sll_llvm_i16 sll_riscv_i16 - simp_lowering - bv_decide - - -/-- ### slt -/ -@[simp_denote] -def slt_llvm := [LV| { - ^entry (%a: i16, %b: i16 ): - %0 = llvm.icmp.slt %a, %b : i16 - %1 = llvm.zext %0: i1 to i16 - llvm.return %1 :i16 - }] - -@[simp_denote] -def slt_riscv := - [LV| { - ^entry (%arg0: i16, %arg1: i16 ): - %a0 = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) - %a1 = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) - %0 = slli %a1, 48 : !i64 - %1 = slli %a0, 48 : !i64 - %2 = srai %1, 48 : !i64 - %3 = srai %0, 48 : !i64 - %4 = slt %2, %3 : !i64 - %5 = "builtin.unrealized_conversion_cast" (%4) : (!i64) -> (i16) - llvm.return %5 :i16 - }] - -def slt_signext_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where - lhs := slt_llvm - rhs := slt_riscv - - -/-- ### sltu -/ -@[simp_denote] -def sltu_llvm := [LV| { - ^entry (%a: i16, %b: i16 ): - %0 = llvm.icmp.ult %a, %b : i16 - %1 = llvm.zext %0: i1 to i16 - llvm.return %1 :i16 - }] - -@[simp_denote] -def sltu_riscv := - [LV| { - ^entry (%arg0: i16, %arg1: i16): - %a0 = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) - %a1 = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) - %0 = li (149595403036) : !i64 -- random value bc reg can hold anything - %1 = "lui" (%0) {imm = 16 : !i64} : (!i64) -> (!i64) - %2 = "addi" (%1) {imm = -1 : !i64} : (!i64) -> (!i64) - %3 = and %2, %a1 : !i64 - %4 = and %2, %a0 : !i64 - %5 = sltu %4, %3 : !i64 - %6 = "builtin.unrealized_conversion_cast" (%5) : (!i64) -> (i16) - llvm.return %6 :i16 - }] - -def sltu_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where - lhs := sltu_llvm - rhs := sltu_riscv - - -/-- ### xor -/ -@[simp_denote] -def xor_llvm_i16:= [LV| { - ^entry (%a: i16,%b: i16 ): - %0 = llvm.xor %a, %b : i16 - llvm.return %0 :i16 - }] - -@[simp_denote] -def xor_riscv_i16 := - [LV| { - ^entry (%arg0: i16, %arg1: i16 ): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) - %0 = xor %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) - llvm.return %1 :i16 - }] - -def xor_i16_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where - lhs := xor_llvm_i16 - rhs := xor_riscv_i16 - - -/-- ### srl -/ -@[simp_denote] -def srl_llvm_i16 := [LV| { - ^entry (%a: i16, %b: i16 ): - %0 = llvm.lshr %a, %b : i16 - llvm.return %0 :i16 - }] - -@[simp_denote] -def srl_riscv_i16 := - [LV| { - ^entry (%arg0: i16, %arg1: i16): - %a0 = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) - %a1 = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) - %0 = slli %a0, 48 : !i64 - %1 = srli %0, 48 : !i64 - %2 = srl %1, %a1 : !i64 - %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i16) - llvm.return %3 :i16 - }] - -def srl_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where - lhs := srl_llvm_i16 - rhs := srl_riscv_i16 - - -/-- ### sra -/ -@[simp_denote] -def sra_llvm_i16 := [LV| { - ^entry (%a: i16, %b: i16 ): - %0 = llvm.ashr %a, %b : i16 - llvm.return %0 :i16 - }] - -@[simp_denote] -def sra_riscv_i16 := - [LV| { - ^entry (%arg0: i16, %arg1: i16): - %a0 = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) - %a1 = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) - %0 = slli %a0, 48 : !i64 - %1 = srai %0, 48 : !i64 - %2 = sra %1, %a1 : !i64 - %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i16) - llvm.return %3 :i16 - }] - -def sra_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where - lhs := sra_llvm_i16 - rhs := sra_riscv_i16 - - -/-- ### or -/ -@[simp_denote] -def or_llvm_i16:= [LV| { - ^entry (%a: i16,%b: i16 ): - %0 = llvm.or %a, %b : i16 - llvm.return %0 :i16 - }] - -@[simp_denote] -def or_riscv_i16 := - [LV| { - ^entry (%arg0: i16, %arg1: i16 ): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) - %0 = or %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) - llvm.return %1 :i16 - }] - -def or_i16_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where - lhs := or_llvm_i16 - rhs := or_riscv_i16 - - -/-- ### and -/ -@[simp_denote] -def and_llvm_i16:= [LV| { - ^entry (%a: i16,%b: i16 ): - %0 = llvm.and %a, %b : i16 - llvm.return %0 :i16 - }] - -@[simp_denote] -def and_riscv_i16 := - [LV| { - ^entry (%arg0: i16, %arg1: i16 ): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) - %0 = and %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) - llvm.return %1 :i16 - }] - -def and_i16_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where - lhs := and_llvm_i16 - rhs := and_riscv_i16 diff --git a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu32.lean b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu32.lean deleted file mode 100644 index b6cb530bd3..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu32.lean +++ /dev/null @@ -1,591 +0,0 @@ -import SSA.Projects.LLVMRiscV.Pipeline.InstructionLowering - -open LLVMRiscV - -/-! - This file implements the `alu32.ll` test case in the LLVM test suite: - https://github.com/llvm/llvm-project/blob/b424207cdddfa2cbfc9129bbe0a31e47cb04e6dc/llvm/test/CodeGen/RISCV/alu32.ll --/ - -/-- addi -/ -@[simp_denote] -def addi_llvm_i32 := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (1) : i32 - %1 = llvm.add %a, %0 : i32 - llvm.return %1 : i32 - }] - -@[simp_denote] -def addi_riscv_i32 := - [LV| { - ^entry (%arg: i32): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %0 = addiw %a, 1 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) - llvm.return %1 : i32 - }] - -def addi_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := addi_llvm_i32 - rhs := addi_riscv_i32 - - -/-- ### slti -/ -@[simp_denote] -def slti_llvm_i32 := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (2) : i32 - %1 = llvm.icmp.slt %a, %0 : i32 - %2 = llvm.zext %1 : i1 to i32 - llvm.return %2 : i32 - }] - -@[simp_denote] -def slti_riscv_i32 := - [LV| { - ^entry (%arg: i32): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %0 = "sext.w" (%a) : (!i64) -> (!i64) - %1 = slti %0, 2 : !i64 - %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) - llvm.return %2 : i32 - }] - -def slti_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := slti_llvm_i32 - rhs := slti_riscv_i32 - - -/-- ### sltiu -/ -@[simp_denote] -def sltiu_llvm_i32 := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (3) : i32 - %1 = llvm.icmp.ult %a, %0 : i32 - %2 = llvm.zext %1 : i1 to i32 - llvm.return %2 : i32 - }] - -@[simp_denote] -def sltiu_riscv_i32 := - [LV| { - ^entry (%arg: i32): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %0 = "sext.w" (%a) :(!i64) -> (!i64) - %1 = sltiu %0, 3 : !i64 - %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) - llvm.return %2 : i32 - }] - -def sltiu_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := sltiu_llvm_i32 - rhs := sltiu_riscv_i32 - - -/-- ### xori -/ -@[simp_denote] -def xori_llvm_i32 := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (4) : i32 - %1 = llvm.xor %a, %0 : i32 - llvm.return %1 : i32 - }] - -@[simp_denote] -def xori_riscv_i32 := - [LV| { - ^entry (%arg: i32): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %0 = xori %a, 4 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) - llvm.return %1 : i32 - }] - -def xori_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := xori_llvm_i32 - rhs := xori_riscv_i32 - - -/-- ### ori -/ -@[simp_denote] -def ori_llvm_i32 := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (5) : i32 - %1 = llvm.or %a, %0 : i32 - llvm.return %1 : i32 - }] - -@[simp_denote] -def ori_riscv_i32 := - [LV| { - ^entry (%arg: i32): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %0 = ori %a, 5 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) - llvm.return %1 : i32 - }] - -def ori_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := ori_llvm_i32 - rhs := ori_riscv_i32 - - -/-- ### andi -/ -@[simp_denote] -def andi_llvm_i32 := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (6) : i32 - %1 = llvm.and %a, %0 : i32 - llvm.return %1 : i32 - }] - -@[simp_denote] -def andi_riscv_i32 := - [LV| { - ^entry (%arg: i32): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %0 = andi %a, 6 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) - llvm.return %1 : i32 - }] - -def andi_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := andi_llvm_i32 - rhs := andi_riscv_i32 - -/-- ### slli -/ -@[simp_denote] -def slli_llvm_i32 := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (7) : i32 - %1 = llvm.shl %a, %0 : i32 - llvm.return %1 : i32 - }] - -@[simp_denote] -def slli_riscv_i32 := - [LV| { - ^entry (%arg: i32): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %0 = slliw %a, 7 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) - llvm.return %1 : i32 - }] - -def slli_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := slli_llvm_i32 - rhs := slli_riscv_i32 - - -/-- ### srli -/ -@[simp_denote] -def srli_llvm_i32 := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (8) : i32 - %1 = llvm.lshr %a, %0 : i32 - llvm.return %1 : i32 - }] - -@[simp_denote] -def srli_riscv_i32 := - [LV| { - ^entry (%arg: i32): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %0 = srliw %a, 8 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) - llvm.return %1 : i32 - }] - -def srli_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := srli_llvm_i32 - rhs := srli_riscv_i32 - -/-- ### srli_demandedbits -/ -@[simp_denote] -def srli_demandedbits_llvm_i32 := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (3) : i32 - %1 = llvm.lshr %a, %0 : i32 - %2 = llvm.mlir.constant (1) : i32 - %3 = llvm.or %1, %2 : i32 - llvm.return %3 : i32 - }] - -@[simp_denote] -def srli_demandedbits_riscv_i32 := - [LV| { - ^entry (%arg: i32): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %0 = srliw %a, 3 : !i64 - %1 = ori %0, 1 : !i64 - %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) - llvm.return %2 : i32 - }] - -def srli_demandedbits_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := srli_demandedbits_llvm_i32 - rhs := srli_demandedbits_riscv_i32 - -/-- ### srai -/ -@[simp_denote] -def srai_llvm_i32 := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (9) : i32 - %1 = llvm.ashr %a, %0 : i32 - llvm.return %1 : i32 - }] - -@[simp_denote] -def srai_riscv_i32 := - [LV| { - ^entry (%arg: i32): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %0 = sraiw %a, 9 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) - llvm.return %1 : i32 - }] - -def srai_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := srai_llvm_i32 - rhs := srai_riscv_i32 - -/-- ### add -/ -@[simp_denote] -def add_llvm_i32 := [LV| { - ^entry (%a: i32, %b: i32): - %0 = llvm.add %a, %b : i32 - llvm.return %0 : i32 - }] - -@[simp_denote] -def add_riscv_i32 := - [LV| { - ^entry (%arg0: i32, %arg1: i32): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) - %0 = addw %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) - llvm.return %1 : i32 - }] - -def add_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where - lhs := add_llvm_i32 - rhs := add_riscv_i32 - -/-- ### sub -/ -@[simp_denote] -def sub_llvm_i32 := [LV| { - ^entry (%a: i32, %b: i32): - %0 = llvm.sub %a, %b : i32 - llvm.return %0 : i32 - }] - -@[simp_denote] -def sub_riscv_i32 := - [LV| { - ^entry (%arg0: i32, %arg1: i32): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) - %0 = subw %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) - llvm.return %1 : i32 - }] - -def sub_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where - lhs := sub_llvm_i32 - rhs := sub_riscv_i32 - - -/-- ### sub -/ -@[simp_denote] -def sub_negative_constant_lhs_llvm_i32 := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (-2) : i32 - %1 = llvm.sub %0, %a : i32 - llvm.return %1 : i32 - }] - -@[simp_denote] -def sub_negative_constant_lhs_riscv_i32 := - [LV| { - ^entry (%arg: i32): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %a1 = "li" () {imm = -2 : !i64} : (!i64) -> (!i64) - %1 = subw %a1, %a : !i64 - %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) - llvm.return %2 : i32 - }] - -def sub_negative_constant_lhs_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := sub_negative_constant_lhs_llvm_i32 - rhs := sub_negative_constant_lhs_riscv_i32 - -/-- ### sll -/ -@[simp_denote] -def sll_llvm_i32 := [LV| { - ^entry (%a: i32, %b: i32): - %0 = llvm.shl %a, %b : i32 - llvm.return %0 : i32 - }] - -@[simp_denote] -def sll_riscv_i32 := - [LV| { - ^entry (%arg0: i32, %arg1: i32): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) - %0 = sllw %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) - llvm.return %1 : i32 - }] - -def sll_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where - lhs := sll_llvm_i32 - rhs := sll_riscv_i32 - -/-- ### sll_negative_constant_lhs -/ -@[simp_denote] -def sll_negative_constant_lhs_llvm_i32 := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (-1) : i32 - %1 = llvm.shl %0, %a : i32 - llvm.return %1 : i32 - }] - -@[simp_denote] -def sll_negative_constant_lhs_riscv_i32 := - [LV| { - ^entry (%arg: i32): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %0 = "li" () {imm = -1 : !i64} : (!i64) -> (!i64) - %1 = sllw %0, %a : !i64 - %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) - llvm.return %2 : i32 - }] - -def sll_negative_constant_lhs_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := sll_negative_constant_lhs_llvm_i32 - rhs := sll_negative_constant_lhs_riscv_i32 - -/-- ### slt -/ -@[simp_denote] -def slt_llvm_i32 := [LV| { - ^entry (%a: i32, %b: i32): - %0 = llvm.icmp.slt %a, %b : i32 - %1 = llvm.zext %0 : i1 to i32 - llvm.return %1 : i32 - }] - -@[simp_denote] -def slt_riscv_i32 := - [LV| { - ^entry (%arg0: i32, %arg1: i32): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) - %0 = sext.w %a : !i64 - %1 = sext.w %b : !i64 - %2 = slt %0, %1 : !i64 - %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i32) - llvm.return %3 : i32 - }] - -def slt_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where - lhs := slt_llvm_i32 - rhs := slt_riscv_i32 - - -/-- ### sltu -/ -@[simp_denote] -def sltu_llvm_i32 := [LV| { - ^entry (%a: i32, %b: i32): - %0 = llvm.icmp.ult %a, %b : i32 - %1 = llvm.zext %0 : i1 to i32 - llvm.return %1 : i32 - }] - -@[simp_denote] -def sltu_riscv_i32 := - [LV| { - ^entry (%arg0: i32, %arg1: i32): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) - %0 = "sext.w" (%a) : (!i64) -> (!i64) - %1 = "sext.w" (%b) : (!i64) -> (!i64) - %2 = sltu %0, %1 : !i64 - %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i32) - llvm.return %3 : i32 - }] - -def sltu_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where - lhs := sltu_llvm_i32 - rhs := sltu_riscv_i32 - -/-- ### xor -/ -@[simp_denote] -def xor_llvm_i32 := [LV| { - ^entry (%a: i32, %b: i32): - %0 = llvm.xor %a, %b : i32 - llvm.return %0 : i32 - }] - -@[simp_denote] -def xor_riscv_i32 := - [LV| { - ^entry (%arg0: i32, %arg1: i32): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) - %0 = xor %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) - llvm.return %1 : i32 - }] - -def xor_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where - lhs := xor_llvm_i32 - rhs := xor_riscv_i32 - - -/-- ### srl -/ -@[simp_denote] -def srl_llvm_i32 := [LV| { - ^entry (%a: i32, %b: i32): - %0 = llvm.lshr %a, %b : i32 - llvm.return %0 : i32 - }] - -@[simp_denote] -def srl_riscv_i32 := - [LV| { - ^entry (%arg0: i32, %arg1: i32): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) - %0 = srlw %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) - llvm.return %1 : i32 - }] - -def srl_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where - lhs := srl_llvm_i32 - rhs := srl_riscv_i32 - - -/-- ### srl_negative_constant_lhs -/ -@[simp_denote] -def srl_negative_constant_lhs_llvm_i32 := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (-1) : i32 - %1 = llvm.lshr %0, %a : i32 - llvm.return %1 : i32 - }] - -@[simp_denote] -def srl_negative_constant_lhs_riscv_i32 := - [LV| { - ^entry (%arg: i32): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %0 = "li" () {imm = -1 : !i64} : (!i64) -> (!i64) - %1 = srlw %0, %a : !i64 - %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) - llvm.return %2 : i32 - }] - -def srl_negative_constant_lhs_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := srl_negative_constant_lhs_llvm_i32 - rhs := srl_negative_constant_lhs_riscv_i32 - - -/-- ### sra -/ -@[simp_denote] -def sra_llvm_i32 := [LV| { - ^entry (%a: i32, %b: i32): - %0 = llvm.ashr %a, %b : i32 - llvm.return %0 : i32 - }] - -@[simp_denote] -def sra_riscv_i32 := - [LV| { - ^entry (%arg0: i32, %arg1: i32): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) - %0 = sraw %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) - llvm.return %1 : i32 - }] - -def sra_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where - lhs := sra_llvm_i32 - rhs := sra_riscv_i32 - - -/-- ### sra_negative_constant_lhs -/ -@[simp_denote] -def sra_negative_constant_lhs_llvm_i32 := [LV| { - ^entry (%a: i32): - %0 = llvm.mlir.constant (2147483648) : i32 - %1 = llvm.ashr %0, %a : i32 - llvm.return %1 : i32 - }] - -@[simp_denote] -def sra_negative_constant_lhs_riscv_i32 := - [LV| { - ^entry (%arg: i32): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) - %b = li (484394305) : !i64 - %0 = "lui" (%b) {imm = 524288 : !i64} : (!i64) -> (!i64) - %1 = sraw %0, %a : !i64 - %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) - llvm.return %2 : i32 - }] - -def sra_negative_constant_lhs_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where - lhs := sra_negative_constant_lhs_llvm_i32 - rhs := sra_negative_constant_lhs_riscv_i32 - -/-- ### or -/ -@[simp_denote] -def or_llvm_i32 := [LV| { - ^entry (%a: i32, %b: i32): - %0 = llvm.or %a, %b : i32 - llvm.return %0 : i32 - }] - -@[simp_denote] -def or_riscv_i32 := - [LV| { - ^entry (%arg0: i32, %arg1: i32): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) - %0 = or %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) - llvm.return %1 : i32 - }] - -def or_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where - lhs := or_llvm_i32 - rhs := or_riscv_i32 - - -/-- ### and -/ -@[simp_denote] -def and_llvm_i32 := [LV| { - ^entry (%a: i32, %b: i32): - %0 = llvm.and %a, %b : i32 - llvm.return %0 : i32 - }] - -@[simp_denote] -def and_riscv_i32 := - [LV| { - ^entry (%arg0: i32, %arg1: i32): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) - %0 = and %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) - llvm.return %1 : i32 - }] - -def and_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where - lhs := and_llvm_i32 - rhs := and_riscv_i32 diff --git a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu64.lean b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu64.lean deleted file mode 100644 index bb15739af6..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu64.lean +++ /dev/null @@ -1,649 +0,0 @@ -import SSA.Projects.LLVMRiscV.Pipeline.InstructionLowering - -open LLVMRiscV - -/-! - This file implements the `alu64.ll` test case in the LLVM test suite: - https://github.com/llvm/llvm-project/blob/b424207cdddfa2cbfc9129bbe0a31e47cb04e6dc/llvm/test/CodeGen/RISCV/alu64.ll --/ - -/-- ### addi -/ -@[simp_denote] -def addi_llvm_i64 := [LV| { - ^entry (%a: i64): - %0 = llvm.mlir.constant (1) : i64 - %1 = llvm.add %a, %0 : i64 - llvm.return %1 : i64 - }] - -@[simp_denote] -def addi_riscv_i64 := - [LV| { - ^entry (%arg: i64): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64) - %0 = addi %a, 1 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) - llvm.return %1 : i64 - }] - -def addi_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := addi_llvm_i64 - rhs := addi_riscv_i64 - - -/-- ### slti -/ -@[simp_denote] -def slti_llvm_i64 := - [LV| { - ^entry (%a: i64): - %0 = llvm.mlir.constant (2) : i64 - %1 = llvm.icmp.slt %a, %0 : i64 - %2 = llvm.zext %1 : i1 to i64 - llvm.return %2 : i64 - }] - -@[simp_denote] -def slti_riscv_i64 := - [LV| { - ^entry (%arg: i64): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64) - %1 = slti %a, 2 : !i64 - %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i64) - llvm.return %2 : i64 - }] - -def slti_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := slti_llvm_i64 - rhs := slti_riscv_i64 - - -/-- ### sltiu -/ -@[simp_denote] -def sltiu_llvm_i64 := [LV| { - ^entry (%a: i64): - %0 = llvm.mlir.constant (3) : i64 - %1 = llvm.icmp.ult %a, %0 : i64 - %2 = llvm.zext %1 : i1 to i64 - llvm.return %2 : i64 - }] - -@[simp_denote] -def sltiu_riscv_i64 := - [LV| { - ^entry (%arg: i64): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64) - %1 = sltiu %a, 3 : !i64 - %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i64) - llvm.return %2 : i64 - }] - -def sltiu_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := sltiu_llvm_i64 - rhs := sltiu_riscv_i64 - - -/-- ### xori -/ -@[simp_denote] -def xori_llvm_i64 := [LV| { - ^entry (%a: i64): - %0 = llvm.mlir.constant (4) : i64 - %1 = llvm.xor %a, %0 : i64 - llvm.return %1 : i64 - }] - -@[simp_denote] -def xori_riscv_i64 := - [LV| { - ^entry (%arg: i64): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64) - %0 = xori %a, 4 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) - llvm.return %1 : i64 - }] - -def xori_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := xori_llvm_i64 - rhs := xori_riscv_i64 - - -/-- ### ori -/ -@[simp_denote] -def ori_llvm_i64 := [LV| { - ^entry (%a: i64): - %0 = llvm.mlir.constant (5) : i64 - %1 = llvm.or %a, %0 : i64 - llvm.return %1 : i64 - }] - -@[simp_denote] -def ori_riscv_i64 := - [LV| { - ^entry (%arg: i64): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64) - %0 = ori %a, 5 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) - llvm.return %1 : i64 - }] - -def ori_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := ori_llvm_i64 - rhs := ori_riscv_i64 - - -/-- ### andi -/ -@[simp_denote] -def andi_llvm_i64 := [LV| { - ^entry (%a: i64): - %0 = llvm.mlir.constant (6) : i64 - %1 = llvm.and %a, %0 : i64 - llvm.return %1 : i64 - }] - -@[simp_denote] -def andi_riscv_i64 := - [LV| { - ^entry (%arg: i64): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64) - %0 = andi %a, 6 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) - llvm.return %1 : i64 - }] - -def andi_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := andi_llvm_i64 - rhs := andi_riscv_i64 - - -/-- ### slli -/ -@[simp_denote] -def slli_llvm_i64 := [LV| { - ^entry (%a: i64): - %0 = llvm.mlir.constant (7) : i64 - %1 = llvm.shl %a, %0 : i64 - llvm.return %1 : i64 - }] - -@[simp_denote] -def slli_riscv_i64 := - [LV| { - ^entry (%arg: i64): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64) - %0 = slli %a, 7 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) - llvm.return %1 : i64 - }] - -def slli_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := slli_llvm_i64 - rhs := slli_riscv_i64 - - -/-- ### srli -/ -@[simp_denote] -def srli_llvm_i64 := [LV| { - ^entry (%a: i64): - %0 = llvm.mlir.constant (8) : i64 - %1 = llvm.lshr %a, %0 : i64 - llvm.return %1 : i64 - }] - -@[simp_denote] -def srli_riscv_i64 := - [LV| { - ^entry (%arg: i64): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64) - %0 = srli %a, 8 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) - llvm.return %1 : i64 - }] - -def srli_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := srli_llvm_i64 - rhs := srli_riscv_i64 - - -/-- ### srai -/ -@[simp_denote] -def srai_llvm_i64 := [LV| { - ^entry (%a: i64): - %0 = llvm.mlir.constant (9) : i64 - %1 = llvm.ashr %a, %0 : i64 - llvm.return %1 : i64 - }] - -@[simp_denote] -def srai_riscv_i64 := - [LV| { - ^entry (%arg: i64): - %a = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64) - %0 = srai %a, 9 : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) - llvm.return %1 : i64 - }] - -def srai_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := srai_llvm_i64 - rhs := srai_riscv_i64 - - -/-- ### add -/ -@[simp_denote] -def add_llvm_i64 := [LV| { - ^entry (%a: i64, %b: i64): - %0 = llvm.add %a, %b : i64 - llvm.return %0 : i64 - }] - -@[simp_denote] -def add_riscv_i64 := - [LV| { - ^entry (%arg0: i64, %arg1: i64): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i64) -> (!i64) - %0 = add %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) - llvm.return %1 : i64 - }] - -def add_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where - lhs := add_llvm_i64 - rhs := add_riscv_i64 - - -/-- ### sub -/ -@[simp_denote] -def sub_llvm_i64 := [LV| { - ^entry (%a: i64, %b: i64): - %0 = llvm.sub %a, %b : i64 - llvm.return %0 : i64 - }] - -@[simp_denote] -def sub_riscv_i64 := - [LV| { - ^entry (%arg0: i64, %arg1: i64): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i64) -> (!i64) - %0 = sub %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) - llvm.return %1 : i64 - }] - -def sub_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where - lhs := sub_llvm_i64 - rhs := sub_riscv_i64 - -/-- ### sll -/ -@[simp_denote] -def sll_llvm_i64 := [LV| { - ^entry (%a: i64, %b: i64): - %0 = llvm.shl %a, %b : i64 - llvm.return %0 : i64 - }] - -@[simp_denote] -def sll_riscv_i64 := - [LV| { - ^entry (%arg0: i64, %arg1: i64): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i64) -> (!i64) - %0 = sll %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) - llvm.return %1 : i64 - }] - -def sll_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where - lhs := sll_llvm_i64 - rhs := sll_riscv_i64 - -/-- ### slt -/ -@[simp_denote] -def slt_llvm_i64 := [LV| { - ^entry (%a: i64, %b: i64): - %0 = llvm.icmp.slt %a, %b : i64 - %1 = llvm.zext %0 : i1 to i64 - llvm.return %1 : i64 - }] - -@[simp_denote] -def slt_riscv_i64 := - [LV| { - ^entry (%arg0: i64, %arg1: i64): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i64) -> (!i64) - %2 = slt %a, %b : !i64 - %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i64) - llvm.return %3 : i64 - }] - -def slt_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where - lhs := slt_llvm_i64 - rhs := slt_riscv_i64 - - -/-- ### sltu -/ -@[simp_denote] -def sltu_llvm_i64 := [LV| { - ^entry (%a: i64, %b: i64): - %0 = llvm.icmp.ult %a, %b : i64 - %1 = llvm.zext %0 : i1 to i64 - llvm.return %1 : i64 - }] - -@[simp_denote] -def sltu_riscv_i64 := - [LV| { - ^entry (%arg0: i64, %arg1: i64): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i64) -> (!i64) - %2 = sltu %a, %b : !i64 - %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i64) - llvm.return %3 : i64 - }] - -def sltu_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where - lhs := sltu_llvm_i64 - rhs := sltu_riscv_i64 - - -/-- ### xor -/ -@[simp_denote] -def xor_llvm_i64 := [LV| { - ^entry (%a: i64, %b: i64): - %0 = llvm.xor %a, %b : i64 - llvm.return %0 : i64 - }] - -@[simp_denote] -def xor_riscv_i64 := - [LV| { - ^entry (%arg0: i64, %arg1: i64): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i64) -> (!i64) - %0 = xor %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) - llvm.return %1 : i64 - }] - -def xor_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where - lhs := xor_llvm_i64 - rhs := xor_riscv_i64 - - -/-- ### srl -/ -@[simp_denote] -def srl_llvm_i64 := [LV| { - ^entry (%a: i64, %b: i64): - %0 = llvm.lshr %a, %b : i64 - llvm.return %0 : i64 - }] - -@[simp_denote] -def srl_riscv_i64 := - [LV| { - ^entry (%arg0: i64, %arg1: i64): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i64) -> (!i64) - %0 = srl %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) - llvm.return %1 : i64 - }] - -def srl_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where - lhs := srl_llvm_i64 - rhs := srl_riscv_i64 - - -/-- ### sra -/ -@[simp_denote] -def sra_llvm_i64 := [LV| { - ^entry (%a: i64, %b: i64): - %0 = llvm.ashr %a, %b : i64 - llvm.return %0 : i64 - }] - -@[simp_denote] -def sra_riscv_i64 := - [LV| { - ^entry (%arg0: i64, %arg1: i64): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i64) -> (!i64) - %0 = sra %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) - llvm.return %1 : i64 - }] - -def sra_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where - lhs := sra_llvm_i64 - rhs := sra_riscv_i64 - - -/-- ### or -/ -@[simp_denote] -def or_llvm_i32 := [LV| { - ^entry (%a: i32, %b: i32): - %0 = llvm.or %a, %b : i32 - llvm.return %0 : i32 - }] - -@[simp_denote] -def or_riscv_i32 := - [LV| { - ^entry (%arg0: i32, %arg1: i32): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) - %0 = or %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) - llvm.return %1 : i32 - }] - -def or_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where - lhs := or_llvm_i32 - rhs := or_riscv_i32 - - -/-- ### and -/ -@[simp_denote] -def and_llvm_i64 := [LV| { - ^entry (%a: i64, %b: i64): - %0 = llvm.and %a, %b : i64 - llvm.return %0 : i64 - }] - -@[simp_denote] -def and_riscv_i64 := - [LV| { - ^entry (%arg0: i64, %arg1: i64): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!i64) - %b = "builtin.unrealized_conversion_cast" (%arg1) : (i64) -> (!i64) - %0 = and %a, %b : !i64 - %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) - llvm.return %1 : i64 - }] - -def and_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where - lhs := and_llvm_i64 - rhs := and_riscv_i64 - - -/- ### addiw - Can't be implemented because Lean-MLIR does not support the intrinsic as in `i32 signext %a` --/ - -/- ### slliw - Can't be implemented because Lean-MLIR does not support the intrinsic as in `i32 signext %a` --/ - -/- ### srliw - Can't be implemented. - TODO: check why --/ - - -/-- ### sraiw -/ -@[simp_denote] -def sraiw_llvm_i64 := [LV| { - ^entry (%a: i64): - %32 = llvm.mlir.constant (32) : i64 - %41 = llvm.mlir.constant (41) : i64 - %0 = llvm.shl %a, %32 : i64 - %1 = llvm.ashr %0, %41: i64 - llvm.return %1 : i64 - }] - -@[simp_denote] -def sraiw_riscv_i64 := [LV| { - ^entry (%arg: i64): - %0 = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!riscv.reg) - %1 = sraiw %0, 9 : !riscv.reg - %2 = "builtin.unrealized_conversion_cast" (%1) : (!riscv.reg) -> (i64) - llvm.return %2 : i64 - }] - -def sraiw_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := sraiw_llvm_i64 - rhs := sraiw_riscv_i64 - - -/- ### sextw - Can't be implemented. - TODO: check why --/ - -/- ### addw - Can't be implemented. - TODO: check why --/ - -/- ### subw - Can't be implemented. - TODO: check why --/ - -/- ### sllw - Can't be implemented. - TODO: check why --/ - -/- ### srlw - Can't be implemented. - TODO: check why --/ - - -/- ### sraw - Can't be implemented. - TODO: check why --/ - - -/-- ### add_hi_and_lo_negone -/ -@[simp_denote] -def add_hi_and_lo_negone_llvm_i64 := [LV| { - ^entry (%arg: i64): - %1 = llvm.mlir.constant (-1) : i64 - %0 = llvm.add %arg, %1 overflow : i64 - llvm.return %0 : i64 - }] - -@[simp_denote] -def add_hi_and_lo_negone_riscv_i64 := - [LV| { - ^entry (%arg0: i64): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!riscv.reg) - %0 = li (0) : !riscv.reg - %1= li (1) : !riscv.reg - %2 = sub %0, %1 : !riscv.reg -- load -1 into %1 becaue can't encode (-1) for the moment - %3 = add %a, %2 : !riscv.reg - %4 = "builtin.unrealized_conversion_cast" (%3) : (!riscv.reg) -> (i64) - llvm.return %4 : i64 - }] - -def add_hi_and_lo_negone_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := add_hi_and_lo_negone_llvm_i64 - rhs := add_hi_and_lo_negone_riscv_i64 - - -/-- ### add_hi_zero_lo_negone -/ -@[simp_denote] -def add_hi_zero_lo_negone_llvm_i64 := [LV| { - ^entry (%0: i64): - %4294967295 = llvm.mlir.constant (4294967295) : i64 - %1 = llvm.add %0, %4294967295 : i64 - llvm.return %1 : i64 - }] - -@[simp_denote] -def add_hi_zero_lo_negone_riscv_i64 := - [LV| { - ^entry (%arg0: i64): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!riscv.reg) - %0 = li (0) : !riscv.reg - %1= li (1) : !riscv.reg - %2 = sub %0, %1 : !riscv.reg -- load -1 into %1 becaue can't encode (-1) for the moment - %3 = srli %2, 32 : !riscv.reg - %4 = add %a, %3 : !riscv.reg - %5 = "builtin.unrealized_conversion_cast" (%4) : (!riscv.reg) -> (i64) - llvm.return %5 : i64 - }] - -def add_hi_one_lo_negone_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := add_hi_zero_lo_negone_llvm_i64 - rhs :=add_hi_zero_lo_negone_riscv_i64 - -/-- ### add_lo_negone -/ -@[simp_denote] -def add_lo_negone_llvm_i64 := [LV| { - ^entry (%arg: i64): - %4294967297 = llvm.mlir.constant (4294967297) : i64 - %0 = llvm.mlir.constant (0) : i64 - %1 =llvm.sub %0, %4294967297 : i64 - %2 = llvm.add %1, %arg overflow : i64 - llvm.return %2 : i64 - }] - -@[simp_denote] -def add_lo_negone_riscv_i64 := - [LV| { - ^entry (%arg0: i64): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!riscv.reg) - %0 = li (0) : !riscv.reg - %1= li (1) : !riscv.reg - %2 = sub %0, %1 : !riscv.reg -- load -1 into %1 becaue can't encode (-1) for the moment - %3 = slli %2, 32 : !riscv.reg - %4 = add %3, %2 : !riscv.reg - %5 = add %a, %4 : !riscv.reg - %6 = "builtin.unrealized_conversion_cast" (%5) : (!riscv.reg) -> (i64) - llvm.return %6 : i64 - }] - -def add_lo_negone_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := add_lo_negone_llvm_i64 - rhs := add_lo_negone_riscv_i64 - -/-- ### add_hi_one_lo_negone -/ -@[simp_denote] -def add_hi_one_lo_negone_llvm_i64 := [LV| { - ^entry (%arg: i64): - %8589934591 = llvm.mlir.constant (8589934591) : i64 - %1 = llvm.add %arg, %8589934591 overflow : i64 - llvm.return %1 : i64 - }] - -@[simp_denote] -def add_hi_one_lo_negone_riscv_i64 := - [LV| { - ^entry (%arg0: i64): - %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!riscv.reg) - %0 = li (0) : !riscv.reg - %1= li (1) : !riscv.reg - %2 = sub %0, %1 : !riscv.reg -- load -1 into %1 becaue can't encode (-1) for the moment - %3 = srli %2, 31 : !riscv.reg - %4 = add %3, %a : !riscv.reg - %5 = "builtin.unrealized_conversion_cast" (%4) : (!riscv.reg) -> (i64) - llvm.return %5 : i64 - }] - -def add_hi_one_lo_negone_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where - lhs := add_hi_one_lo_negone_llvm_i64 - rhs := add_hi_one_lo_negone_riscv_i64 diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_3.mlir b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_3.mlir deleted file mode 100644 index 448914c3b0..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_3.mlir +++ /dev/null @@ -1,900 +0,0 @@ -module { - func.func @main(%arg0: i64) -> i1 { - %0 = llvm.and %arg0, %arg0 : i64 - %1 = llvm.and %0, %arg0 : i64 - %2 = llvm.trunc %1 : i64 to i1 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32) -> i1 { - %0 = llvm.zext %arg1 : i32 to i64 - %1 = llvm.sdiv %arg0, %0 : i64 - %2 = llvm.icmp "ult" %arg0, %1 : i64 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.ashr %arg0, %arg0 : i64 - %1 = llvm.select %arg1, %0, %arg2 : i1, i64 - %2 = llvm.lshr %0, %1 : i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.or %arg2, %arg2 : i64 - %1 = llvm.or %arg1, %0 : i64 - %2 = llvm.icmp "ugt" %arg0, %1 : i64 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.zext %0 : i1 to i64 - %2 = llvm.trunc %1 : i64 to i1 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.urem %arg0, %arg1 : i64 - %1 = llvm.or %arg1, %arg2 : i64 - %2 = llvm.icmp "ugt" %0, %1 : i64 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.or %arg0, %arg1 : i64 - %1 = llvm.ashr %0, %arg1 : i64 - %2 = llvm.icmp "sle" %0, %1 : i64 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.ashr %arg1, %arg0 : i64 - %1 = llvm.icmp "ne" %arg0, %0 : i64 - %2 = llvm.zext %1 : i1 to i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.udiv %arg0, %arg1 : i64 - %1 = llvm.lshr %arg0, %0 : i64 - %2 = llvm.urem %arg0, %1 : i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.xor %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.icmp "sgt" %arg0, %arg1 : i64 - %1 = llvm.select %0, %arg2, %arg0 : i1, i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.sext %0 : i32 to i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.zext %arg0 : i1 to i64 - %1 = llvm.srem %arg1, %arg2 : i64 - %2 = llvm.icmp "eq" %0, %1 : i64 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.xor %arg0, %arg1 : i64 - %1 = llvm.sdiv %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.zext %0 : i32 to i64 - %2 = llvm.trunc %1 : i64 to i1 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.lshr %arg0, %arg1 : i64 - %1 = llvm.xor %0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.xor %arg0, %arg1 : i64 - %1 = llvm.ashr %0, %arg1 : i64 - %2 = llvm.trunc %1 : i64 to i1 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.srem %arg0, %arg1 : i64 - %1 = llvm.xor %0, %arg2 : i64 - %2 = llvm.icmp "slt" %1, %0 : i64 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1) -> i32 { - %0 = llvm.zext %arg0 : i1 to i64 - %1 = llvm.udiv %0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.udiv %arg0, %arg1 : i64 - %1 = llvm.srem %arg0, %0 : i64 - %2 = llvm.icmp "sgt" %1, %0 : i64 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.zext %0 : i32 to i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.trunc %1 : i64 to i1 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.select %arg0, %arg1, %arg2 : i1, i64 - %1 = llvm.sdiv %0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.xor %arg1, %arg2 : i64 - %1 = llvm.xor %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.or %arg1, %arg1 : i64 - %1 = llvm.udiv %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i1 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.icmp "ult" %arg0, %arg1 : i64 - %1 = llvm.zext %0 : i1 to i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.sext %0 : i32 to i64 - %2 = llvm.trunc %1 : i64 to i1 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.or %arg0, %arg0 : i64 - %1 = llvm.udiv %0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64) -> i32 { - %0 = llvm.xor %arg1, %arg1 : i64 - %1 = llvm.select %arg0, %0, %0 : i1, i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1) -> i32 { - %0 = llvm.zext %arg1 : i1 to i64 - %1 = llvm.xor %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.zext %0 : i32 to i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.zext %0 : i1 to i64 - %2 = llvm.trunc %1 : i64 to i1 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i1) -> i32 { - %0 = llvm.sext %arg2 : i1 to i64 - %1 = llvm.select %arg0, %arg1, %0 : i1, i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.and %arg1, %arg2 : i64 - %1 = llvm.lshr %arg0, %0 : i64 - %2 = llvm.ashr %1, %0 : i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.urem %arg0, %arg0 : i64 - %1 = llvm.lshr %0, %arg1 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.urem %arg0, %arg1 : i64 - %1 = llvm.lshr %0, %0 : i64 - %2 = llvm.and %0, %1 : i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.sext %0 : i32 to i64 - %2 = llvm.sdiv %1, %arg1 : i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.icmp "ugt" %arg0, %arg0 : i64 - %1 = llvm.zext %0 : i1 to i64 - %2 = llvm.udiv %1, %arg1 : i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.select %0, %arg1, %arg2 : i1, i64 - %2 = llvm.trunc %1 : i64 to i1 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.icmp "sge" %arg0, %arg1 : i64 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.trunc %1 : i64 to i1 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.urem %arg0, %arg0 : i64 - %1 = llvm.lshr %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.urem %arg0, %arg0 : i64 - %1 = llvm.urem %0, %arg1 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i64 { - %0 = llvm.urem %arg0, %arg0 : i64 - %1 = llvm.icmp "ne" %arg0, %0 : i64 - %2 = llvm.zext %1 : i1 to i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1) -> i32 { - %0 = llvm.sext %arg1 : i1 to i64 - %1 = llvm.udiv %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.and %arg1, %arg1 : i64 - %1 = llvm.urem %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.udiv %arg0, %arg0 : i64 - %1 = llvm.and %0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.and %arg0, %arg0 : i64 - %1 = llvm.sdiv %0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.urem %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.sext %1 : i32 to i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.ashr %arg0, %arg1 : i64 - %1 = llvm.or %0, %arg2 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { - %0 = llvm.select %arg1, %arg2, %arg0 : i1, i64 - %1 = llvm.and %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.udiv %arg0, %arg0 : i64 - %1 = llvm.xor %0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i32, %arg1: i64) -> i1 { - %0 = llvm.zext %arg0 : i32 to i64 - %1 = llvm.srem %0, %arg1 : i64 - %2 = llvm.trunc %1 : i64 to i1 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32) -> i1 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.sext %arg1 : i32 to i64 - %2 = llvm.icmp "eq" %0, %1 : i64 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { - %0 = llvm.select %arg1, %arg2, %arg2 : i1, i64 - %1 = llvm.udiv %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.icmp "ne" %arg0, %arg1 : i64 - %1 = llvm.or %arg2, %arg1 : i64 - %2 = llvm.select %0, %arg1, %1 : i1, i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.sdiv %arg0, %arg1 : i64 - %1 = llvm.sdiv %0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i64 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.srem %0, %0 : i64 - %2 = llvm.lshr %0, %1 : i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i32, %arg1: i64) -> i32 { - %0 = llvm.sext %arg0 : i32 to i64 - %1 = llvm.or %0, %arg1 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1) -> i64 { - %0 = llvm.xor %arg0, %arg0 : i64 - %1 = llvm.zext %arg1 : i1 to i64 - %2 = llvm.xor %0, %1 : i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.udiv %arg1, %arg2 : i64 - %1 = llvm.or %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1) -> i1 { - %0 = llvm.sext %arg1 : i1 to i64 - %1 = llvm.ashr %0, %0 : i64 - %2 = llvm.icmp "ule" %arg0, %1 : i64 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i1 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.udiv %0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i1 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.urem %arg1, %arg2 : i64 - %1 = llvm.xor %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i32) -> i1 { - %0 = llvm.sext %arg0 : i32 to i64 - %1 = llvm.srem %0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i1 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i32, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.zext %arg0 : i32 to i64 - %1 = llvm.or %arg1, %arg2 : i64 - %2 = llvm.urem %0, %1 : i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.urem %arg0, %arg1 : i64 - %1 = llvm.lshr %0, %arg1 : i64 - %2 = llvm.urem %0, %1 : i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.select %arg1, %arg2, %arg0 : i1, i64 - %1 = llvm.urem %arg0, %0 : i64 - %2 = llvm.xor %arg0, %1 : i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.udiv %arg0, %arg0 : i64 - %1 = llvm.urem %0, %arg0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.trunc %arg1 : i64 to i32 - %1 = llvm.zext %0 : i32 to i64 - %2 = llvm.icmp "eq" %arg0, %1 : i64 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i64 { - %0 = llvm.or %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.sext %1 : i1 to i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.icmp "ult" %arg0, %arg1 : i64 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.icmp "ne" %arg0, %1 : i64 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.zext %0 : i32 to i64 - %2 = llvm.trunc %1 : i64 to i1 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.ashr %0, %arg1 : i64 - %2 = llvm.trunc %1 : i64 to i1 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.udiv %arg0, %arg0 : i64 - %1 = llvm.lshr %0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.udiv %arg1, %arg2 : i64 - %1 = llvm.or %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.srem %arg1, %arg0 : i64 - %1 = llvm.srem %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.ashr %arg0, %arg0 : i64 - %1 = llvm.lshr %arg1, %arg2 : i64 - %2 = llvm.udiv %0, %1 : i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.zext %0 : i32 to i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64) -> i32 { - %0 = llvm.zext %arg0 : i1 to i64 - %1 = llvm.or %0, %arg1 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.xor %arg0, %arg0 : i64 - %1 = llvm.ashr %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.sdiv %arg1, %arg2 : i64 - %1 = llvm.or %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i64 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.zext %1 : i1 to i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1) -> i1 { - %0 = llvm.sext %arg1 : i1 to i64 - %1 = llvm.ashr %arg0, %0 : i64 - %2 = llvm.icmp "sle" %arg0, %1 : i64 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i1 { - %0 = llvm.ashr %arg0, %arg0 : i64 - %1 = llvm.srem %0, %arg0 : i64 - %2 = llvm.trunc %1 : i64 to i1 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.xor %arg1, %arg0 : i64 - %1 = llvm.sdiv %0, %arg2 : i64 - %2 = llvm.icmp "ule" %arg0, %1 : i64 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.sext %0 : i32 to i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.urem %arg1, %arg1 : i64 - %1 = llvm.xor %arg2, %0 : i64 - %2 = llvm.select %arg0, %arg1, %1 : i1, i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1) -> i64 { - %0 = llvm.zext %arg1 : i1 to i64 - %1 = llvm.icmp "sgt" %arg0, %0 : i64 - %2 = llvm.zext %1 : i1 to i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.urem %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.select %1, %0, %arg1 : i1, i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.icmp "sle" %arg0, %arg1 : i64 - %1 = llvm.select %0, %arg2, %arg0 : i1, i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { - %0 = llvm.select %arg1, %arg2, %arg0 : i1, i64 - %1 = llvm.srem %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - return %2 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.srem %arg0, %arg1 : i64 - %1 = llvm.xor %arg0, %0 : i64 - %2 = llvm.icmp "ne" %arg0, %1 : i64 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.and %1, %arg1 : i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1) -> i1 { - %0 = llvm.zext %arg1 : i1 to i64 - %1 = llvm.and %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i1 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i1 { - %0 = llvm.urem %arg0, %arg0 : i64 - %1 = llvm.lshr %arg0, %0 : i64 - %2 = llvm.icmp "sgt" %arg0, %1 : i64 - return %2 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1) -> i64 { - %0 = llvm.sext %arg0 : i1 to i64 - %1 = llvm.and %0, %0 : i64 - %2 = llvm.or %1, %1 : i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i64 { - %0 = llvm.and %arg0, %arg1 : i64 - %1 = llvm.select %arg2, %arg0, %0 : i1, i64 - %2 = llvm.udiv %0, %1 : i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.udiv %arg1, %arg1 : i64 - %1 = llvm.lshr %0, %arg2 : i64 - %2 = llvm.and %arg0, %1 : i64 - return %2 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.sdiv %0, %arg1 : i64 - %2 = llvm.trunc %1 : i64 to i1 - return %2 : i1 - } -} -// ----- diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_4.mlir b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_4.mlir deleted file mode 100644 index fe44514a5b..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_4.mlir +++ /dev/null @@ -1,1000 +0,0 @@ -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.xor %arg0, %arg0 : i64 - %1 = llvm.srem %arg1, %arg1 : i64 - %2 = llvm.urem %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i1 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.sext %0 : i32 to i64 - %2 = llvm.ashr %1, %arg1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.xor %arg0, %arg1 : i64 - %1 = llvm.or %arg2, %0 : i64 - %2 = llvm.sdiv %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i32, %arg1: i64) -> i32 { - %0 = llvm.zext %arg0 : i32 to i64 - %1 = llvm.xor %0, %arg1 : i64 - %2 = llvm.lshr %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.urem %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.sext %1 : i1 to i64 - %3 = llvm.trunc %2 : i64 to i1 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.srem %arg1, %arg1 : i64 - %1 = llvm.select %arg0, %0, %arg2 : i1, i64 - %2 = llvm.xor %1, %arg1 : i64 - %3 = llvm.trunc %2 : i64 to i1 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.and %arg1, %arg2 : i64 - %1 = llvm.xor %0, %arg1 : i64 - %2 = llvm.urem %arg1, %arg1 : i64 - %3 = llvm.select %arg0, %1, %2 : i1, i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.and %arg0, %arg0 : i64 - %1 = llvm.urem %arg0, %arg1 : i64 - %2 = llvm.srem %0, %1 : i64 - %3 = llvm.icmp "sle" %2, %arg1 : i64 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 - %1 = llvm.lshr %arg2, %arg1 : i64 - %2 = llvm.and %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1) -> i32 { - %0 = llvm.zext %arg0 : i1 to i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.sext %1 : i1 to i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { - %0 = llvm.select %arg1, %arg2, %arg2 : i1, i64 - %1 = llvm.xor %0, %arg2 : i64 - %2 = llvm.lshr %arg0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.and %arg1, %arg2 : i64 - %1 = llvm.or %arg0, %0 : i64 - %2 = llvm.lshr %1, %0 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.ashr %arg1, %arg2 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.sext %1 : i1 to i64 - %3 = llvm.or %arg0, %2 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.udiv %arg1, %arg2 : i64 - %1 = llvm.srem %0, %arg1 : i64 - %2 = llvm.xor %0, %1 : i64 - %3 = llvm.srem %arg0, %2 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i32, %arg1: i64) -> i1 { - %0 = llvm.sext %arg0 : i32 to i64 - %1 = llvm.ashr %arg1, %arg1 : i64 - %2 = llvm.urem %arg1, %1 : i64 - %3 = llvm.icmp "uge" %0, %2 : i64 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1) -> i1 { - %0 = llvm.sext %arg0 : i1 to i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.sext %1 : i1 to i64 - %3 = llvm.trunc %2 : i64 to i1 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.xor %arg1, %arg2 : i64 - %2 = llvm.urem %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i1 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.lshr %arg1, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.zext %1 : i32 to i64 - %3 = llvm.icmp "sge" %arg0, %2 : i64 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i32) -> i32 { - %0 = llvm.zext %arg2 : i32 to i64 - %1 = llvm.lshr %arg1, %0 : i64 - %2 = llvm.srem %arg0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.and %arg0, %arg1 : i64 - %1 = llvm.srem %arg0, %0 : i64 - %2 = llvm.lshr %1, %arg2 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i64 { - %0 = llvm.ashr %arg0, %arg0 : i64 - %1 = llvm.urem %arg0, %0 : i64 - %2 = llvm.and %1, %1 : i64 - %3 = llvm.and %0, %2 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.or %arg0, %arg1 : i64 - %1 = llvm.and %0, %arg2 : i64 - %2 = llvm.lshr %arg0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.select %0, %arg0, %arg1 : i1, i64 - %2 = llvm.or %arg2, %arg0 : i64 - %3 = llvm.icmp "ule" %1, %2 : i64 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.lshr %0, %arg1 : i64 - %2 = llvm.trunc %1 : i64 to i1 - %3 = llvm.select %2, %arg2, %arg0 : i1, i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.urem %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.sext %1 : i32 to i64 - %3 = llvm.or %2, %arg0 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.or %arg0, %arg1 : i64 - %1 = llvm.or %arg2, %0 : i64 - %2 = llvm.ashr %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { - %0 = llvm.select %arg1, %arg0, %arg2 : i1, i64 - %1 = llvm.sdiv %arg0, %0 : i64 - %2 = llvm.lshr %1, %0 : i64 - %3 = llvm.icmp "sgt" %arg0, %2 : i64 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i32, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.sext %arg0 : i32 to i64 - %1 = llvm.lshr %arg1, %arg2 : i64 - %2 = llvm.srem %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i32, %arg1: i64) -> i64 { - %0 = llvm.zext %arg0 : i32 to i64 - %1 = llvm.xor %arg1, %0 : i64 - %2 = llvm.icmp "sle" %0, %1 : i64 - %3 = llvm.zext %2 : i1 to i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.udiv %arg0, %arg1 : i64 - %1 = llvm.sdiv %0, %arg2 : i64 - %2 = llvm.urem %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.icmp "ult" %arg0, %arg0 : i64 - %1 = llvm.udiv %arg1, %arg2 : i64 - %2 = llvm.select %0, %1, %arg0 : i1, i64 - %3 = llvm.trunc %2 : i64 to i1 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.ashr %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.sext %1 : i32 to i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i32, %arg1: i64) -> i32 { - %0 = llvm.zext %arg0 : i32 to i64 - %1 = llvm.icmp "sge" %0, %arg1 : i64 - %2 = llvm.zext %1 : i1 to i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.or %arg0, %arg1 : i64 - %1 = llvm.sdiv %arg0, %0 : i64 - %2 = llvm.sdiv %1, %arg2 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.sdiv %arg0, %arg0 : i64 - %1 = llvm.trunc %arg1 : i64 to i1 - %2 = llvm.zext %1 : i1 to i64 - %3 = llvm.srem %0, %2 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i1) -> i1 { - %0 = llvm.sext %arg0 : i1 to i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.sext %1 : i1 to i64 - %3 = llvm.trunc %2 : i64 to i1 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.sdiv %arg0, %arg1 : i64 - %3 = llvm.and %1, %2 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.sdiv %arg1, %arg1 : i64 - %1 = llvm.lshr %arg0, %0 : i64 - %2 = llvm.srem %1, %arg2 : i64 - %3 = llvm.trunc %2 : i64 to i1 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.or %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.zext %1 : i32 to i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.select %arg1, %arg2, %arg2 : i1, i64 - %1 = llvm.udiv %0, %0 : i64 - %2 = llvm.srem %arg0, %1 : i64 - %3 = llvm.sdiv %arg0, %2 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { - %0 = llvm.sdiv %arg0, %arg0 : i64 - %1 = llvm.sdiv %arg0, %arg0 : i64 - %2 = llvm.select %arg1, %arg2, %1 : i1, i64 - %3 = llvm.icmp "ne" %0, %2 : i64 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32) -> i32 { - %0 = llvm.urem %arg0, %arg0 : i64 - %1 = llvm.zext %arg1 : i32 to i64 - %2 = llvm.srem %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1, %arg3: i32) -> i64 { - %0 = llvm.and %arg0, %arg1 : i64 - %1 = llvm.zext %arg3 : i32 to i64 - %2 = llvm.select %arg2, %0, %1 : i1, i64 - %3 = llvm.udiv %0, %2 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i1 { - %0 = llvm.udiv %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.select %1, %0, %arg0 : i1, i64 - %3 = llvm.trunc %2 : i64 to i1 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.select %0, %arg1, %arg2 : i1, i64 - %2 = llvm.ashr %arg2, %arg2 : i64 - %3 = llvm.icmp "ne" %1, %2 : i64 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { - %0 = llvm.zext %arg1 : i1 to i64 - %1 = llvm.srem %arg0, %0 : i64 - %2 = llvm.srem %arg2, %1 : i64 - %3 = llvm.icmp "ule" %1, %2 : i64 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.and %arg0, %arg0 : i64 - %1 = llvm.and %arg0, %arg0 : i64 - %2 = llvm.xor %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.sext %arg1 : i1 to i64 - %1 = llvm.srem %arg2, %arg0 : i64 - %2 = llvm.udiv %0, %1 : i64 - %3 = llvm.udiv %arg0, %2 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.zext %0 : i32 to i64 - %2 = llvm.udiv %1, %arg1 : i64 - %3 = llvm.xor %1, %2 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.or %arg1, %arg1 : i64 - %1 = llvm.sdiv %arg0, %0 : i64 - %2 = llvm.srem %1, %0 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.srem %arg0, %arg1 : i64 - %1 = llvm.trunc %arg2 : i64 to i32 - %2 = llvm.zext %1 : i32 to i64 - %3 = llvm.xor %0, %2 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.udiv %arg0, %arg1 : i64 - %1 = llvm.or %0, %arg0 : i64 - %2 = llvm.udiv %1, %arg2 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i1) -> i32 { - %0 = llvm.lshr %arg1, %arg1 : i64 - %1 = llvm.zext %arg2 : i1 to i64 - %2 = llvm.select %arg0, %0, %1 : i1, i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i64 { - %0 = llvm.sdiv %arg1, %arg0 : i64 - %1 = llvm.zext %arg2 : i1 to i64 - %2 = llvm.urem %0, %1 : i64 - %3 = llvm.ashr %arg0, %2 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i64 { - %0 = llvm.icmp "uge" %arg0, %arg0 : i64 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.lshr %arg1, %arg2 : i64 - %1 = llvm.select %arg0, %arg1, %arg1 : i1, i64 - %2 = llvm.sdiv %1, %1 : i64 - %3 = llvm.select %arg0, %0, %2 : i1, i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.sext %0 : i32 to i64 - %2 = llvm.udiv %1, %arg1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.lshr %1, %arg0 : i64 - %3 = llvm.select %0, %arg0, %2 : i1, i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1) -> i32 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.sext %arg1 : i1 to i64 - %2 = llvm.urem %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.zext %0 : i32 to i64 - %2 = llvm.srem %1, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i1) -> i1 { - %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 - %1 = llvm.sext %arg2 : i1 to i64 - %2 = llvm.urem %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i1 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.sext %0 : i32 to i64 - %2 = llvm.lshr %1, %arg0 : i64 - %3 = llvm.sdiv %2, %1 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64) -> i32 { - %0 = llvm.zext %arg0 : i1 to i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.select %1, %arg1, %0 : i1, i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i64 { - %0 = llvm.udiv %arg0, %arg0 : i64 - %1 = llvm.srem %0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.zext %2 : i32 to i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.select %arg1, %arg2, %arg0 : i1, i64 - %1 = llvm.srem %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i1 - %3 = llvm.select %2, %arg0, %0 : i1, i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.ashr %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.zext %1 : i32 to i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.ashr %arg0, %arg0 : i64 - %1 = llvm.xor %arg1, %arg2 : i64 - %2 = llvm.sdiv %0, %1 : i64 - %3 = llvm.icmp "ule" %2, %arg1 : i64 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.or %arg1, %arg0 : i64 - %1 = llvm.or %0, %arg2 : i64 - %2 = llvm.sdiv %arg0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.or %arg0, %arg0 : i64 - %1 = llvm.srem %arg1, %arg2 : i64 - %2 = llvm.urem %0, %1 : i64 - %3 = llvm.ashr %2, %arg1 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.udiv %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.zext %1 : i1 to i64 - %3 = llvm.urem %2, %arg0 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.icmp "sle" %arg0, %arg0 : i64 - %1 = llvm.select %0, %arg1, %arg2 : i1, i64 - %2 = llvm.urem %arg0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.or %0, %0 : i64 - %2 = llvm.udiv %arg0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.lshr %arg0, %arg1 : i64 - %1 = llvm.urem %arg2, %arg2 : i64 - %2 = llvm.udiv %1, %arg2 : i64 - %3 = llvm.ashr %0, %2 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.udiv %arg0, %arg0 : i64 - %2 = llvm.ashr %arg0, %arg0 : i64 - %3 = llvm.select %0, %1, %2 : i1, i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.ashr %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.zext %1 : i1 to i64 - %3 = llvm.trunc %2 : i64 to i1 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.or %0, %arg0 : i64 - %2 = llvm.lshr %arg0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.xor %arg0, %arg2 : i64 - %1 = llvm.sdiv %arg1, %0 : i64 - %2 = llvm.lshr %arg0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.ashr %arg2, %arg2 : i64 - %1 = llvm.ashr %arg1, %0 : i64 - %2 = llvm.and %arg0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i1 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.urem %arg1, %arg0 : i64 - %2 = llvm.or %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.zext %0 : i32 to i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.zext %2 : i32 to i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i32, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.zext %arg0 : i32 to i64 - %1 = llvm.srem %arg1, %arg2 : i64 - %2 = llvm.srem %1, %0 : i64 - %3 = llvm.srem %0, %2 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.sdiv %1, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.select %arg0, %arg1, %arg2 : i1, i64 - %1 = llvm.udiv %0, %arg1 : i64 - %2 = llvm.udiv %1, %1 : i64 - %3 = llvm.lshr %0, %2 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i32) -> i64 { - %0 = llvm.sext %arg2 : i32 to i64 - %1 = llvm.or %arg1, %0 : i64 - %2 = llvm.urem %1, %0 : i64 - %3 = llvm.xor %arg0, %2 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i32, %arg1: i64) -> i1 { - %0 = llvm.sext %arg0 : i32 to i64 - %1 = llvm.and %0, %arg1 : i64 - %2 = llvm.or %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i1 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.and %arg2, %arg2 : i64 - %1 = llvm.urem %arg1, %0 : i64 - %2 = llvm.select %arg0, %1, %arg1 : i1, i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.select %arg1, %arg2, %arg0 : i1, i64 - %1 = llvm.and %arg0, %arg0 : i64 - %2 = llvm.urem %0, %1 : i64 - %3 = llvm.xor %arg0, %2 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i64 { - %0 = llvm.sext %arg1 : i32 to i64 - %1 = llvm.and %arg2, %0 : i64 - %2 = llvm.udiv %0, %1 : i64 - %3 = llvm.and %arg0, %2 : i64 - return %3 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { - %0 = llvm.udiv %arg0, %arg0 : i64 - %1 = llvm.select %arg1, %arg2, %0 : i1, i64 - %2 = llvm.lshr %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { - %0 = llvm.select %arg1, %arg0, %arg2 : i1, i64 - %1 = llvm.srem %0, %arg2 : i64 - %2 = llvm.srem %1, %1 : i64 - %3 = llvm.icmp "slt" %arg0, %2 : i64 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.lshr %arg1, %arg1 : i64 - %1 = llvm.sdiv %arg0, %0 : i64 - %2 = llvm.sdiv %1, %arg2 : i64 - %3 = llvm.trunc %2 : i64 to i1 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { - %0 = llvm.select %arg1, %arg2, %arg0 : i1, i64 - %1 = llvm.or %arg0, %0 : i64 - %2 = llvm.ashr %1, %1 : i64 - %3 = llvm.trunc %2 : i64 to i1 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.trunc %arg1 : i64 to i32 - %1 = llvm.sext %0 : i32 to i64 - %2 = llvm.ashr %arg0, %1 : i64 - %3 = llvm.icmp "uge" %2, %arg1 : i64 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.lshr %arg0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.urem %arg1, %arg1 : i64 - %1 = llvm.urem %0, %arg2 : i64 - %2 = llvm.ashr %arg0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i1 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.and %arg0, %arg0 : i64 - %1 = llvm.udiv %arg1, %arg1 : i64 - %2 = llvm.and %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.or %arg0, %arg1 : i64 - %1 = llvm.icmp "sgt" %0, %arg0 : i64 - %2 = llvm.zext %1 : i1 to i64 - %3 = llvm.trunc %2 : i64 to i1 - return %3 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.sdiv %arg0, %arg0 : i64 - %1 = llvm.xor %arg1, %0 : i64 - %2 = llvm.urem %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.lshr %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.zext %1 : i32 to i64 - %3 = llvm.trunc %2 : i64 to i32 - return %3 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.and %arg0, %arg1 : i64 - %2 = llvm.sext %0 : i1 to i64 - %3 = llvm.select %0, %1, %2 : i1, i64 - return %3 : i64 - } -} -// ----- diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_5.mlir b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_5.mlir deleted file mode 100644 index 2245149cb7..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_5.mlir +++ /dev/null @@ -1,1100 +0,0 @@ -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1, %arg3: i32) -> i1 { - %0 = llvm.zext %arg2 : i1 to i64 - %1 = llvm.srem %arg1, %0 : i64 - %2 = llvm.xor %arg0, %1 : i64 - %3 = llvm.sext %arg3 : i32 to i64 - %4 = llvm.icmp "sge" %2, %3 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.urem %0, %arg1 : i64 - %2 = llvm.trunc %1 : i64 to i1 - %3 = llvm.zext %2 : i1 to i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 - %1 = llvm.and %0, %arg1 : i64 - %2 = llvm.udiv %arg2, %arg1 : i64 - %3 = llvm.ashr %1, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.icmp "eq" %0, %arg1 : i64 - %2 = llvm.select %1, %arg2, %arg2 : i1, i64 - %3 = llvm.xor %arg0, %2 : i64 - %4 = llvm.srem %3, %arg1 : i64 - return %4 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { - %0 = llvm.and %arg2, %arg0 : i64 - %1 = llvm.ashr %0, %arg0 : i64 - %2 = llvm.select %arg1, %1, %0 : i1, i64 - %3 = llvm.and %arg0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.select %0, %arg0, %arg0 : i1, i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.zext %2 : i32 to i64 - %4 = llvm.icmp "eq" %3, %arg0 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.xor %arg0, %arg0 : i64 - %1 = llvm.sdiv %0, %arg0 : i64 - %2 = llvm.udiv %1, %1 : i64 - %3 = llvm.urem %2, %arg1 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.and %arg0, %arg0 : i64 - %1 = llvm.urem %arg0, %0 : i64 - %2 = llvm.and %arg0, %1 : i64 - %3 = llvm.ashr %arg1, %arg2 : i64 - %4 = llvm.icmp "ugt" %2, %3 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.icmp "ne" %arg0, %arg1 : i64 - %1 = llvm.select %0, %arg0, %arg0 : i1, i64 - %2 = llvm.sdiv %arg0, %1 : i64 - %3 = llvm.udiv %arg0, %arg2 : i64 - %4 = llvm.icmp "ne" %2, %3 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i1) -> i1 { - %0 = llvm.sext %arg1 : i1 to i64 - %1 = llvm.select %arg2, %arg0, %0 : i1, i64 - %2 = llvm.urem %0, %1 : i64 - %3 = llvm.udiv %arg0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i32) -> i1 { - %0 = llvm.sdiv %arg0, %arg0 : i64 - %1 = llvm.sext %arg2 : i32 to i64 - %2 = llvm.and %arg1, %1 : i64 - %3 = llvm.and %0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.trunc %arg2 : i64 to i32 - %1 = llvm.zext %0 : i32 to i64 - %2 = llvm.lshr %arg1, %1 : i64 - %3 = llvm.or %arg0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.select %arg0, %arg1, %arg2 : i1, i64 - %1 = llvm.and %0, %arg2 : i64 - %2 = llvm.sext %arg0 : i1 to i64 - %3 = llvm.udiv %1, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.select %arg1, %arg2, %arg2 : i1, i64 - %1 = llvm.select %arg0, %0, %arg2 : i1, i64 - %2 = llvm.and %arg2, %arg2 : i64 - %3 = llvm.and %1, %2 : i64 - %4 = llvm.udiv %3, %1 : i64 - return %4 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.urem %arg0, %arg1 : i64 - %1 = llvm.sdiv %arg0, %0 : i64 - %2 = llvm.urem %0, %1 : i64 - %3 = llvm.lshr %arg2, %2 : i64 - %4 = llvm.udiv %2, %3 : i64 - return %4 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1) -> i32 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.sdiv %arg0, %0 : i64 - %2 = llvm.select %arg1, %arg0, %arg0 : i1, i64 - %3 = llvm.and %1, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.srem %arg1, %arg2 : i64 - %1 = llvm.udiv %arg0, %0 : i64 - %2 = llvm.sdiv %arg1, %1 : i64 - %3 = llvm.udiv %2, %arg0 : i64 - %4 = llvm.icmp "ule" %1, %3 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.or %arg0, %arg1 : i64 - %1 = llvm.ashr %0, %arg2 : i64 - %2 = llvm.urem %1, %1 : i64 - %3 = llvm.ashr %2, %arg0 : i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.udiv %arg0, %arg0 : i64 - %1 = llvm.urem %0, %arg0 : i64 - %2 = llvm.udiv %1, %arg1 : i64 - %3 = llvm.sdiv %1, %2 : i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.urem %arg0, %arg1 : i64 - %1 = llvm.icmp "sge" %arg1, %arg2 : i64 - %2 = llvm.sext %1 : i1 to i64 - %3 = llvm.sdiv %0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.trunc %arg1 : i64 to i1 - %1 = llvm.select %0, %arg1, %arg2 : i1, i64 - %2 = llvm.and %arg0, %1 : i64 - %3 = llvm.or %arg2, %arg2 : i64 - %4 = llvm.icmp "sge" %2, %3 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i1 { - %0 = llvm.lshr %arg0, %arg1 : i64 - %1 = llvm.sext %arg3 : i1 to i64 - %2 = llvm.or %arg2, %1 : i64 - %3 = llvm.urem %arg0, %2 : i64 - %4 = llvm.icmp "sgt" %0, %3 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.urem %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.sext %1 : i1 to i64 - %3 = llvm.lshr %arg1, %0 : i64 - %4 = llvm.icmp "sle" %2, %3 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.trunc %arg2 : i64 to i32 - %1 = llvm.sext %0 : i32 to i64 - %2 = llvm.ashr %arg1, %1 : i64 - %3 = llvm.srem %arg0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.urem %arg1, %arg0 : i64 - %1 = llvm.srem %0, %arg1 : i64 - %2 = llvm.or %arg0, %1 : i64 - %3 = llvm.xor %arg0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.xor %arg0, %arg1 : i64 - %1 = llvm.urem %arg0, %arg0 : i64 - %2 = llvm.icmp "ule" %0, %1 : i64 - %3 = llvm.sext %2 : i1 to i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { - %0 = llvm.select %arg1, %arg2, %arg0 : i1, i64 - %1 = llvm.and %arg0, %0 : i64 - %2 = llvm.urem %arg0, %1 : i64 - %3 = llvm.and %2, %arg0 : i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i1) -> i32 { - %0 = llvm.sext %arg2 : i1 to i64 - %1 = llvm.srem %0, %arg0 : i64 - %2 = llvm.select %arg1, %0, %1 : i1, i64 - %3 = llvm.srem %arg0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.and %arg0, %arg1 : i64 - %1 = llvm.or %arg0, %0 : i64 - %2 = llvm.urem %arg2, %arg2 : i64 - %3 = llvm.lshr %1, %2 : i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { - %0 = llvm.select %arg1, %arg2, %arg2 : i1, i64 - %1 = llvm.sdiv %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.sext %arg1 : i1 to i64 - %1 = llvm.ashr %arg0, %0 : i64 - %2 = llvm.xor %arg2, %1 : i64 - %3 = llvm.xor %1, %2 : i64 - %4 = llvm.udiv %3, %0 : i64 - return %4 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i32) -> i64 { - %0 = llvm.zext %arg0 : i32 to i64 - %1 = llvm.srem %0, %0 : i64 - %2 = llvm.urem %1, %0 : i64 - %3 = llvm.or %1, %2 : i64 - %4 = llvm.srem %3, %0 : i64 - return %4 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.sdiv %arg0, %arg1 : i64 - %1 = llvm.and %0, %arg0 : i64 - %2 = llvm.ashr %1, %arg2 : i64 - %3 = llvm.trunc %2 : i64 to i32 - %4 = llvm.zext %3 : i32 to i64 - return %4 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.sdiv %arg0, %arg1 : i64 - %1 = llvm.icmp "uge" %arg2, %arg2 : i64 - %2 = llvm.select %1, %0, %0 : i1, i64 - %3 = llvm.lshr %0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.udiv %arg1, %arg0 : i64 - %1 = llvm.udiv %arg0, %0 : i64 - %2 = llvm.xor %1, %0 : i64 - %3 = llvm.lshr %arg0, %0 : i64 - %4 = llvm.icmp "ne" %2, %3 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.icmp "slt" %arg0, %arg0 : i64 - %1 = llvm.zext %0 : i1 to i64 - %2 = llvm.udiv %1, %arg1 : i64 - %3 = llvm.sdiv %arg0, %2 : i64 - %4 = llvm.icmp "eq" %arg0, %3 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i32) -> i1 { - %0 = llvm.zext %arg0 : i1 to i64 - %1 = llvm.lshr %0, %arg1 : i64 - %2 = llvm.zext %arg2 : i32 to i64 - %3 = llvm.and %1, %2 : i64 - %4 = llvm.icmp "slt" %0, %3 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.and %arg0, %arg1 : i64 - %1 = llvm.lshr %0, %arg0 : i64 - %2 = llvm.sdiv %1, %arg2 : i64 - %3 = llvm.or %0, %2 : i64 - %4 = llvm.lshr %3, %arg1 : i64 - return %4 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.ashr %arg0, %arg1 : i64 - %1 = llvm.xor %arg0, %0 : i64 - %2 = llvm.icmp "slt" %1, %arg2 : i64 - %3 = llvm.lshr %0, %arg2 : i64 - %4 = llvm.select %2, %arg0, %3 : i1, i64 - return %4 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.zext %0 : i32 to i64 - %2 = llvm.zext %arg1 : i32 to i64 - %3 = llvm.xor %1, %2 : i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.ashr %arg2, %arg0 : i64 - %1 = llvm.xor %arg1, %0 : i64 - %2 = llvm.udiv %arg0, %1 : i64 - %3 = llvm.lshr %1, %2 : i64 - %4 = llvm.icmp "ne" %2, %3 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.or %arg1, %arg2 : i64 - %1 = llvm.and %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i1 - %3 = llvm.sext %2 : i1 to i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.udiv %arg0, %arg0 : i64 - %1 = llvm.or %arg0, %0 : i64 - %2 = llvm.urem %arg2, %1 : i64 - %3 = llvm.select %arg1, %2, %arg2 : i1, i64 - %4 = llvm.lshr %arg0, %3 : i64 - return %4 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64) -> i32 { - %0 = llvm.or %arg1, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.sext %1 : i32 to i64 - %3 = llvm.select %arg0, %2, %2 : i1, i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { - %0 = llvm.sext %arg1 : i1 to i64 - %1 = llvm.select %arg1, %arg2, %0 : i1, i64 - %2 = llvm.trunc %1 : i64 to i1 - %3 = llvm.select %2, %arg0, %arg0 : i1, i64 - %4 = llvm.icmp "sge" %arg0, %3 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.xor %arg0, %arg0 : i64 - %1 = llvm.sdiv %arg0, %0 : i64 - %2 = llvm.lshr %arg1, %arg2 : i64 - %3 = llvm.and %1, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.urem %arg0, %arg0 : i64 - %1 = llvm.urem %arg1, %0 : i64 - %2 = llvm.urem %1, %0 : i64 - %3 = llvm.udiv %0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1) -> i32 { - %0 = llvm.and %arg0, %arg0 : i64 - %1 = llvm.or %0, %arg0 : i64 - %2 = llvm.select %arg1, %arg0, %1 : i1, i64 - %3 = llvm.and %0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { - %0 = llvm.lshr %arg2, %arg2 : i64 - %1 = llvm.select %arg1, %arg2, %0 : i1, i64 - %2 = llvm.srem %arg0, %1 : i64 - %3 = llvm.or %arg0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i32, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.sext %arg0 : i32 to i64 - %1 = llvm.urem %arg1, %arg2 : i64 - %2 = llvm.xor %0, %1 : i64 - %3 = llvm.and %0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 - %1 = llvm.ashr %arg1, %arg2 : i64 - %2 = llvm.udiv %1, %1 : i64 - %3 = llvm.and %0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.ashr %arg0, %arg0 : i64 - %1 = llvm.ashr %0, %0 : i64 - %2 = llvm.sdiv %arg1, %arg2 : i64 - %3 = llvm.and %1, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.icmp "sgt" %arg0, %arg1 : i64 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.ashr %arg0, %1 : i64 - %3 = llvm.udiv %2, %1 : i64 - %4 = llvm.or %1, %3 : i64 - return %4 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i64 { - %0 = llvm.srem %arg0, %arg1 : i64 - %1 = llvm.sext %arg2 : i1 to i64 - %2 = llvm.and %arg1, %1 : i64 - %3 = llvm.urem %2, %1 : i64 - %4 = llvm.udiv %0, %3 : i64 - return %4 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i1) -> i1 { - %0 = llvm.sext %arg0 : i1 to i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.zext %1 : i32 to i64 - %3 = llvm.xor %0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.udiv %arg0, %arg0 : i64 - %1 = llvm.trunc %arg0 : i64 to i1 - %2 = llvm.zext %1 : i1 to i64 - %3 = llvm.udiv %0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.udiv %0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i1 - %3 = llvm.select %2, %arg1, %arg0 : i1, i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.xor %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.sext %1 : i32 to i64 - %3 = llvm.xor %0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.sdiv %arg0, %arg1 : i64 - %1 = llvm.xor %arg0, %arg1 : i64 - %2 = llvm.urem %1, %arg2 : i64 - %3 = llvm.or %0, %2 : i64 - %4 = llvm.or %3, %arg2 : i64 - return %4 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.ashr %arg0, %arg0 : i64 - %1 = llvm.udiv %arg1, %arg0 : i64 - %2 = llvm.icmp "ult" %0, %1 : i64 - %3 = llvm.zext %2 : i1 to i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.ashr %arg0, %arg1 : i64 - %1 = llvm.or %arg2, %arg0 : i64 - %2 = llvm.srem %arg1, %1 : i64 - %3 = llvm.or %0, %2 : i64 - %4 = llvm.icmp "sge" %3, %1 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.icmp "sle" %arg0, %arg1 : i64 - %1 = llvm.select %0, %arg2, %arg0 : i1, i64 - %2 = llvm.and %arg0, %arg0 : i64 - %3 = llvm.ashr %1, %2 : i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.srem %arg1, %arg0 : i64 - %1 = llvm.ashr %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.zext %2 : i32 to i64 - %4 = llvm.udiv %3, %0 : i64 - return %4 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.and %arg0, %arg0 : i64 - %1 = llvm.udiv %arg1, %arg0 : i64 - %2 = llvm.trunc %1 : i64 to i1 - %3 = llvm.select %2, %arg2, %arg1 : i1, i64 - %4 = llvm.icmp "ult" %0, %3 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32, %arg2: i64, %arg3: i1) -> i1 { - %0 = llvm.sext %arg1 : i32 to i64 - %1 = llvm.lshr %arg0, %0 : i64 - %2 = llvm.srem %1, %arg2 : i64 - %3 = llvm.select %arg3, %arg2, %0 : i1, i64 - %4 = llvm.icmp "ne" %2, %3 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.xor %arg0, %arg1 : i64 - %1 = llvm.sdiv %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.zext %2 : i32 to i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.xor %arg1, %arg2 : i64 - %1 = llvm.xor %arg0, %0 : i64 - %2 = llvm.sdiv %arg2, %1 : i64 - %3 = llvm.and %1, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64) -> i32 { - %0 = llvm.zext %arg0 : i1 to i64 - %1 = llvm.trunc %arg1 : i64 to i1 - %2 = llvm.sext %1 : i1 to i64 - %3 = llvm.ashr %0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.zext %arg0 : i1 to i64 - %1 = llvm.udiv %0, %arg1 : i64 - %2 = llvm.lshr %arg2, %1 : i64 - %3 = llvm.or %1, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.select %0, %arg1, %arg0 : i1, i64 - %2 = llvm.xor %arg0, %1 : i64 - %3 = llvm.xor %arg2, %2 : i64 - %4 = llvm.lshr %2, %3 : i64 - return %4 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.srem %arg0, %arg1 : i64 - %1 = llvm.ashr %arg0, %0 : i64 - %2 = llvm.sdiv %1, %arg1 : i64 - %3 = llvm.or %0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.ashr %arg0, %arg0 : i64 - %1 = llvm.udiv %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32) -> i1 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.urem %0, %0 : i64 - %2 = llvm.zext %arg1 : i32 to i64 - %3 = llvm.urem %1, %2 : i64 - %4 = llvm.icmp "slt" %1, %3 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64) -> i64 { - %0 = llvm.ashr %arg1, %arg1 : i64 - %1 = llvm.and %arg1, %0 : i64 - %2 = llvm.select %arg0, %1, %1 : i1, i64 - %3 = llvm.trunc %2 : i64 to i32 - %4 = llvm.sext %3 : i32 to i64 - return %4 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.xor %arg0, %arg0 : i64 - %1 = llvm.sdiv %0, %arg1 : i64 - %2 = llvm.sdiv %0, %1 : i64 - %3 = llvm.and %1, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.sext %0 : i32 to i64 - %2 = llvm.trunc %1 : i64 to i1 - %3 = llvm.zext %2 : i1 to i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.xor %arg2, %arg1 : i64 - %1 = llvm.icmp "eq" %arg2, %0 : i64 - %2 = llvm.sext %1 : i1 to i64 - %3 = llvm.select %arg0, %arg1, %2 : i1, i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { - %0 = llvm.sext %arg2 : i1 to i64 - %1 = llvm.ashr %arg0, %0 : i64 - %2 = llvm.lshr %arg1, %1 : i64 - %3 = llvm.xor %2, %1 : i64 - %4 = llvm.icmp "ult" %arg0, %3 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.srem %arg1, %arg2 : i64 - %1 = llvm.ashr %arg0, %0 : i64 - %2 = llvm.icmp "ule" %1, %arg2 : i64 - %3 = llvm.zext %2 : i1 to i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.urem %arg0, %arg0 : i64 - %1 = llvm.and %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i1 - %3 = llvm.sext %2 : i1 to i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.or %0, %0 : i64 - %2 = llvm.udiv %1, %arg1 : i64 - %3 = llvm.udiv %2, %arg2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.select %0, %arg1, %arg2 : i1, i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.ashr %arg1, %arg2 : i64 - %1 = llvm.urem %arg1, %0 : i64 - %2 = llvm.ashr %arg1, %0 : i64 - %3 = llvm.select %arg0, %1, %2 : i1, i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { - %0 = llvm.trunc %arg1 : i64 to i1 - %1 = llvm.select %0, %arg2, %arg2 : i1, i64 - %2 = llvm.sext %arg3 : i32 to i64 - %3 = llvm.select %arg0, %1, %2 : i1, i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32, %arg2: i1) -> i32 { - %0 = llvm.sext %arg1 : i32 to i64 - %1 = llvm.udiv %arg0, %0 : i64 - %2 = llvm.sext %arg2 : i1 to i64 - %3 = llvm.xor %1, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.srem %arg0, %arg1 : i64 - %1 = llvm.icmp "ne" %0, %arg2 : i64 - %2 = llvm.zext %1 : i1 to i64 - %3 = llvm.sdiv %2, %0 : i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.srem %arg1, %arg2 : i64 - %1 = llvm.or %arg2, %arg1 : i64 - %2 = llvm.select %arg0, %0, %1 : i1, i64 - %3 = llvm.sdiv %2, %0 : i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i64 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.sext %1 : i32 to i64 - %3 = llvm.trunc %2 : i64 to i32 - %4 = llvm.sext %3 : i32 to i64 - return %4 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.or %arg0, %arg0 : i64 - %1 = llvm.xor %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.icmp "sgt" %arg0, %arg1 : i64 - %1 = llvm.icmp "uge" %arg0, %arg2 : i64 - %2 = llvm.xor %arg0, %arg1 : i64 - %3 = llvm.select %1, %2, %2 : i1, i64 - %4 = llvm.select %0, %3, %3 : i1, i64 - return %4 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1) -> i64 { - %0 = llvm.sext %arg1 : i1 to i64 - %1 = llvm.ashr %0, %arg0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.zext %2 : i32 to i64 - %4 = llvm.sdiv %arg0, %3 : i64 - return %4 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { - %0 = llvm.sext %arg2 : i1 to i64 - %1 = llvm.icmp "ult" %0, %arg1 : i64 - %2 = llvm.zext %1 : i1 to i64 - %3 = llvm.urem %arg1, %2 : i64 - %4 = llvm.icmp "ugt" %arg0, %3 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.and %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.sext %1 : i32 to i64 - %3 = llvm.urem %arg2, %arg1 : i64 - %4 = llvm.xor %2, %3 : i64 - return %4 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.ashr %arg0, %arg1 : i64 - %1 = llvm.sdiv %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { - %0 = llvm.icmp "ule" %arg0, %arg0 : i64 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.select %arg1, %arg2, %arg0 : i1, i64 - %3 = llvm.ashr %1, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - return %4 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.zext %0 : i1 to i64 - %2 = llvm.and %arg0, %arg1 : i64 - %3 = llvm.udiv %1, %2 : i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i1 { - %0 = llvm.xor %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.zext %1 : i1 to i64 - %3 = llvm.sdiv %arg0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.sdiv %arg1, %arg1 : i64 - %1 = llvm.urem %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i1 - %3 = llvm.zext %2 : i1 to i64 - %4 = llvm.trunc %3 : i64 to i1 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { - %0 = llvm.ashr %arg0, %arg0 : i64 - %1 = llvm.select %arg1, %arg2, %arg2 : i1, i64 - %2 = llvm.trunc %1 : i64 to i1 - %3 = llvm.sext %2 : i1 to i64 - %4 = llvm.icmp "ule" %0, %3 : i64 - return %4 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.sext %0 : i32 to i64 - %2 = llvm.or %1, %arg1 : i64 - %3 = llvm.zext %0 : i32 to i64 - %4 = llvm.icmp "ugt" %2, %3 : i64 - return %4 : i1 - } -} -// ----- diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_6.mlir b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_6.mlir deleted file mode 100644 index 12bd88c709..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_6.mlir +++ /dev/null @@ -1,1200 +0,0 @@ -module { - func.func @main(%arg0: i64, %arg1: i1) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.zext %0 : i32 to i64 - %2 = llvm.ashr %1, %arg0 : i64 - %3 = llvm.urem %1, %2 : i64 - %4 = llvm.zext %arg1 : i1 to i64 - %5 = llvm.icmp "ult" %3, %4 : i64 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.ashr %arg1, %arg0 : i64 - %1 = llvm.sdiv %0, %arg2 : i64 - %2 = llvm.sdiv %arg2, %arg1 : i64 - %3 = llvm.sdiv %1, %2 : i64 - %4 = llvm.icmp "slt" %arg0, %3 : i64 - %5 = llvm.sext %4 : i1 to i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32) -> i1 { - %0 = llvm.zext %arg1 : i32 to i64 - %1 = llvm.srem %0, %0 : i64 - %2 = llvm.udiv %1, %0 : i64 - %3 = llvm.ashr %2, %arg0 : i64 - %4 = llvm.or %arg0, %3 : i64 - %5 = llvm.trunc %4 : i64 to i1 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.and %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.sext %1 : i32 to i64 - %3 = llvm.lshr %arg0, %arg1 : i64 - %4 = llvm.srem %2, %3 : i64 - %5 = llvm.udiv %2, %4 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.srem %arg0, %1 : i64 - %3 = llvm.sext %arg1 : i32 to i64 - %4 = llvm.sdiv %2, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 - %1 = llvm.srem %arg2, %0 : i64 - %2 = llvm.urem %1, %arg2 : i64 - %3 = llvm.icmp "ult" %0, %2 : i64 - %4 = llvm.select %3, %1, %0 : i1, i64 - %5 = llvm.trunc %4 : i64 to i1 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.xor %arg0, %arg1 : i64 - %1 = llvm.lshr %arg2, %arg1 : i64 - %2 = llvm.and %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - %4 = llvm.sext %3 : i32 to i64 - %5 = llvm.icmp "sge" %4, %arg1 : i64 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.trunc %arg1 : i64 to i32 - %1 = llvm.zext %0 : i32 to i64 - %2 = llvm.xor %arg1, %1 : i64 - %3 = llvm.lshr %2, %arg1 : i64 - %4 = llvm.lshr %arg0, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 - %1 = llvm.udiv %arg1, %arg2 : i64 - %2 = llvm.sdiv %arg1, %1 : i64 - %3 = llvm.urem %arg2, %2 : i64 - %4 = llvm.lshr %0, %3 : i64 - %5 = llvm.udiv %4, %2 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.and %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.sext %1 : i32 to i64 - %3 = llvm.trunc %2 : i64 to i1 - %4 = llvm.sext %3 : i1 to i64 - %5 = llvm.trunc %4 : i64 to i1 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.udiv %arg0, %arg0 : i64 - %1 = llvm.or %0, %0 : i64 - %2 = llvm.lshr %0, %arg1 : i64 - %3 = llvm.or %2, %0 : i64 - %4 = llvm.ashr %1, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { - %0 = llvm.sdiv %arg2, %arg2 : i64 - %1 = llvm.select %arg1, %0, %0 : i1, i64 - %2 = llvm.ashr %0, %arg0 : i64 - %3 = llvm.xor %1, %2 : i64 - %4 = llvm.xor %arg0, %3 : i64 - %5 = llvm.icmp "sle" %4, %arg0 : i64 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i32 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.ashr %arg1, %arg1 : i64 - %2 = llvm.lshr %0, %1 : i64 - %3 = llvm.select %arg2, %1, %2 : i1, i64 - %4 = llvm.lshr %2, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1) -> i1 { - %0 = llvm.urem %arg0, %arg0 : i64 - %1 = llvm.zext %arg1 : i1 to i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - %4 = llvm.srem %0, %3 : i64 - %5 = llvm.trunc %4 : i64 to i1 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i1 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.zext %1 : i32 to i64 - %3 = llvm.trunc %2 : i64 to i32 - %4 = llvm.zext %3 : i32 to i64 - %5 = llvm.trunc %4 : i64 to i1 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.udiv %arg0, %arg1 : i64 - %1 = llvm.xor %arg0, %arg2 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.zext %2 : i32 to i64 - %4 = llvm.sdiv %0, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.urem %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.zext %1 : i32 to i64 - %3 = llvm.trunc %2 : i64 to i1 - %4 = llvm.sext %3 : i1 to i64 - %5 = llvm.ashr %4, %0 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.srem %arg1, %arg2 : i64 - %1 = llvm.sdiv %0, %arg2 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - %4 = llvm.udiv %3, %0 : i64 - %5 = llvm.select %arg0, %0, %4 : i1, i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i64 { - %0 = llvm.ashr %arg0, %arg1 : i64 - %1 = llvm.srem %0, %arg2 : i64 - %2 = llvm.or %arg1, %arg2 : i64 - %3 = llvm.lshr %arg0, %arg1 : i64 - %4 = llvm.select %arg3, %2, %3 : i1, i64 - %5 = llvm.srem %1, %4 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.sext %0 : i32 to i64 - %2 = llvm.ashr %arg0, %arg2 : i64 - %3 = llvm.sdiv %2, %arg2 : i64 - %4 = llvm.lshr %arg1, %3 : i64 - %5 = llvm.icmp "ugt" %1, %4 : i64 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.udiv %arg0, %0 : i64 - %2 = llvm.trunc %arg1 : i64 to i32 - %3 = llvm.zext %2 : i32 to i64 - %4 = llvm.xor %1, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.sext %1 : i1 to i64 - %3 = llvm.ashr %arg0, %2 : i64 - %4 = llvm.srem %arg0, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i1 { - %0 = llvm.udiv %arg0, %arg0 : i64 - %1 = llvm.lshr %arg0, %0 : i64 - %2 = llvm.lshr %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - %4 = llvm.zext %3 : i32 to i64 - %5 = llvm.trunc %4 : i64 to i1 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i64 { - %0 = llvm.udiv %arg0, %arg1 : i64 - %1 = llvm.zext %arg2 : i1 to i64 - %2 = llvm.or %0, %1 : i64 - %3 = llvm.sdiv %2, %0 : i64 - %4 = llvm.trunc %3 : i64 to i32 - %5 = llvm.zext %4 : i32 to i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.icmp "ugt" %arg0, %arg0 : i64 - %1 = llvm.xor %arg1, %arg2 : i64 - %2 = llvm.lshr %1, %arg1 : i64 - %3 = llvm.select %0, %arg0, %2 : i1, i64 - %4 = llvm.trunc %3 : i64 to i1 - %5 = llvm.select %4, %arg1, %2 : i1, i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i32 { - %0 = llvm.lshr %arg0, %arg1 : i64 - %1 = llvm.select %arg3, %arg2, %arg1 : i1, i64 - %2 = llvm.udiv %arg2, %1 : i64 - %3 = llvm.urem %2, %arg1 : i64 - %4 = llvm.or %0, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1) -> i32 { - %0 = llvm.zext %arg0 : i1 to i64 - %1 = llvm.sdiv %0, %0 : i64 - %2 = llvm.and %1, %0 : i64 - %3 = llvm.xor %1, %2 : i64 - %4 = llvm.urem %0, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.ashr %arg0, %arg2 : i64 - %1 = llvm.srem %arg1, %0 : i64 - %2 = llvm.urem %arg1, %arg0 : i64 - %3 = llvm.icmp "ne" %1, %2 : i64 - %4 = llvm.zext %3 : i1 to i64 - %5 = llvm.icmp "ugt" %arg0, %4 : i64 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.and %arg1, %arg2 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.sext %1 : i1 to i64 - %3 = llvm.sdiv %arg0, %2 : i64 - %4 = llvm.lshr %3, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { - %0 = llvm.select %arg1, %arg0, %arg2 : i1, i64 - %1 = llvm.srem %arg0, %0 : i64 - %2 = llvm.or %1, %0 : i64 - %3 = llvm.trunc %2 : i64 to i1 - %4 = llvm.sext %3 : i1 to i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.select %0, %arg0, %arg1 : i1, i64 - %2 = llvm.lshr %arg0, %arg2 : i64 - %3 = llvm.xor %arg1, %2 : i64 - %4 = llvm.and %1, %3 : i64 - %5 = llvm.ashr %1, %4 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.or %arg0, %arg1 : i64 - %1 = llvm.sdiv %0, %arg1 : i64 - %2 = llvm.and %arg0, %1 : i64 - %3 = llvm.urem %0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i1 - %5 = llvm.select %4, %0, %arg1 : i1, i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.sdiv %arg0, %arg0 : i64 - %1 = llvm.srem %arg0, %0 : i64 - %2 = llvm.and %arg1, %arg2 : i64 - %3 = llvm.icmp "ugt" %1, %2 : i64 - %4 = llvm.zext %3 : i1 to i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.zext %0 : i32 to i64 - %2 = llvm.icmp "sge" %1, %arg1 : i64 - %3 = llvm.zext %2 : i1 to i64 - %4 = llvm.urem %3, %arg1 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { - %0 = llvm.select %arg1, %arg2, %arg2 : i1, i64 - %1 = llvm.lshr %arg0, %0 : i64 - %2 = llvm.sext %arg1 : i1 to i64 - %3 = llvm.and %1, %2 : i64 - %4 = llvm.and %1, %3 : i64 - %5 = llvm.trunc %4 : i64 to i1 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.zext %0 : i32 to i64 - %2 = llvm.sdiv %arg1, %arg0 : i64 - %3 = llvm.or %1, %2 : i64 - %4 = llvm.lshr %3, %arg1 : i64 - %5 = llvm.urem %3, %4 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.and %arg2, %1 : i64 - %3 = llvm.ashr %arg1, %2 : i64 - %4 = llvm.lshr %3, %1 : i64 - %5 = llvm.icmp "ne" %1, %4 : i64 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.urem %arg0, %arg0 : i64 - %1 = llvm.select %arg1, %arg2, %0 : i1, i64 - %2 = llvm.udiv %arg0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i1 - %4 = llvm.or %arg0, %arg2 : i64 - %5 = llvm.select %3, %4, %2 : i1, i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i32 { - %0 = llvm.urem %arg0, %arg1 : i64 - %1 = llvm.or %0, %arg1 : i64 - %2 = llvm.urem %1, %0 : i64 - %3 = llvm.zext %arg2 : i1 to i64 - %4 = llvm.xor %2, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1) -> i64 { - %0 = llvm.zext %arg1 : i1 to i64 - %1 = llvm.lshr %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.zext %2 : i32 to i64 - %4 = llvm.udiv %arg0, %3 : i64 - %5 = llvm.sdiv %3, %4 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.urem %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.sext %1 : i1 to i64 - %3 = llvm.udiv %2, %arg1 : i64 - %4 = llvm.ashr %arg0, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.zext %0 : i32 to i64 - %2 = llvm.trunc %arg0 : i64 to i1 - %3 = llvm.select %2, %1, %arg1 : i1, i64 - %4 = llvm.udiv %1, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.urem %arg0, %arg0 : i64 - %1 = llvm.xor %arg0, %0 : i64 - %2 = llvm.xor %1, %arg1 : i64 - %3 = llvm.ashr %2, %arg1 : i64 - %4 = llvm.udiv %0, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.srem %arg0, %arg1 : i64 - %1 = llvm.ashr %0, %arg2 : i64 - %2 = llvm.ashr %1, %0 : i64 - %3 = llvm.lshr %arg1, %arg0 : i64 - %4 = llvm.udiv %0, %3 : i64 - %5 = llvm.icmp "eq" %2, %4 : i64 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.ashr %arg1, %arg2 : i64 - %1 = llvm.sdiv %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - %4 = llvm.srem %3, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.select %arg1, %arg0, %arg0 : i1, i64 - %2 = llvm.select %0, %1, %1 : i1, i64 - %3 = llvm.urem %arg2, %arg0 : i64 - %4 = llvm.xor %2, %3 : i64 - %5 = llvm.srem %4, %arg0 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.srem %arg1, %arg0 : i64 - %1 = llvm.xor %0, %arg1 : i64 - %2 = llvm.ashr %arg0, %1 : i64 - %3 = llvm.urem %1, %0 : i64 - %4 = llvm.xor %2, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.sext %arg0 : i1 to i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.or %arg1, %arg2 : i64 - %3 = llvm.ashr %2, %0 : i64 - %4 = llvm.select %1, %3, %2 : i1, i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { - %0 = llvm.sdiv %arg0, %arg1 : i64 - %1 = llvm.select %arg2, %arg0, %0 : i1, i64 - %2 = llvm.udiv %0, %1 : i64 - %3 = llvm.srem %arg1, %2 : i64 - %4 = llvm.ashr %1, %3 : i64 - %5 = llvm.icmp "eq" %2, %4 : i64 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { - %0 = llvm.select %arg1, %arg2, %arg2 : i1, i64 - %1 = llvm.sdiv %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - %4 = llvm.srem %3, %0 : i64 - %5 = llvm.trunc %4 : i64 to i1 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.ashr %arg1, %arg2 : i64 - %1 = llvm.urem %arg0, %0 : i64 - %2 = llvm.udiv %arg2, %0 : i64 - %3 = llvm.sdiv %0, %2 : i64 - %4 = llvm.srem %1, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { - %0 = llvm.icmp "sgt" %arg0, %arg1 : i64 - %1 = llvm.sext %arg2 : i1 to i64 - %2 = llvm.select %0, %arg0, %1 : i1, i64 - %3 = llvm.udiv %2, %arg1 : i64 - %4 = llvm.lshr %1, %arg1 : i64 - %5 = llvm.icmp "ne" %3, %4 : i64 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.or %arg0, %arg0 : i64 - %1 = llvm.urem %arg2, %0 : i64 - %2 = llvm.ashr %arg2, %1 : i64 - %3 = llvm.srem %2, %2 : i64 - %4 = llvm.select %arg1, %3, %0 : i1, i64 - %5 = llvm.srem %0, %4 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.or %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.zext %1 : i1 to i64 - %3 = llvm.or %arg1, %0 : i64 - %4 = llvm.or %3, %2 : i64 - %5 = llvm.urem %2, %4 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.sext %0 : i32 to i64 - %2 = llvm.ashr %1, %1 : i64 - %3 = llvm.xor %arg0, %arg0 : i64 - %4 = llvm.and %1, %3 : i64 - %5 = llvm.lshr %2, %4 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.select %arg1, %arg0, %arg2 : i1, i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.zext %1 : i32 to i64 - %3 = llvm.urem %arg0, %2 : i64 - %4 = llvm.srem %arg2, %arg0 : i64 - %5 = llvm.ashr %3, %4 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.lshr %arg2, %arg0 : i64 - %1 = llvm.or %0, %arg0 : i64 - %2 = llvm.lshr %1, %arg0 : i64 - %3 = llvm.udiv %arg1, %2 : i64 - %4 = llvm.or %arg0, %3 : i64 - %5 = llvm.trunc %4 : i64 to i1 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.zext %arg0 : i1 to i64 - %1 = llvm.urem %0, %arg2 : i64 - %2 = llvm.and %arg1, %1 : i64 - %3 = llvm.select %arg0, %2, %0 : i1, i64 - %4 = llvm.xor %2, %3 : i64 - %5 = llvm.icmp "ule" %0, %4 : i64 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.srem %arg1, %arg0 : i64 - %1 = llvm.udiv %0, %arg2 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - %4 = llvm.or %arg0, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { - %0 = llvm.select %arg1, %arg0, %arg0 : i1, i64 - %1 = llvm.lshr %arg0, %0 : i64 - %2 = llvm.sdiv %arg2, %0 : i64 - %3 = llvm.udiv %1, %2 : i64 - %4 = llvm.sdiv %3, %arg2 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.or %arg0, %arg1 : i64 - %1 = llvm.udiv %0, %arg2 : i64 - %2 = llvm.sdiv %arg0, %arg1 : i64 - %3 = llvm.ashr %2, %arg1 : i64 - %4 = llvm.icmp "ult" %1, %3 : i64 - %5 = llvm.select %4, %arg1, %arg0 : i1, i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.lshr %arg2, %arg1 : i64 - %1 = llvm.select %arg0, %arg1, %0 : i1, i64 - %2 = llvm.udiv %arg2, %arg1 : i64 - %3 = llvm.or %1, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - %5 = llvm.zext %4 : i32 to i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.udiv %arg0, %arg2 : i64 - %1 = llvm.srem %arg1, %0 : i64 - %2 = llvm.udiv %arg0, %1 : i64 - %3 = llvm.xor %0, %arg1 : i64 - %4 = llvm.ashr %3, %arg0 : i64 - %5 = llvm.and %2, %4 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.xor %arg1, %arg1 : i64 - %1 = llvm.and %arg2, %0 : i64 - %2 = llvm.icmp "eq" %0, %1 : i64 - %3 = llvm.sext %2 : i1 to i64 - %4 = llvm.or %arg0, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i1) -> i1 { - %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 - %1 = llvm.select %arg2, %arg1, %arg1 : i1, i64 - %2 = llvm.udiv %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - %4 = llvm.zext %3 : i32 to i64 - %5 = llvm.trunc %4 : i64 to i1 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.and %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.sext %1 : i1 to i64 - %3 = llvm.udiv %arg2, %arg2 : i64 - %4 = llvm.udiv %2, %3 : i64 - %5 = llvm.sdiv %arg0, %4 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.zext %0 : i1 to i64 - %2 = llvm.zext %arg1 : i1 to i64 - %3 = llvm.icmp "ule" %1, %2 : i64 - %4 = llvm.select %3, %arg2, %arg0 : i1, i64 - %5 = llvm.trunc %4 : i64 to i1 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.sdiv %arg1, %arg2 : i64 - %1 = llvm.xor %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i1 - %3 = llvm.sext %2 : i1 to i64 - %4 = llvm.lshr %arg2, %1 : i64 - %5 = llvm.icmp "ule" %3, %4 : i64 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.udiv %arg0, %arg0 : i64 - %1 = llvm.xor %0, %0 : i64 - %2 = llvm.and %0, %1 : i64 - %3 = llvm.srem %arg1, %0 : i64 - %4 = llvm.srem %2, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.udiv %arg1, %arg1 : i64 - %1 = llvm.urem %arg0, %0 : i64 - %2 = llvm.icmp "sge" %1, %arg2 : i64 - %3 = llvm.zext %2 : i1 to i64 - %4 = llvm.or %arg0, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.and %arg2, %arg1 : i64 - %1 = llvm.xor %0, %arg2 : i64 - %2 = llvm.select %arg0, %arg1, %1 : i1, i64 - %3 = llvm.xor %arg2, %arg1 : i64 - %4 = llvm.urem %arg2, %3 : i64 - %5 = llvm.or %2, %4 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.ashr %arg1, %arg2 : i64 - %1 = llvm.and %arg0, %0 : i64 - %2 = llvm.lshr %1, %0 : i64 - %3 = llvm.xor %arg2, %arg0 : i64 - %4 = llvm.sdiv %2, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1) -> i1 { - %0 = llvm.zext %arg0 : i1 to i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.zext %1 : i1 to i64 - %3 = llvm.trunc %2 : i64 to i32 - %4 = llvm.sext %3 : i32 to i64 - %5 = llvm.trunc %4 : i64 to i1 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.srem %0, %arg1 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - %4 = llvm.udiv %3, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i1 { - %0 = llvm.zext %arg1 : i32 to i64 - %1 = llvm.sdiv %arg0, %arg2 : i64 - %2 = llvm.urem %0, %1 : i64 - %3 = llvm.urem %arg0, %2 : i64 - %4 = llvm.lshr %3, %0 : i64 - %5 = llvm.trunc %4 : i64 to i1 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1) -> i32 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.zext %arg1 : i1 to i64 - %2 = llvm.sdiv %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - %4 = llvm.sext %3 : i32 to i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i1 { - %0 = llvm.urem %arg2, %arg0 : i64 - %1 = llvm.sext %arg3 : i1 to i64 - %2 = llvm.or %0, %1 : i64 - %3 = llvm.urem %2, %arg2 : i64 - %4 = llvm.lshr %arg1, %3 : i64 - %5 = llvm.icmp "sle" %arg0, %4 : i64 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i32) -> i32 { - %0 = llvm.ashr %arg1, %arg2 : i64 - %1 = llvm.lshr %arg0, %0 : i64 - %2 = llvm.sext %arg3 : i32 to i64 - %3 = llvm.xor %2, %arg0 : i64 - %4 = llvm.or %1, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.sext %0 : i32 to i64 - %2 = llvm.sdiv %1, %1 : i64 - %3 = llvm.udiv %arg1, %arg1 : i64 - %4 = llvm.xor %3, %arg2 : i64 - %5 = llvm.icmp "ult" %2, %4 : i64 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.xor %arg0, %arg1 : i64 - %1 = llvm.or %0, %arg2 : i64 - %2 = llvm.udiv %arg2, %arg2 : i64 - %3 = llvm.urem %1, %2 : i64 - %4 = llvm.or %3, %0 : i64 - %5 = llvm.trunc %4 : i64 to i1 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.or %arg1, %arg2 : i64 - %1 = llvm.srem %arg0, %0 : i64 - %2 = llvm.urem %arg1, %arg2 : i64 - %3 = llvm.udiv %2, %0 : i64 - %4 = llvm.ashr %1, %3 : i64 - %5 = llvm.trunc %4 : i64 to i1 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.zext %arg0 : i1 to i64 - %1 = llvm.udiv %0, %arg1 : i64 - %2 = llvm.select %arg0, %arg2, %arg2 : i1, i64 - %3 = llvm.or %1, %2 : i64 - %4 = llvm.urem %0, %3 : i64 - %5 = llvm.icmp "uge" %3, %4 : i64 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.sdiv %arg0, %arg1 : i64 - %1 = llvm.and %arg2, %arg0 : i64 - %2 = llvm.udiv %1, %1 : i64 - %3 = llvm.trunc %2 : i64 to i1 - %4 = llvm.sext %3 : i1 to i64 - %5 = llvm.udiv %0, %4 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.udiv %arg0, %arg1 : i64 - %1 = llvm.srem %arg2, %arg0 : i64 - %2 = llvm.srem %0, %1 : i64 - %3 = llvm.urem %arg0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - %5 = llvm.sext %4 : i32 to i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.urem %arg1, %arg0 : i64 - %1 = llvm.xor %arg2, %0 : i64 - %2 = llvm.or %0, %1 : i64 - %3 = llvm.xor %arg0, %2 : i64 - %4 = llvm.or %3, %1 : i64 - %5 = llvm.lshr %3, %4 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i32 { - %0 = llvm.ashr %arg0, %arg1 : i64 - %1 = llvm.select %arg2, %arg0, %0 : i1, i64 - %2 = llvm.icmp "sge" %0, %1 : i64 - %3 = llvm.sext %2 : i1 to i64 - %4 = llvm.srem %3, %1 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.ashr %arg0, %arg0 : i64 - %1 = llvm.lshr %0, %arg1 : i64 - %2 = llvm.udiv %arg2, %0 : i64 - %3 = llvm.trunc %2 : i64 to i1 - %4 = llvm.sext %3 : i1 to i64 - %5 = llvm.lshr %1, %4 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.icmp "sge" %arg0, %arg0 : i64 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.udiv %1, %arg1 : i64 - %3 = llvm.icmp "sge" %1, %2 : i64 - %4 = llvm.sext %3 : i1 to i64 - %5 = llvm.icmp "uge" %4, %arg2 : i64 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.srem %arg0, %arg1 : i64 - %1 = llvm.xor %0, %arg1 : i64 - %2 = llvm.xor %1, %0 : i64 - %3 = llvm.and %2, %arg2 : i64 - %4 = llvm.ashr %1, %3 : i64 - %5 = llvm.and %4, %1 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.sdiv %arg0, %arg1 : i64 - %1 = llvm.trunc %arg1 : i64 to i32 - %2 = llvm.zext %1 : i32 to i64 - %3 = llvm.sdiv %arg1, %2 : i64 - %4 = llvm.or %0, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i64 { - %0 = llvm.udiv %arg0, %arg1 : i64 - %1 = llvm.lshr %arg2, %arg1 : i64 - %2 = llvm.lshr %arg1, %1 : i64 - %3 = llvm.select %arg3, %arg2, %arg0 : i1, i64 - %4 = llvm.or %2, %3 : i64 - %5 = llvm.or %0, %4 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.xor %arg0, %arg1 : i64 - %1 = llvm.icmp "sge" %arg0, %0 : i64 - %2 = llvm.zext %1 : i1 to i64 - %3 = llvm.urem %2, %0 : i64 - %4 = llvm.udiv %arg2, %3 : i64 - %5 = llvm.icmp "eq" %0, %4 : i64 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.udiv %arg0, %arg1 : i64 - %1 = llvm.sdiv %arg1, %arg2 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - %4 = llvm.xor %0, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i32) -> i1 { - %0 = llvm.udiv %arg0, %arg1 : i64 - %1 = llvm.zext %arg2 : i32 to i64 - %2 = llvm.lshr %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - %4 = llvm.sext %3 : i32 to i64 - %5 = llvm.trunc %4 : i64 to i1 - return %5 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.icmp "eq" %arg1, %arg2 : i64 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.icmp "sgt" %arg0, %1 : i64 - %3 = llvm.zext %2 : i1 to i64 - %4 = llvm.lshr %3, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.trunc %arg2 : i64 to i32 - %1 = llvm.zext %0 : i32 to i64 - %2 = llvm.udiv %arg1, %1 : i64 - %3 = llvm.sdiv %2, %arg2 : i64 - %4 = llvm.and %arg0, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - return %5 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64, %arg3: i32) -> i64 { - %0 = llvm.sext %arg3 : i32 to i64 - %1 = llvm.select %arg1, %arg2, %0 : i1, i64 - %2 = llvm.icmp "ugt" %arg0, %1 : i64 - %3 = llvm.zext %2 : i1 to i64 - %4 = llvm.xor %arg0, %3 : i64 - %5 = llvm.udiv %4, %0 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i32) -> i64 { - %0 = llvm.ashr %arg0, %arg1 : i64 - %1 = llvm.sext %arg2 : i32 to i64 - %2 = llvm.or %1, %1 : i64 - %3 = llvm.xor %1, %2 : i64 - %4 = llvm.srem %3, %3 : i64 - %5 = llvm.xor %0, %4 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.sext %0 : i32 to i64 - %2 = llvm.ashr %arg1, %arg0 : i64 - %3 = llvm.trunc %2 : i64 to i1 - %4 = llvm.select %3, %arg0, %arg2 : i1, i64 - %5 = llvm.lshr %1, %4 : i64 - return %5 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.ashr %arg0, %arg0 : i64 - %1 = llvm.or %0, %arg1 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - %4 = llvm.xor %3, %1 : i64 - %5 = llvm.icmp "ugt" %0, %4 : i64 - return %5 : i1 - } -} -// ----- diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_7.mlir b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_7.mlir deleted file mode 100644 index d671e6d157..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_7.mlir +++ /dev/null @@ -1,1300 +0,0 @@ -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.and %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.zext %1 : i1 to i64 - %3 = llvm.urem %2, %arg1 : i64 - %4 = llvm.icmp "sgt" %3, %arg1 : i64 - %5 = llvm.zext %4 : i1 to i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i32) -> i32 { - %0 = llvm.xor %arg0, %arg1 : i64 - %1 = llvm.icmp "uge" %arg1, %arg2 : i64 - %2 = llvm.sext %arg3 : i32 to i64 - %3 = llvm.select %1, %0, %2 : i1, i64 - %4 = llvm.and %0, %3 : i64 - %5 = llvm.xor %arg0, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.lshr %arg1, %arg1 : i64 - %1 = llvm.udiv %arg0, %0 : i64 - %2 = llvm.srem %0, %arg2 : i64 - %3 = llvm.sdiv %1, %2 : i64 - %4 = llvm.lshr %3, %arg1 : i64 - %5 = llvm.trunc %4 : i64 to i32 - %6 = llvm.zext %5 : i32 to i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1) -> i32 { - %0 = llvm.sext %arg1 : i1 to i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.zext %1 : i1 to i64 - %3 = llvm.urem %arg0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - %5 = llvm.sext %4 : i32 to i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.urem %0, %arg1 : i64 - %2 = llvm.srem %arg0, %1 : i64 - %3 = llvm.urem %2, %arg2 : i64 - %4 = llvm.icmp "sgt" %arg0, %3 : i64 - %5 = llvm.select %4, %0, %3 : i1, i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.srem %arg1, %arg2 : i64 - %1 = llvm.srem %arg0, %0 : i64 - %2 = llvm.icmp "ugt" %arg0, %1 : i64 - %3 = llvm.select %2, %0, %arg0 : i1, i64 - %4 = llvm.sdiv %arg2, %arg0 : i64 - %5 = llvm.select %2, %3, %4 : i1, i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.udiv %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.lshr %arg2, %0 : i64 - %3 = llvm.select %1, %arg2, %2 : i1, i64 - %4 = llvm.sdiv %arg0, %2 : i64 - %5 = llvm.select %arg1, %3, %4 : i1, i64 - %6 = llvm.sdiv %arg0, %5 : i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.urem %arg0, %arg0 : i64 - %2 = llvm.sdiv %arg0, %1 : i64 - %3 = llvm.select %0, %2, %2 : i1, i64 - %4 = llvm.trunc %3 : i64 to i1 - %5 = llvm.select %4, %arg1, %arg2 : i1, i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { - %0 = llvm.sext %arg0 : i1 to i64 - %1 = llvm.udiv %arg1, %arg2 : i64 - %2 = llvm.xor %0, %1 : i64 - %3 = llvm.and %2, %2 : i64 - %4 = llvm.sext %arg3 : i32 to i64 - %5 = llvm.udiv %3, %4 : i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.icmp "sle" %arg0, %arg1 : i64 - %1 = llvm.zext %0 : i1 to i64 - %2 = llvm.trunc %1 : i64 to i1 - %3 = llvm.udiv %arg1, %1 : i64 - %4 = llvm.select %2, %3, %arg2 : i1, i64 - %5 = llvm.udiv %arg0, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i1 { - %0 = llvm.sext %arg1 : i32 to i64 - %1 = llvm.icmp "uge" %0, %arg2 : i64 - %2 = llvm.select %1, %0, %0 : i1, i64 - %3 = llvm.urem %2, %2 : i64 - %4 = llvm.srem %arg0, %3 : i64 - %5 = llvm.ashr %arg0, %4 : i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.zext %0 : i1 to i64 - %2 = llvm.udiv %arg0, %1 : i64 - %3 = llvm.urem %1, %arg1 : i64 - %4 = llvm.urem %2, %3 : i64 - %5 = llvm.sdiv %1, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.urem %arg1, %arg1 : i64 - %2 = llvm.select %arg2, %1, %1 : i1, i64 - %3 = llvm.select %0, %arg1, %2 : i1, i64 - %4 = llvm.trunc %3 : i64 to i1 - %5 = llvm.zext %4 : i1 to i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.icmp "ugt" %arg1, %arg1 : i64 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.icmp "ne" %arg0, %1 : i64 - %3 = llvm.srem %arg1, %arg2 : i64 - %4 = llvm.select %2, %arg1, %3 : i1, i64 - %5 = llvm.urem %4, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.xor %arg0, %arg0 : i64 - %1 = llvm.lshr %arg0, %0 : i64 - %2 = llvm.xor %1, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - %4 = llvm.sext %3 : i32 to i64 - %5 = llvm.srem %4, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.ashr %arg1, %arg2 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.sext %1 : i32 to i64 - %3 = llvm.zext %1 : i32 to i64 - %4 = llvm.srem %3, %arg1 : i64 - %5 = llvm.ashr %2, %4 : i64 - %6 = llvm.urem %arg0, %5 : i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i32 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.sext %arg1 : i32 to i64 - %2 = llvm.or %1, %arg0 : i64 - %3 = llvm.urem %0, %2 : i64 - %4 = llvm.udiv %arg2, %0 : i64 - %5 = llvm.srem %3, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i32) -> i32 { - %0 = llvm.srem %arg0, %arg1 : i64 - %1 = llvm.zext %arg2 : i32 to i64 - %2 = llvm.ashr %0, %1 : i64 - %3 = llvm.trunc %arg0 : i64 to i32 - %4 = llvm.zext %3 : i32 to i64 - %5 = llvm.urem %2, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.sext %0 : i32 to i64 - %2 = llvm.sdiv %1, %1 : i64 - %3 = llvm.sdiv %2, %arg1 : i64 - %4 = llvm.and %arg0, %3 : i64 - %5 = llvm.lshr %arg0, %4 : i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64) -> i32 { - %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 - %1 = llvm.xor %0, %0 : i64 - %2 = llvm.urem %1, %1 : i64 - %3 = llvm.icmp "sgt" %1, %2 : i64 - %4 = llvm.sdiv %0, %0 : i64 - %5 = llvm.select %3, %4, %4 : i1, i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.udiv %arg0, %arg1 : i64 - %1 = llvm.icmp "ule" %arg1, %0 : i64 - %2 = llvm.select %1, %arg0, %arg2 : i1, i64 - %3 = llvm.trunc %2 : i64 to i1 - %4 = llvm.sext %3 : i1 to i64 - %5 = llvm.urem %4, %arg0 : i64 - %6 = llvm.icmp "ugt" %0, %5 : i64 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.xor %arg0, %arg1 : i64 - %1 = llvm.lshr %0, %arg1 : i64 - %2 = llvm.ashr %0, %1 : i64 - %3 = llvm.and %arg0, %arg2 : i64 - %4 = llvm.lshr %3, %arg2 : i64 - %5 = llvm.and %2, %4 : i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.and %arg2, %0 : i64 - %2 = llvm.icmp "ule" %arg1, %1 : i64 - %3 = llvm.zext %2 : i1 to i64 - %4 = llvm.xor %0, %3 : i64 - %5 = llvm.sdiv %arg0, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.zext %2 : i32 to i64 - %4 = llvm.xor %3, %arg1 : i64 - %5 = llvm.trunc %4 : i64 to i1 - %6 = llvm.zext %5 : i1 to i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.sext %arg1 : i1 to i64 - %1 = llvm.udiv %arg0, %0 : i64 - %2 = llvm.icmp "uge" %arg2, %1 : i64 - %3 = llvm.ashr %arg2, %1 : i64 - %4 = llvm.xor %arg2, %3 : i64 - %5 = llvm.select %2, %3, %4 : i1, i64 - %6 = llvm.ashr %1, %5 : i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.icmp "uge" %arg1, %arg0 : i64 - %1 = llvm.zext %0 : i1 to i64 - %2 = llvm.udiv %arg0, %1 : i64 - %3 = llvm.lshr %arg2, %arg0 : i64 - %4 = llvm.ashr %3, %arg2 : i64 - %5 = llvm.xor %2, %4 : i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { - %0 = llvm.select %arg2, %arg1, %arg1 : i1, i64 - %1 = llvm.lshr %arg1, %0 : i64 - %2 = llvm.and %0, %arg0 : i64 - %3 = llvm.srem %0, %2 : i64 - %4 = llvm.sdiv %1, %3 : i64 - %5 = llvm.ashr %arg0, %4 : i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.srem %arg0, %arg1 : i64 - %1 = llvm.icmp "sgt" %arg0, %0 : i64 - %2 = llvm.and %arg2, %arg1 : i64 - %3 = llvm.ashr %0, %0 : i64 - %4 = llvm.select %1, %2, %3 : i1, i64 - %5 = llvm.srem %arg0, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { - %0 = llvm.udiv %arg0, %arg0 : i64 - %1 = llvm.or %0, %arg0 : i64 - %2 = llvm.select %arg1, %arg2, %1 : i1, i64 - %3 = llvm.xor %1, %2 : i64 - %4 = llvm.sdiv %0, %3 : i64 - %5 = llvm.or %4, %3 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.urem %arg2, %arg0 : i64 - %1 = llvm.srem %arg2, %0 : i64 - %2 = llvm.trunc %1 : i64 to i1 - %3 = llvm.zext %2 : i1 to i64 - %4 = llvm.srem %arg2, %3 : i64 - %5 = llvm.lshr %arg1, %4 : i64 - %6 = llvm.icmp "ugt" %arg0, %5 : i64 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { - %0 = llvm.srem %arg0, %arg1 : i64 - %1 = llvm.icmp "ne" %arg2, %arg1 : i64 - %2 = llvm.zext %arg3 : i32 to i64 - %3 = llvm.srem %arg0, %arg0 : i64 - %4 = llvm.urem %3, %arg2 : i64 - %5 = llvm.select %1, %2, %4 : i1, i64 - %6 = llvm.icmp "ule" %0, %5 : i64 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.or %arg0, %arg1 : i64 - %1 = llvm.trunc %arg2 : i64 to i32 - %2 = llvm.sext %1 : i32 to i64 - %3 = llvm.xor %2, %0 : i64 - %4 = llvm.lshr %3, %arg2 : i64 - %5 = llvm.udiv %0, %4 : i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.srem %arg1, %arg0 : i64 - %1 = llvm.xor %0, %arg2 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - %4 = llvm.icmp "ne" %arg0, %3 : i64 - %5 = llvm.zext %4 : i1 to i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i32) -> i64 { - %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 - %1 = llvm.and %0, %arg1 : i64 - %2 = llvm.sext %arg2 : i32 to i64 - %3 = llvm.icmp "ne" %1, %2 : i64 - %4 = llvm.sext %3 : i1 to i64 - %5 = llvm.trunc %4 : i64 to i1 - %6 = llvm.zext %5 : i1 to i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.ashr %arg1, %arg2 : i64 - %1 = llvm.or %arg0, %0 : i64 - %2 = llvm.srem %1, %1 : i64 - %3 = llvm.trunc %2 : i64 to i1 - %4 = llvm.or %0, %0 : i64 - %5 = llvm.select %3, %4, %arg0 : i1, i64 - %6 = llvm.srem %5, %arg1 : i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.lshr %arg0, %arg1 : i64 - %1 = llvm.ashr %arg1, %0 : i64 - %2 = llvm.xor %1, %0 : i64 - %3 = llvm.icmp "ult" %arg0, %2 : i64 - %4 = llvm.zext %3 : i1 to i64 - %5 = llvm.and %arg0, %4 : i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.and %arg1, %arg1 : i64 - %1 = llvm.or %arg0, %0 : i64 - %2 = llvm.icmp "ult" %arg1, %1 : i64 - %3 = llvm.select %2, %arg2, %0 : i1, i64 - %4 = llvm.or %arg0, %3 : i64 - %5 = llvm.xor %4, %3 : i64 - %6 = llvm.icmp "slt" %1, %5 : i64 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i32 { - %0 = llvm.urem %arg1, %arg2 : i64 - %1 = llvm.and %arg0, %0 : i64 - %2 = llvm.zext %arg3 : i1 to i64 - %3 = llvm.srem %2, %0 : i64 - %4 = llvm.srem %arg0, %3 : i64 - %5 = llvm.or %1, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.or %arg0, %arg1 : i64 - %1 = llvm.lshr %0, %arg2 : i64 - %2 = llvm.urem %1, %1 : i64 - %3 = llvm.and %2, %2 : i64 - %4 = llvm.urem %arg1, %3 : i64 - %5 = llvm.or %arg0, %4 : i64 - %6 = llvm.icmp "ne" %1, %5 : i64 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.and %arg0, %arg0 : i64 - %1 = llvm.xor %arg1, %arg2 : i64 - %2 = llvm.and %0, %1 : i64 - %3 = llvm.ashr %1, %arg1 : i64 - %4 = llvm.lshr %2, %3 : i64 - %5 = llvm.icmp "sgt" %0, %4 : i64 - %6 = llvm.zext %5 : i1 to i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i32) -> i32 { - %0 = llvm.ashr %arg0, %arg1 : i64 - %1 = llvm.zext %arg2 : i32 to i64 - %2 = llvm.urem %arg1, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - %4 = llvm.sext %3 : i32 to i64 - %5 = llvm.urem %0, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.icmp "uge" %arg0, %arg1 : i64 - %1 = llvm.select %0, %arg2, %arg0 : i1, i64 - %2 = llvm.urem %arg1, %arg1 : i64 - %3 = llvm.icmp "ugt" %1, %2 : i64 - %4 = llvm.select %3, %arg2, %1 : i1, i64 - %5 = llvm.select %3, %2, %4 : i1, i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.and %arg0, %arg1 : i64 - %1 = llvm.srem %0, %arg2 : i64 - %2 = llvm.and %arg1, %0 : i64 - %3 = llvm.trunc %2 : i64 to i32 - %4 = llvm.zext %3 : i32 to i64 - %5 = llvm.srem %1, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64, %arg3: i32) -> i32 { - %0 = llvm.select %arg0, %arg1, %arg2 : i1, i64 - %1 = llvm.zext %arg3 : i32 to i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - %4 = llvm.lshr %0, %3 : i64 - %5 = llvm.lshr %4, %arg1 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i32 { - %0 = llvm.xor %arg0, %arg1 : i64 - %1 = llvm.select %arg2, %arg1, %arg1 : i1, i64 - %2 = llvm.xor %arg0, %1 : i64 - %3 = llvm.urem %0, %2 : i64 - %4 = llvm.ashr %3, %3 : i64 - %5 = llvm.xor %4, %2 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.udiv %arg1, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.sext %1 : i32 to i64 - %3 = llvm.urem %2, %arg1 : i64 - %4 = llvm.and %3, %arg2 : i64 - %5 = llvm.xor %arg0, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.and %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.sext %1 : i1 to i64 - %3 = llvm.select %1, %arg2, %0 : i1, i64 - %4 = llvm.xor %arg2, %3 : i64 - %5 = llvm.udiv %2, %4 : i64 - %6 = llvm.urem %0, %5 : i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.xor %arg0, %arg1 : i64 - %1 = llvm.udiv %0, %arg0 : i64 - %2 = llvm.udiv %1, %arg2 : i64 - %3 = llvm.lshr %0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i1 - %5 = llvm.zext %4 : i1 to i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { - %0 = llvm.sdiv %arg0, %arg0 : i64 - %1 = llvm.icmp "ule" %arg1, %arg2 : i64 - %2 = llvm.zext %arg3 : i32 to i64 - %3 = llvm.udiv %2, %arg1 : i64 - %4 = llvm.select %1, %arg1, %3 : i1, i64 - %5 = llvm.and %0, %4 : i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.sdiv %arg0, %arg0 : i64 - %1 = llvm.lshr %0, %arg1 : i64 - %2 = llvm.udiv %arg1, %arg2 : i64 - %3 = llvm.sdiv %1, %2 : i64 - %4 = llvm.ashr %0, %3 : i64 - %5 = llvm.udiv %0, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.srem %arg1, %arg2 : i64 - %2 = llvm.select %0, %1, %arg2 : i1, i64 - %3 = llvm.xor %arg0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - %5 = llvm.zext %4 : i32 to i64 - %6 = llvm.and %5, %arg1 : i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { - %0 = llvm.zext %arg1 : i1 to i64 - %1 = llvm.and %arg0, %arg2 : i64 - %2 = llvm.xor %0, %1 : i64 - %3 = llvm.ashr %arg0, %2 : i64 - %4 = llvm.urem %3, %1 : i64 - %5 = llvm.srem %arg0, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.or %arg0, %arg0 : i64 - %1 = llvm.urem %arg0, %0 : i64 - %2 = llvm.icmp "sge" %arg1, %arg1 : i64 - %3 = llvm.sext %2 : i1 to i64 - %4 = llvm.udiv %1, %3 : i64 - %5 = llvm.urem %arg0, %4 : i64 - %6 = llvm.and %5, %arg2 : i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.icmp "ult" %arg0, %0 : i64 - %2 = llvm.select %1, %arg1, %arg0 : i1, i64 - %3 = llvm.trunc %2 : i64 to i1 - %4 = llvm.sext %3 : i1 to i64 - %5 = llvm.srem %4, %arg0 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.ashr %arg1, %arg2 : i64 - %1 = llvm.select %arg0, %0, %0 : i1, i64 - %2 = llvm.srem %1, %1 : i64 - %3 = llvm.ashr %2, %1 : i64 - %4 = llvm.udiv %arg1, %3 : i64 - %5 = llvm.udiv %2, %4 : i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.zext %0 : i1 to i64 - %2 = llvm.zext %arg1 : i32 to i64 - %3 = llvm.srem %2, %2 : i64 - %4 = llvm.ashr %2, %3 : i64 - %5 = llvm.srem %1, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.sdiv %arg0, %arg0 : i64 - %1 = llvm.or %arg1, %arg2 : i64 - %2 = llvm.ashr %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i1 - %4 = llvm.select %3, %0, %2 : i1, i64 - %5 = llvm.xor %arg0, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.urem %arg0, %arg1 : i64 - %1 = llvm.sdiv %arg2, %0 : i64 - %2 = llvm.urem %arg1, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - %4 = llvm.sext %3 : i32 to i64 - %5 = llvm.or %arg0, %4 : i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.udiv %arg0, %arg1 : i64 - %1 = llvm.trunc %arg2 : i64 to i32 - %2 = llvm.zext %1 : i32 to i64 - %3 = llvm.ashr %arg2, %0 : i64 - %4 = llvm.icmp "ne" %2, %3 : i64 - %5 = llvm.select %4, %3, %arg0 : i1, i64 - %6 = llvm.lshr %0, %5 : i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.icmp "uge" %arg0, %arg0 : i64 - %1 = llvm.urem %arg0, %arg0 : i64 - %2 = llvm.select %0, %1, %arg1 : i1, i64 - %3 = llvm.sdiv %arg0, %2 : i64 - %4 = llvm.xor %arg2, %arg2 : i64 - %5 = llvm.icmp "sgt" %3, %4 : i64 - %6 = llvm.zext %5 : i1 to i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.icmp "sge" %arg0, %arg0 : i64 - %1 = llvm.udiv %arg1, %arg0 : i64 - %2 = llvm.srem %1, %arg2 : i64 - %3 = llvm.xor %arg0, %arg2 : i64 - %4 = llvm.select %0, %2, %3 : i1, i64 - %5 = llvm.sext %0 : i1 to i64 - %6 = llvm.icmp "sge" %4, %5 : i64 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.or %arg1, %arg2 : i64 - %1 = llvm.udiv %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - %4 = llvm.xor %1, %1 : i64 - %5 = llvm.and %3, %4 : i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i1) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.sext %0 : i32 to i64 - %2 = llvm.zext %arg2 : i1 to i64 - %3 = llvm.select %arg1, %2, %arg0 : i1, i64 - %4 = llvm.icmp "ule" %3, %3 : i64 - %5 = llvm.select %4, %3, %2 : i1, i64 - %6 = llvm.and %1, %5 : i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.or %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.lshr %arg2, %0 : i64 - %3 = llvm.select %1, %2, %2 : i1, i64 - %4 = llvm.srem %arg1, %arg0 : i64 - %5 = llvm.or %3, %4 : i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.icmp "slt" %arg0, %0 : i64 - %2 = llvm.trunc %arg1 : i64 to i1 - %3 = llvm.sext %2 : i1 to i64 - %4 = llvm.lshr %arg1, %arg2 : i64 - %5 = llvm.select %1, %3, %4 : i1, i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.select %0, %arg1, %arg1 : i1, i64 - %2 = llvm.sdiv %1, %arg1 : i64 - %3 = llvm.srem %arg2, %arg2 : i64 - %4 = llvm.or %1, %3 : i64 - %5 = llvm.or %2, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i32 { - %0 = llvm.urem %arg1, %arg0 : i64 - %1 = llvm.lshr %arg0, %0 : i64 - %2 = llvm.select %arg2, %arg0, %0 : i1, i64 - %3 = llvm.sdiv %2, %2 : i64 - %4 = llvm.sdiv %1, %3 : i64 - %5 = llvm.sdiv %arg0, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i32, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.zext %arg0 : i32 to i64 - %1 = llvm.and %0, %0 : i64 - %2 = llvm.xor %arg1, %arg2 : i64 - %3 = llvm.icmp "ugt" %1, %2 : i64 - %4 = llvm.sext %3 : i1 to i64 - %5 = llvm.ashr %4, %arg2 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.zext %arg1 : i1 to i64 - %1 = llvm.and %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.zext %2 : i32 to i64 - %4 = llvm.trunc %arg2 : i64 to i32 - %5 = llvm.zext %4 : i32 to i64 - %6 = llvm.or %3, %5 : i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { - %0 = llvm.icmp "ult" %arg1, %arg1 : i64 - %1 = llvm.select %0, %arg2, %arg2 : i1, i64 - %2 = llvm.icmp "ule" %arg0, %1 : i64 - %3 = llvm.sext %2 : i1 to i64 - %4 = llvm.sext %arg3 : i32 to i64 - %5 = llvm.urem %arg1, %4 : i64 - %6 = llvm.icmp "sgt" %3, %5 : i64 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.or %arg0, %arg1 : i64 - %1 = llvm.or %arg1, %arg2 : i64 - %2 = llvm.icmp "sge" %0, %1 : i64 - %3 = llvm.select %2, %1, %arg0 : i1, i64 - %4 = llvm.srem %arg2, %3 : i64 - %5 = llvm.select %2, %4, %arg2 : i1, i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.lshr %arg0, %arg1 : i64 - %1 = llvm.sdiv %arg1, %0 : i64 - %2 = llvm.urem %0, %1 : i64 - %3 = llvm.or %2, %1 : i64 - %4 = llvm.srem %1, %2 : i64 - %5 = llvm.urem %arg2, %4 : i64 - %6 = llvm.and %3, %5 : i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.xor %arg0, %arg0 : i64 - %1 = llvm.urem %0, %arg2 : i64 - %2 = llvm.lshr %arg1, %1 : i64 - %3 = llvm.ashr %arg0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i1 - %5 = llvm.sext %4 : i1 to i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { - %0 = llvm.ashr %arg0, %arg1 : i64 - %1 = llvm.select %arg2, %arg0, %arg1 : i1, i64 - %2 = llvm.sdiv %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i1 - %4 = llvm.ashr %0, %2 : i64 - %5 = llvm.select %3, %4, %0 : i1, i64 - %6 = llvm.icmp "ule" %2, %5 : i64 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.udiv %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.select %1, %arg2, %0 : i1, i64 - %3 = llvm.xor %2, %arg1 : i64 - %4 = llvm.srem %arg1, %3 : i64 - %5 = llvm.select %1, %arg1, %4 : i1, i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i1 { - %0 = llvm.sext %arg1 : i32 to i64 - %1 = llvm.or %0, %arg2 : i64 - %2 = llvm.srem %arg0, %1 : i64 - %3 = llvm.zext %arg1 : i32 to i64 - %4 = llvm.sdiv %1, %1 : i64 - %5 = llvm.and %3, %4 : i64 - %6 = llvm.icmp "sle" %2, %5 : i64 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 - %1 = llvm.or %0, %arg1 : i64 - %2 = llvm.udiv %1, %1 : i64 - %3 = llvm.trunc %arg2 : i64 to i32 - %4 = llvm.sext %3 : i32 to i64 - %5 = llvm.srem %2, %4 : i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i1 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.and %0, %0 : i64 - %2 = llvm.sext %arg1 : i32 to i64 - %3 = llvm.udiv %1, %2 : i64 - %4 = llvm.urem %arg2, %3 : i64 - %5 = llvm.xor %3, %4 : i64 - %6 = llvm.icmp "uge" %arg0, %5 : i64 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.select %arg1, %arg0, %arg2 : i1, i64 - %1 = llvm.icmp "ugt" %arg0, %0 : i64 - %2 = llvm.sext %1 : i1 to i64 - %3 = llvm.lshr %0, %2 : i64 - %4 = llvm.sdiv %arg0, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - %6 = llvm.sext %5 : i32 to i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.srem %arg0, %arg1 : i64 - %1 = llvm.and %arg0, %arg1 : i64 - %2 = llvm.udiv %0, %1 : i64 - %3 = llvm.udiv %2, %0 : i64 - %4 = llvm.trunc %3 : i64 to i32 - %5 = llvm.sext %4 : i32 to i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { - %0 = llvm.select %arg2, %arg0, %arg1 : i1, i64 - %1 = llvm.lshr %arg0, %0 : i64 - %2 = llvm.icmp "ugt" %arg1, %1 : i64 - %3 = llvm.or %1, %arg0 : i64 - %4 = llvm.select %2, %3, %0 : i1, i64 - %5 = llvm.and %arg0, %4 : i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i1) -> i1 { - %0 = llvm.select %arg2, %arg0, %arg0 : i1, i64 - %1 = llvm.urem %arg0, %0 : i64 - %2 = llvm.urem %1, %arg0 : i64 - %3 = llvm.or %0, %2 : i64 - %4 = llvm.select %arg1, %3, %arg0 : i1, i64 - %5 = llvm.or %arg0, %4 : i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.select %0, %arg0, %arg0 : i1, i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - %4 = llvm.srem %3, %3 : i64 - %5 = llvm.lshr %4, %arg0 : i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.select %1, %arg1, %0 : i1, i64 - %3 = llvm.ashr %2, %arg2 : i64 - %4 = llvm.icmp "slt" %2, %0 : i64 - %5 = llvm.select %4, %arg0, %0 : i1, i64 - %6 = llvm.urem %3, %5 : i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.icmp "ugt" %arg0, %arg1 : i64 - %1 = llvm.zext %0 : i1 to i64 - %2 = llvm.ashr %1, %arg0 : i64 - %3 = llvm.sdiv %arg2, %arg0 : i64 - %4 = llvm.sdiv %3, %arg1 : i64 - %5 = llvm.lshr %2, %4 : i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.xor %arg0, %arg0 : i64 - %1 = llvm.urem %0, %arg1 : i64 - %2 = llvm.and %1, %arg2 : i64 - %3 = llvm.or %2, %arg2 : i64 - %4 = llvm.srem %3, %arg0 : i64 - %5 = llvm.sdiv %arg2, %4 : i64 - %6 = llvm.icmp "eq" %1, %5 : i64 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i32) -> i32 { - %0 = llvm.ashr %arg0, %arg0 : i64 - %1 = llvm.lshr %0, %arg1 : i64 - %2 = llvm.sdiv %arg2, %arg0 : i64 - %3 = llvm.sext %arg3 : i32 to i64 - %4 = llvm.lshr %2, %3 : i64 - %5 = llvm.lshr %1, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i32, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.sext %arg0 : i32 to i64 - %1 = llvm.trunc %arg1 : i64 to i1 - %2 = llvm.sext %1 : i1 to i64 - %3 = llvm.icmp "uge" %0, %2 : i64 - %4 = llvm.zext %3 : i1 to i64 - %5 = llvm.ashr %4, %arg2 : i64 - %6 = llvm.xor %5, %arg1 : i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.icmp "ugt" %arg0, %arg0 : i64 - %1 = llvm.srem %arg0, %arg0 : i64 - %2 = llvm.xor %1, %1 : i64 - %3 = llvm.trunc %arg1 : i64 to i1 - %4 = llvm.sext %3 : i1 to i64 - %5 = llvm.select %0, %2, %4 : i1, i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i1 { - %0 = llvm.ashr %arg0, %arg1 : i64 - %1 = llvm.zext %arg3 : i1 to i64 - %2 = llvm.lshr %arg1, %1 : i64 - %3 = llvm.trunc %2 : i64 to i1 - %4 = llvm.select %3, %1, %arg0 : i1, i64 - %5 = llvm.and %arg2, %4 : i64 - %6 = llvm.icmp "slt" %0, %5 : i64 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i32, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.sext %arg0 : i32 to i64 - %1 = llvm.sext %arg1 : i1 to i64 - %2 = llvm.sdiv %1, %arg2 : i64 - %3 = llvm.ashr %0, %2 : i64 - %4 = llvm.lshr %3, %arg2 : i64 - %5 = llvm.and %3, %4 : i64 - %6 = llvm.and %3, %5 : i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i64 { - %0 = llvm.urem %arg1, %arg1 : i64 - %1 = llvm.ashr %arg0, %0 : i64 - %2 = llvm.srem %arg2, %1 : i64 - %3 = llvm.and %1, %2 : i64 - %4 = llvm.sext %arg3 : i1 to i64 - %5 = llvm.lshr %1, %4 : i64 - %6 = llvm.xor %3, %5 : i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.urem %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.sext %1 : i32 to i64 - %3 = llvm.zext %1 : i32 to i64 - %4 = llvm.udiv %2, %3 : i64 - %5 = llvm.srem %4, %3 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64) -> i32 { - %0 = llvm.sext %arg0 : i1 to i64 - %1 = llvm.udiv %0, %0 : i64 - %2 = llvm.xor %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - %4 = llvm.zext %3 : i32 to i64 - %5 = llvm.lshr %4, %arg1 : i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i1 { - %0 = llvm.or %arg0, %arg0 : i64 - %1 = llvm.srem %0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - %4 = llvm.trunc %3 : i64 to i32 - %5 = llvm.zext %4 : i32 to i64 - %6 = llvm.icmp "ule" %0, %5 : i64 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.udiv %arg0, %1 : i64 - %3 = llvm.icmp "ugt" %arg1, %arg2 : i64 - %4 = llvm.select %3, %arg2, %2 : i1, i64 - %5 = llvm.and %2, %4 : i64 - %6 = llvm.trunc %5 : i64 to i1 - return %6 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.zext %0 : i1 to i64 - %2 = llvm.and %1, %1 : i64 - %3 = llvm.udiv %2, %2 : i64 - %4 = llvm.trunc %3 : i64 to i1 - %5 = llvm.zext %4 : i1 to i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i64 { - %0 = llvm.or %arg0, %arg1 : i64 - %1 = llvm.sext %arg2 : i1 to i64 - %2 = llvm.and %0, %1 : i64 - %3 = llvm.icmp "eq" %1, %2 : i64 - %4 = llvm.xor %arg0, %1 : i64 - %5 = llvm.select %3, %2, %4 : i1, i64 - %6 = llvm.ashr %0, %5 : i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.and %arg0, %arg0 : i64 - %1 = llvm.or %0, %arg1 : i64 - %2 = llvm.ashr %arg0, %arg2 : i64 - %3 = llvm.sdiv %2, %arg1 : i64 - %4 = llvm.urem %1, %0 : i64 - %5 = llvm.sdiv %3, %4 : i64 - %6 = llvm.urem %1, %5 : i64 - return %6 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.xor %arg0, %arg2 : i64 - %1 = llvm.lshr %arg1, %0 : i64 - %2 = llvm.xor %1, %arg0 : i64 - %3 = llvm.urem %arg0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - %5 = llvm.sext %4 : i32 to i64 - %6 = llvm.trunc %5 : i64 to i32 - return %6 : i32 - } -} -// ----- diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_8.mlir b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_8.mlir deleted file mode 100644 index 0fdbac9802..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_8.mlir +++ /dev/null @@ -1,1400 +0,0 @@ -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i1 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.lshr %0, %arg1 : i64 - %2 = llvm.and %1, %arg2 : i64 - %3 = llvm.urem %arg0, %0 : i64 - %4 = llvm.select %arg3, %3, %2 : i1, i64 - %5 = llvm.and %2, %4 : i64 - %6 = llvm.or %2, %5 : i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.sdiv %arg0, %arg1 : i64 - %1 = llvm.udiv %0, %arg2 : i64 - %2 = llvm.and %arg0, %1 : i64 - %3 = llvm.udiv %0, %2 : i64 - %4 = llvm.ashr %arg1, %arg0 : i64 - %5 = llvm.xor %3, %4 : i64 - %6 = llvm.udiv %5, %arg0 : i64 - %7 = llvm.icmp "ule" %2, %6 : i64 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64) -> i32 { - %0 = llvm.sext %arg0 : i1 to i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.sext %1 : i32 to i64 - %3 = llvm.srem %0, %arg1 : i64 - %4 = llvm.trunc %3 : i64 to i32 - %5 = llvm.sext %4 : i32 to i64 - %6 = llvm.or %2, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { - %0 = llvm.select %arg1, %arg2, %arg2 : i1, i64 - %1 = llvm.udiv %arg0, %0 : i64 - %2 = llvm.srem %1, %0 : i64 - %3 = llvm.urem %arg0, %2 : i64 - %4 = llvm.and %arg2, %3 : i64 - %5 = llvm.or %4, %3 : i64 - %6 = llvm.or %3, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { - %0 = llvm.select %arg0, %arg1, %arg2 : i1, i64 - %1 = llvm.sext %arg3 : i32 to i64 - %2 = llvm.select %arg0, %arg1, %1 : i1, i64 - %3 = llvm.lshr %1, %2 : i64 - %4 = llvm.lshr %0, %3 : i64 - %5 = llvm.select %arg0, %arg1, %4 : i1, i64 - %6 = llvm.urem %4, %5 : i64 - %7 = llvm.icmp "sgt" %4, %6 : i64 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i32 { - %0 = llvm.sdiv %arg0, %arg0 : i64 - %1 = llvm.or %arg1, %arg0 : i64 - %2 = llvm.select %arg3, %arg2, %0 : i1, i64 - %3 = llvm.ashr %arg2, %2 : i64 - %4 = llvm.sdiv %1, %3 : i64 - %5 = llvm.and %0, %4 : i64 - %6 = llvm.ashr %5, %0 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i32, %arg2: i64) -> i1 { - %0 = llvm.sext %arg0 : i1 to i64 - %1 = llvm.sext %arg1 : i32 to i64 - %2 = llvm.or %arg2, %0 : i64 - %3 = llvm.sdiv %2, %0 : i64 - %4 = llvm.srem %3, %2 : i64 - %5 = llvm.and %1, %4 : i64 - %6 = llvm.sdiv %0, %5 : i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64, %arg3: i32) -> i32 { - %0 = llvm.sext %arg3 : i32 to i64 - %1 = llvm.lshr %arg2, %0 : i64 - %2 = llvm.icmp "sge" %1, %arg0 : i64 - %3 = llvm.sext %2 : i1 to i64 - %4 = llvm.select %arg1, %1, %3 : i1, i64 - %5 = llvm.and %4, %4 : i64 - %6 = llvm.udiv %arg0, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { - %0 = llvm.sext %arg1 : i1 to i64 - %1 = llvm.and %0, %arg0 : i64 - %2 = llvm.ashr %1, %arg2 : i64 - %3 = llvm.sdiv %2, %arg2 : i64 - %4 = llvm.udiv %arg0, %3 : i64 - %5 = llvm.trunc %4 : i64 to i1 - %6 = llvm.sext %5 : i1 to i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.xor %arg0, %arg1 : i64 - %1 = llvm.xor %0, %0 : i64 - %2 = llvm.ashr %arg0, %arg1 : i64 - %3 = llvm.udiv %arg2, %1 : i64 - %4 = llvm.sdiv %2, %3 : i64 - %5 = llvm.or %1, %4 : i64 - %6 = llvm.srem %5, %4 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.xor %arg1, %arg2 : i64 - %2 = llvm.xor %0, %1 : i64 - %3 = llvm.lshr %arg1, %2 : i64 - %4 = llvm.srem %3, %2 : i64 - %5 = llvm.and %0, %4 : i64 - %6 = llvm.or %5, %0 : i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i1, %arg2: i64) -> i1 { - %0 = llvm.zext %arg0 : i1 to i64 - %1 = llvm.select %arg1, %0, %0 : i1, i64 - %2 = llvm.lshr %1, %arg2 : i64 - %3 = llvm.icmp "sge" %0, %2 : i64 - %4 = llvm.sext %3 : i1 to i64 - %5 = llvm.trunc %2 : i64 to i1 - %6 = llvm.sext %5 : i1 to i64 - %7 = llvm.icmp "sgt" %4, %6 : i64 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.ashr %arg2, %arg0 : i64 - %1 = llvm.or %arg1, %0 : i64 - %2 = llvm.trunc %1 : i64 to i1 - %3 = llvm.select %2, %1, %1 : i1, i64 - %4 = llvm.sdiv %3, %1 : i64 - %5 = llvm.select %2, %1, %0 : i1, i64 - %6 = llvm.select %2, %4, %5 : i1, i64 - %7 = llvm.icmp "uge" %arg0, %6 : i64 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i32 { - %0 = llvm.zext %arg2 : i1 to i64 - %1 = llvm.or %arg1, %0 : i64 - %2 = llvm.urem %arg1, %1 : i64 - %3 = llvm.urem %2, %arg1 : i64 - %4 = llvm.srem %arg1, %3 : i64 - %5 = llvm.sdiv %arg0, %4 : i64 - %6 = llvm.ashr %5, %0 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.sext %0 : i32 to i64 - %2 = llvm.udiv %arg2, %1 : i64 - %3 = llvm.xor %arg2, %2 : i64 - %4 = llvm.sdiv %3, %arg2 : i64 - %5 = llvm.select %arg1, %2, %4 : i1, i64 - %6 = llvm.lshr %arg0, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { - %0 = llvm.and %arg0, %arg0 : i64 - %1 = llvm.udiv %arg2, %arg2 : i64 - %2 = llvm.srem %arg2, %1 : i64 - %3 = llvm.lshr %arg1, %2 : i64 - %4 = llvm.zext %arg3 : i32 to i64 - %5 = llvm.sdiv %3, %4 : i64 - %6 = llvm.udiv %0, %5 : i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.sext %0 : i1 to i64 - %2 = llvm.srem %1, %arg1 : i64 - %3 = llvm.urem %1, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - %5 = llvm.zext %4 : i32 to i64 - %6 = llvm.udiv %5, %1 : i64 - %7 = llvm.urem %6, %arg2 : i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.trunc %arg1 : i64 to i1 - %1 = llvm.zext %0 : i1 to i64 - %2 = llvm.sdiv %1, %arg2 : i64 - %3 = llvm.urem %arg0, %2 : i64 - %4 = llvm.udiv %arg1, %arg1 : i64 - %5 = llvm.icmp "slt" %3, %4 : i64 - %6 = llvm.lshr %arg2, %4 : i64 - %7 = llvm.select %5, %6, %1 : i1, i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i64 { - %0 = llvm.udiv %arg2, %arg2 : i64 - %1 = llvm.or %0, %0 : i64 - %2 = llvm.xor %1, %arg0 : i64 - %3 = llvm.xor %arg1, %2 : i64 - %4 = llvm.sdiv %arg0, %3 : i64 - %5 = llvm.zext %arg3 : i1 to i64 - %6 = llvm.or %4, %5 : i64 - %7 = llvm.ashr %arg0, %6 : i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.urem %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.select %1, %arg0, %0 : i1, i64 - %3 = llvm.udiv %0, %arg0 : i64 - %4 = llvm.or %2, %3 : i64 - %5 = llvm.or %arg1, %arg2 : i64 - %6 = llvm.and %4, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.zext %0 : i32 to i64 - %2 = llvm.ashr %1, %1 : i64 - %3 = llvm.srem %2, %arg1 : i64 - %4 = llvm.ashr %1, %3 : i64 - %5 = llvm.urem %4, %2 : i64 - %6 = llvm.sdiv %1, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.srem %arg0, %arg1 : i64 - %1 = llvm.ashr %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.zext %2 : i32 to i64 - %4 = llvm.trunc %3 : i64 to i32 - %5 = llvm.sext %4 : i32 to i64 - %6 = llvm.and %5, %arg2 : i64 - %7 = llvm.icmp "ne" %3, %6 : i64 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64, %arg3: i32) -> i64 { - %0 = llvm.urem %arg0, %arg0 : i64 - %1 = llvm.select %arg1, %0, %arg2 : i1, i64 - %2 = llvm.icmp "ugt" %0, %1 : i64 - %3 = llvm.trunc %arg2 : i64 to i1 - %4 = llvm.sext %arg3 : i32 to i64 - %5 = llvm.lshr %arg2, %0 : i64 - %6 = llvm.select %3, %4, %5 : i1, i64 - %7 = llvm.select %2, %arg0, %6 : i1, i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.icmp "sle" %arg0, %arg0 : i64 - %1 = llvm.zext %0 : i1 to i64 - %2 = llvm.urem %arg1, %arg2 : i64 - %3 = llvm.icmp "ne" %1, %2 : i64 - %4 = llvm.srem %arg2, %arg0 : i64 - %5 = llvm.sdiv %4, %arg0 : i64 - %6 = llvm.select %3, %arg1, %5 : i1, i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.sdiv %arg0, %arg1 : i64 - %1 = llvm.and %arg2, %arg0 : i64 - %2 = llvm.udiv %arg2, %1 : i64 - %3 = llvm.udiv %0, %2 : i64 - %4 = llvm.srem %3, %arg0 : i64 - %5 = llvm.srem %4, %arg0 : i64 - %6 = llvm.sdiv %3, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64) -> i1 { - %0 = llvm.zext %arg0 : i1 to i64 - %1 = llvm.icmp "ule" %0, %0 : i64 - %2 = llvm.zext %1 : i1 to i64 - %3 = llvm.sdiv %0, %arg1 : i64 - %4 = llvm.lshr %0, %3 : i64 - %5 = llvm.sdiv %arg1, %4 : i64 - %6 = llvm.lshr %2, %5 : i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.and %arg0, %arg0 : i64 - %1 = llvm.select %arg1, %arg2, %arg0 : i1, i64 - %2 = llvm.urem %0, %1 : i64 - %3 = llvm.or %1, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - %5 = llvm.zext %4 : i32 to i64 - %6 = llvm.and %2, %5 : i64 - %7 = llvm.ashr %6, %5 : i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.icmp "slt" %arg0, %arg1 : i64 - %1 = llvm.zext %0 : i1 to i64 - %2 = llvm.and %arg1, %1 : i64 - %3 = llvm.xor %arg0, %2 : i64 - %4 = llvm.icmp "sge" %arg2, %3 : i64 - %5 = llvm.srem %1, %arg0 : i64 - %6 = llvm.select %4, %arg1, %5 : i1, i64 - %7 = llvm.lshr %3, %6 : i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.xor %arg0, %arg1 : i64 - %1 = llvm.udiv %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.sext %2 : i32 to i64 - %4 = llvm.srem %arg2, %arg2 : i64 - %5 = llvm.or %3, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - %7 = llvm.sext %6 : i32 to i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.and %0, %0 : i64 - %2 = llvm.srem %arg2, %arg2 : i64 - %3 = llvm.select %arg1, %arg2, %2 : i1, i64 - %4 = llvm.urem %1, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - %6 = llvm.sext %5 : i32 to i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i32, %arg2: i64) -> i1 { - %0 = llvm.sext %arg1 : i32 to i64 - %1 = llvm.select %arg0, %0, %arg2 : i1, i64 - %2 = llvm.ashr %1, %1 : i64 - %3 = llvm.sext %arg0 : i1 to i64 - %4 = llvm.sdiv %3, %3 : i64 - %5 = llvm.or %4, %1 : i64 - %6 = llvm.ashr %2, %5 : i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i32 { - %0 = llvm.sext %arg1 : i32 to i64 - %1 = llvm.xor %0, %arg0 : i64 - %2 = llvm.or %arg0, %1 : i64 - %3 = llvm.sdiv %2, %1 : i64 - %4 = llvm.trunc %3 : i64 to i32 - %5 = llvm.zext %4 : i32 to i64 - %6 = llvm.sdiv %5, %arg2 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.urem %arg0, %arg0 : i64 - %1 = llvm.select %arg1, %arg2, %0 : i1, i64 - %2 = llvm.sdiv %1, %0 : i64 - %3 = llvm.and %2, %arg0 : i64 - %4 = llvm.trunc %3 : i64 to i32 - %5 = llvm.zext %4 : i32 to i64 - %6 = llvm.sdiv %5, %5 : i64 - %7 = llvm.udiv %0, %6 : i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.select %arg0, %arg1, %arg2 : i1, i64 - %1 = llvm.sext %arg0 : i1 to i64 - %2 = llvm.udiv %0, %1 : i64 - %3 = llvm.lshr %2, %1 : i64 - %4 = llvm.trunc %arg1 : i64 to i1 - %5 = llvm.sext %4 : i1 to i64 - %6 = llvm.ashr %3, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.sext %arg0 : i1 to i64 - %1 = llvm.udiv %arg1, %arg2 : i64 - %2 = llvm.icmp "ne" %0, %1 : i64 - %3 = llvm.sext %2 : i1 to i64 - %4 = llvm.ashr %0, %3 : i64 - %5 = llvm.udiv %arg2, %4 : i64 - %6 = llvm.udiv %4, %5 : i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i1 { - %0 = llvm.srem %arg0, %arg1 : i64 - %1 = llvm.or %arg2, %arg1 : i64 - %2 = llvm.zext %arg3 : i1 to i64 - %3 = llvm.lshr %1, %2 : i64 - %4 = llvm.icmp "ult" %0, %3 : i64 - %5 = llvm.zext %4 : i1 to i64 - %6 = llvm.urem %arg0, %2 : i64 - %7 = llvm.icmp "ult" %5, %6 : i64 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.icmp "ule" %arg0, %arg0 : i64 - %1 = llvm.zext %0 : i1 to i64 - %2 = llvm.xor %arg1, %1 : i64 - %3 = llvm.srem %arg2, %arg0 : i64 - %4 = llvm.urem %2, %3 : i64 - %5 = llvm.lshr %4, %1 : i64 - %6 = llvm.udiv %1, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { - %0 = llvm.and %arg0, %arg1 : i64 - %1 = llvm.zext %arg2 : i1 to i64 - %2 = llvm.srem %0, %1 : i64 - %3 = llvm.sdiv %arg0, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - %5 = llvm.zext %4 : i32 to i64 - %6 = llvm.and %arg0, %5 : i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i1 - %1 = llvm.select %0, %arg0, %arg0 : i1, i64 - %2 = llvm.icmp "sgt" %1, %1 : i64 - %3 = llvm.or %arg1, %arg0 : i64 - %4 = llvm.ashr %3, %1 : i64 - %5 = llvm.srem %1, %4 : i64 - %6 = llvm.select %2, %3, %5 : i1, i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i1 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.zext %0 : i32 to i64 - %2 = llvm.or %1, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - %4 = llvm.zext %3 : i32 to i64 - %5 = llvm.ashr %1, %4 : i64 - %6 = llvm.and %2, %5 : i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64) -> i1 { - %0 = llvm.sdiv %arg0, %arg0 : i64 - %1 = llvm.xor %0, %0 : i64 - %2 = llvm.srem %0, %1 : i64 - %3 = llvm.udiv %arg0, %2 : i64 - %4 = llvm.or %3, %arg0 : i64 - %5 = llvm.trunc %4 : i64 to i1 - %6 = llvm.sext %5 : i1 to i64 - %7 = llvm.icmp "ult" %6, %0 : i64 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i32 { - %0 = llvm.ashr %arg0, %arg1 : i64 - %1 = llvm.lshr %arg0, %0 : i64 - %2 = llvm.select %arg2, %arg1, %arg0 : i1, i64 - %3 = llvm.icmp "eq" %1, %2 : i64 - %4 = llvm.sext %3 : i1 to i64 - %5 = llvm.icmp "sle" %arg0, %4 : i64 - %6 = llvm.sext %5 : i1 to i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.select %arg0, %arg1, %arg2 : i1, i64 - %1 = llvm.and %0, %arg1 : i64 - %2 = llvm.ashr %1, %0 : i64 - %3 = llvm.trunc %2 : i64 to i1 - %4 = llvm.trunc %arg1 : i64 to i32 - %5 = llvm.zext %4 : i32 to i64 - %6 = llvm.select %3, %5, %5 : i1, i64 - %7 = llvm.srem %1, %6 : i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.ashr %arg1, %arg2 : i64 - %1 = llvm.sdiv %0, %0 : i64 - %2 = llvm.sdiv %1, %0 : i64 - %3 = llvm.and %1, %1 : i64 - %4 = llvm.or %0, %3 : i64 - %5 = llvm.sdiv %2, %4 : i64 - %6 = llvm.select %arg0, %0, %5 : i1, i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i32 { - %0 = llvm.udiv %arg0, %arg2 : i64 - %1 = llvm.select %arg3, %arg0, %arg1 : i1, i64 - %2 = llvm.udiv %0, %1 : i64 - %3 = llvm.udiv %0, %2 : i64 - %4 = llvm.xor %3, %2 : i64 - %5 = llvm.xor %arg1, %4 : i64 - %6 = llvm.lshr %arg0, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { - %0 = llvm.and %arg0, %arg0 : i64 - %1 = llvm.srem %0, %arg0 : i64 - %2 = llvm.trunc %1 : i64 to i1 - %3 = llvm.or %arg1, %arg0 : i64 - %4 = llvm.select %arg2, %arg0, %3 : i1, i64 - %5 = llvm.select %2, %3, %4 : i1, i64 - %6 = llvm.and %1, %3 : i64 - %7 = llvm.icmp "ne" %5, %6 : i64 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { - %0 = llvm.urem %arg1, %arg2 : i64 - %1 = llvm.ashr %arg0, %0 : i64 - %2 = llvm.sext %arg3 : i32 to i64 - %3 = llvm.ashr %arg1, %0 : i64 - %4 = llvm.xor %2, %3 : i64 - %5 = llvm.xor %1, %4 : i64 - %6 = llvm.and %arg0, %5 : i64 - %7 = llvm.icmp "slt" %6, %1 : i64 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i1 { - %0 = llvm.sext %arg1 : i32 to i64 - %1 = llvm.and %arg0, %0 : i64 - %2 = llvm.sdiv %1, %1 : i64 - %3 = llvm.and %arg0, %2 : i64 - %4 = llvm.srem %arg2, %2 : i64 - %5 = llvm.ashr %1, %4 : i64 - %6 = llvm.srem %3, %5 : i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.udiv %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.sext %1 : i32 to i64 - %3 = llvm.icmp "sgt" %arg0, %0 : i64 - %4 = llvm.sext %3 : i1 to i64 - %5 = llvm.xor %2, %2 : i64 - %6 = llvm.urem %4, %5 : i64 - %7 = llvm.ashr %2, %6 : i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.xor %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.sext %1 : i32 to i64 - %3 = llvm.ashr %arg0, %arg1 : i64 - %4 = llvm.icmp "uge" %2, %3 : i64 - %5 = llvm.and %arg2, %3 : i64 - %6 = llvm.select %4, %5, %arg2 : i1, i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.lshr %arg1, %arg2 : i64 - %1 = llvm.urem %0, %arg0 : i64 - %2 = llvm.ashr %arg1, %1 : i64 - %3 = llvm.udiv %1, %2 : i64 - %4 = llvm.trunc %3 : i64 to i1 - %5 = llvm.select %4, %3, %2 : i1, i64 - %6 = llvm.ashr %arg0, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.srem %arg2, %arg1 : i64 - %1 = llvm.srem %arg1, %0 : i64 - %2 = llvm.lshr %0, %arg0 : i64 - %3 = llvm.or %1, %2 : i64 - %4 = llvm.xor %2, %2 : i64 - %5 = llvm.urem %3, %4 : i64 - %6 = llvm.udiv %arg0, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.udiv %arg0, %arg0 : i64 - %1 = llvm.and %arg0, %0 : i64 - %2 = llvm.sdiv %arg1, %arg2 : i64 - %3 = llvm.lshr %1, %2 : i64 - %4 = llvm.srem %3, %arg2 : i64 - %5 = llvm.trunc %4 : i64 to i32 - %6 = llvm.zext %5 : i32 to i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i32 { - %0 = llvm.xor %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.zext %1 : i32 to i64 - %3 = llvm.sext %arg2 : i1 to i64 - %4 = llvm.or %2, %3 : i64 - %5 = llvm.srem %2, %4 : i64 - %6 = llvm.udiv %2, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.urem %arg0, %arg0 : i64 - %1 = llvm.xor %arg0, %0 : i64 - %2 = llvm.icmp "uge" %1, %1 : i64 - %3 = llvm.trunc %arg1 : i64 to i1 - %4 = llvm.sdiv %arg2, %arg1 : i64 - %5 = llvm.select %3, %4, %arg2 : i1, i64 - %6 = llvm.select %2, %0, %5 : i1, i64 - %7 = llvm.icmp "ule" %6, %arg2 : i64 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.ashr %arg0, %arg1 : i64 - %1 = llvm.lshr %arg0, %0 : i64 - %2 = llvm.and %arg2, %1 : i64 - %3 = llvm.urem %1, %2 : i64 - %4 = llvm.trunc %arg1 : i64 to i1 - %5 = llvm.zext %4 : i1 to i64 - %6 = llvm.sdiv %3, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.select %arg1, %arg0, %arg2 : i1, i64 - %1 = llvm.urem %0, %0 : i64 - %2 = llvm.sdiv %arg0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i1 - %4 = llvm.and %0, %1 : i64 - %5 = llvm.xor %1, %1 : i64 - %6 = llvm.srem %5, %4 : i64 - %7 = llvm.select %3, %4, %6 : i1, i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i32, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.sext %arg0 : i32 to i64 - %1 = llvm.urem %arg1, %arg1 : i64 - %2 = llvm.or %arg1, %1 : i64 - %3 = llvm.icmp "ugt" %2, %0 : i64 - %4 = llvm.sext %3 : i1 to i64 - %5 = llvm.sdiv %0, %4 : i64 - %6 = llvm.srem %arg2, %1 : i64 - %7 = llvm.and %5, %6 : i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64, %arg3: i32) -> i1 { - %0 = llvm.sext %arg3 : i32 to i64 - %1 = llvm.select %arg1, %arg2, %0 : i1, i64 - %2 = llvm.udiv %arg0, %1 : i64 - %3 = llvm.ashr %2, %arg2 : i64 - %4 = llvm.and %1, %3 : i64 - %5 = llvm.icmp "slt" %4, %arg0 : i64 - %6 = llvm.sext %5 : i1 to i64 - %7 = llvm.icmp "sgt" %arg0, %6 : i64 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i1 { - %0 = llvm.sext %arg1 : i32 to i64 - %1 = llvm.xor %arg0, %0 : i64 - %2 = llvm.or %1, %arg2 : i64 - %3 = llvm.or %2, %arg0 : i64 - %4 = llvm.trunc %3 : i64 to i1 - %5 = llvm.sext %4 : i1 to i64 - %6 = llvm.ashr %arg2, %5 : i64 - %7 = llvm.icmp "uge" %1, %6 : i64 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i1 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.sext %arg1 : i32 to i64 - %2 = llvm.xor %1, %arg0 : i64 - %3 = llvm.icmp "ne" %1, %2 : i64 - %4 = llvm.xor %arg0, %arg2 : i64 - %5 = llvm.select %3, %2, %4 : i1, i64 - %6 = llvm.or %0, %5 : i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.sext %arg0 : i1 to i64 - %1 = llvm.select %arg0, %arg1, %arg1 : i1, i64 - %2 = llvm.icmp "ne" %arg2, %1 : i64 - %3 = llvm.sext %2 : i1 to i64 - %4 = llvm.trunc %3 : i64 to i32 - %5 = llvm.sext %4 : i32 to i64 - %6 = llvm.lshr %arg1, %5 : i64 - %7 = llvm.urem %0, %6 : i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i32 { - %0 = llvm.zext %arg1 : i32 to i64 - %1 = llvm.urem %arg2, %0 : i64 - %2 = llvm.or %0, %1 : i64 - %3 = llvm.or %1, %1 : i64 - %4 = llvm.urem %1, %3 : i64 - %5 = llvm.xor %2, %4 : i64 - %6 = llvm.lshr %arg0, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.icmp "ule" %arg2, %arg2 : i64 - %1 = llvm.zext %0 : i1 to i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.zext %2 : i32 to i64 - %4 = llvm.and %arg1, %3 : i64 - %5 = llvm.sdiv %arg0, %4 : i64 - %6 = llvm.xor %arg2, %1 : i64 - %7 = llvm.sdiv %5, %6 : i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.xor %arg0, %arg0 : i64 - %1 = llvm.and %arg2, %arg0 : i64 - %2 = llvm.lshr %arg1, %1 : i64 - %3 = llvm.trunc %2 : i64 to i32 - %4 = llvm.sext %3 : i32 to i64 - %5 = llvm.sdiv %0, %4 : i64 - %6 = llvm.urem %5, %5 : i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64) -> i1 { - %0 = llvm.zext %arg0 : i1 to i64 - %1 = llvm.sext %arg0 : i1 to i64 - %2 = llvm.srem %1, %1 : i64 - %3 = llvm.srem %0, %2 : i64 - %4 = llvm.urem %arg1, %3 : i64 - %5 = llvm.udiv %0, %4 : i64 - %6 = llvm.xor %0, %5 : i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.and %0, %arg0 : i64 - %2 = llvm.urem %1, %arg2 : i64 - %3 = llvm.or %arg1, %2 : i64 - %4 = llvm.icmp "ule" %0, %3 : i64 - %5 = llvm.zext %4 : i1 to i64 - %6 = llvm.srem %1, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.ashr %arg1, %arg2 : i64 - %1 = llvm.or %arg0, %0 : i64 - %2 = llvm.trunc %arg1 : i64 to i1 - %3 = llvm.zext %2 : i1 to i64 - %4 = llvm.icmp "slt" %1, %3 : i64 - %5 = llvm.select %4, %0, %arg2 : i1, i64 - %6 = llvm.trunc %5 : i64 to i32 - %7 = llvm.sext %6 : i32 to i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { - %0 = llvm.zext %arg1 : i1 to i64 - %1 = llvm.trunc %arg2 : i64 to i1 - %2 = llvm.sext %1 : i1 to i64 - %3 = llvm.and %0, %2 : i64 - %4 = llvm.udiv %arg0, %3 : i64 - %5 = llvm.udiv %4, %0 : i64 - %6 = llvm.and %5, %4 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { - %0 = llvm.select %arg1, %arg0, %arg2 : i1, i64 - %1 = llvm.srem %arg0, %0 : i64 - %2 = llvm.xor %arg0, %1 : i64 - %3 = llvm.xor %0, %0 : i64 - %4 = llvm.or %2, %3 : i64 - %5 = llvm.trunc %4 : i64 to i1 - %6 = llvm.zext %5 : i1 to i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.udiv %0, %arg1 : i64 - %2 = llvm.lshr %0, %1 : i64 - %3 = llvm.icmp "ult" %0, %arg0 : i64 - %4 = llvm.sext %3 : i1 to i64 - %5 = llvm.udiv %2, %4 : i64 - %6 = llvm.or %arg0, %5 : i64 - %7 = llvm.icmp "sgt" %6, %0 : i64 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.or %arg1, %arg1 : i64 - %1 = llvm.sdiv %arg1, %arg2 : i64 - %2 = llvm.icmp "ne" %arg2, %1 : i64 - %3 = llvm.zext %2 : i1 to i64 - %4 = llvm.and %arg2, %1 : i64 - %5 = llvm.urem %3, %4 : i64 - %6 = llvm.sdiv %0, %5 : i64 - %7 = llvm.icmp "ugt" %arg0, %6 : i64 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.udiv %arg0, %arg1 : i64 - %1 = llvm.lshr %arg1, %arg0 : i64 - %2 = llvm.sdiv %0, %1 : i64 - %3 = llvm.sdiv %arg2, %arg0 : i64 - %4 = llvm.ashr %arg2, %3 : i64 - %5 = llvm.and %arg1, %4 : i64 - %6 = llvm.udiv %2, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.select %arg0, %arg1, %arg2 : i1, i64 - %1 = llvm.icmp "ugt" %0, %arg1 : i64 - %2 = llvm.sext %1 : i1 to i64 - %3 = llvm.urem %0, %2 : i64 - %4 = llvm.and %3, %arg2 : i64 - %5 = llvm.udiv %2, %4 : i64 - %6 = llvm.udiv %3, %5 : i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.trunc %arg0 : i64 to i32 - %1 = llvm.sext %0 : i32 to i64 - %2 = llvm.lshr %arg1, %1 : i64 - %3 = llvm.ashr %2, %arg1 : i64 - %4 = llvm.or %1, %3 : i64 - %5 = llvm.trunc %1 : i64 to i32 - %6 = llvm.sext %5 : i32 to i64 - %7 = llvm.xor %4, %6 : i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.lshr %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i1 - %2 = llvm.select %1, %arg2, %arg2 : i1, i64 - %3 = llvm.srem %0, %arg1 : i64 - %4 = llvm.xor %2, %3 : i64 - %5 = llvm.and %4, %arg1 : i64 - %6 = llvm.ashr %arg2, %arg0 : i64 - %7 = llvm.icmp "sge" %5, %6 : i64 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i64 { - %0 = llvm.or %arg0, %arg1 : i64 - %1 = llvm.sdiv %arg1, %arg0 : i64 - %2 = llvm.zext %arg2 : i1 to i64 - %3 = llvm.urem %arg1, %2 : i64 - %4 = llvm.and %2, %3 : i64 - %5 = llvm.srem %1, %4 : i64 - %6 = llvm.udiv %0, %5 : i64 - %7 = llvm.sdiv %arg0, %6 : i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.icmp "ne" %arg0, %arg1 : i64 - %1 = llvm.select %0, %arg2, %arg2 : i1, i64 - %2 = llvm.srem %arg1, %arg0 : i64 - %3 = llvm.ashr %arg1, %2 : i64 - %4 = llvm.sdiv %3, %1 : i64 - %5 = llvm.xor %1, %4 : i64 - %6 = llvm.or %5, %4 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.ashr %arg1, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.sext %1 : i32 to i64 - %3 = llvm.trunc %2 : i64 to i1 - %4 = llvm.sext %3 : i1 to i64 - %5 = llvm.trunc %4 : i64 to i32 - %6 = llvm.sext %5 : i32 to i64 - %7 = llvm.ashr %arg0, %6 : i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.or %arg0, %arg1 : i64 - %1 = llvm.and %0, %arg2 : i64 - %2 = llvm.sdiv %1, %1 : i64 - %3 = llvm.lshr %2, %arg2 : i64 - %4 = llvm.srem %arg1, %3 : i64 - %5 = llvm.urem %2, %4 : i64 - %6 = llvm.or %5, %arg1 : i64 - %7 = llvm.srem %6, %6 : i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { - %0 = llvm.select %arg1, %arg2, %arg0 : i1, i64 - %1 = llvm.sdiv %arg0, %0 : i64 - %2 = llvm.sdiv %1, %1 : i64 - %3 = llvm.and %2, %2 : i64 - %4 = llvm.trunc %3 : i64 to i1 - %5 = llvm.or %0, %0 : i64 - %6 = llvm.xor %3, %5 : i64 - %7 = llvm.select %4, %1, %6 : i1, i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32) -> i32 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.zext %arg1 : i32 to i64 - %2 = llvm.trunc %1 : i64 to i1 - %3 = llvm.zext %2 : i1 to i64 - %4 = llvm.zext %2 : i1 to i64 - %5 = llvm.urem %3, %4 : i64 - %6 = llvm.urem %0, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.sdiv %arg0, %arg0 : i64 - %1 = llvm.xor %arg0, %0 : i64 - %2 = llvm.urem %arg0, %1 : i64 - %3 = llvm.ashr %arg1, %arg0 : i64 - %4 = llvm.or %2, %3 : i64 - %5 = llvm.trunc %4 : i64 to i1 - %6 = llvm.zext %5 : i1 to i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.urem %arg1, %arg2 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.sext %1 : i32 to i64 - %3 = llvm.udiv %arg0, %arg2 : i64 - %4 = llvm.urem %2, %3 : i64 - %5 = llvm.lshr %arg0, %4 : i64 - %6 = llvm.sdiv %5, %arg2 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.zext %arg0 : i1 to i64 - %1 = llvm.xor %0, %0 : i64 - %2 = llvm.xor %0, %1 : i64 - %3 = llvm.and %2, %1 : i64 - %4 = llvm.xor %arg1, %0 : i64 - %5 = llvm.icmp "sge" %3, %4 : i64 - %6 = llvm.sext %5 : i1 to i64 - %7 = llvm.sdiv %6, %arg2 : i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.udiv %arg0, %arg1 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.zext %1 : i32 to i64 - %3 = llvm.lshr %arg2, %arg0 : i64 - %4 = llvm.lshr %2, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - %6 = llvm.zext %5 : i32 to i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { - %0 = llvm.and %arg0, %arg0 : i64 - %1 = llvm.lshr %0, %0 : i64 - %2 = llvm.select %arg1, %arg2, %arg0 : i1, i64 - %3 = llvm.icmp "eq" %arg0, %2 : i64 - %4 = llvm.sext %3 : i1 to i64 - %5 = llvm.sdiv %4, %arg0 : i64 - %6 = llvm.ashr %2, %5 : i64 - %7 = llvm.icmp "ne" %1, %6 : i64 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.urem %arg0, %arg1 : i64 - %1 = llvm.srem %arg1, %arg2 : i64 - %2 = llvm.ashr %1, %1 : i64 - %3 = llvm.udiv %0, %2 : i64 - %4 = llvm.or %0, %3 : i64 - %5 = llvm.urem %arg2, %1 : i64 - %6 = llvm.udiv %5, %5 : i64 - %7 = llvm.lshr %4, %6 : i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.icmp "ult" %arg0, %arg0 : i64 - %1 = llvm.zext %0 : i1 to i64 - %2 = llvm.or %arg0, %1 : i64 - %3 = llvm.ashr %2, %arg1 : i64 - %4 = llvm.udiv %3, %arg1 : i64 - %5 = llvm.sdiv %4, %arg2 : i64 - %6 = llvm.sdiv %5, %arg0 : i64 - %7 = llvm.icmp "slt" %4, %6 : i64 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.ashr %arg0, %arg1 : i64 - %1 = llvm.udiv %arg2, %arg1 : i64 - %2 = llvm.or %arg0, %1 : i64 - %3 = llvm.lshr %0, %2 : i64 - %4 = llvm.ashr %3, %arg1 : i64 - %5 = llvm.or %3, %4 : i64 - %6 = llvm.trunc %5 : i64 to i32 - %7 = llvm.zext %6 : i32 to i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.lshr %arg0, %arg0 : i64 - %1 = llvm.xor %arg0, %0 : i64 - %2 = llvm.trunc %1 : i64 to i32 - %3 = llvm.zext %2 : i32 to i64 - %4 = llvm.xor %3, %3 : i64 - %5 = llvm.and %3, %arg1 : i64 - %6 = llvm.lshr %4, %5 : i64 - %7 = llvm.srem %6, %5 : i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i32 { - %0 = llvm.sext %arg1 : i32 to i64 - %1 = llvm.icmp "ult" %arg0, %0 : i64 - %2 = llvm.select %1, %0, %arg2 : i1, i64 - %3 = llvm.trunc %2 : i64 to i32 - %4 = llvm.zext %3 : i32 to i64 - %5 = llvm.lshr %2, %arg0 : i64 - %6 = llvm.ashr %4, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { - %0 = llvm.urem %arg1, %arg2 : i64 - %1 = llvm.udiv %arg1, %0 : i64 - %2 = llvm.sdiv %0, %1 : i64 - %3 = llvm.udiv %arg0, %2 : i64 - %4 = llvm.icmp "ugt" %3, %1 : i64 - %5 = llvm.sext %4 : i1 to i64 - %6 = llvm.srem %5, %1 : i64 - %7 = llvm.lshr %5, %6 : i64 - return %7 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.udiv %arg1, %arg2 : i64 - %1 = llvm.icmp "sle" %0, %arg0 : i64 - %2 = llvm.sext %1 : i1 to i64 - %3 = llvm.sdiv %2, %2 : i64 - %4 = llvm.trunc %3 : i64 to i32 - %5 = llvm.sext %4 : i32 to i64 - %6 = llvm.ashr %arg0, %5 : i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { - %0 = llvm.ashr %arg0, %arg1 : i64 - %1 = llvm.or %arg0, %0 : i64 - %2 = llvm.and %arg2, %arg2 : i64 - %3 = llvm.sdiv %arg1, %2 : i64 - %4 = llvm.sdiv %3, %2 : i64 - %5 = llvm.xor %4, %1 : i64 - %6 = llvm.xor %arg2, %5 : i64 - %7 = llvm.icmp "uge" %1, %6 : i64 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { - %0 = llvm.zext %arg3 : i32 to i64 - %1 = llvm.srem %arg2, %0 : i64 - %2 = llvm.or %arg1, %1 : i64 - %3 = llvm.sdiv %arg0, %0 : i64 - %4 = llvm.sdiv %2, %3 : i64 - %5 = llvm.urem %4, %arg1 : i64 - %6 = llvm.lshr %arg0, %5 : i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i1, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { - %0 = llvm.lshr %arg1, %arg1 : i64 - %1 = llvm.udiv %arg1, %arg2 : i64 - %2 = llvm.and %0, %1 : i64 - %3 = llvm.trunc %2 : i64 to i1 - %4 = llvm.sext %arg3 : i32 to i64 - %5 = llvm.select %3, %2, %4 : i1, i64 - %6 = llvm.select %arg0, %arg1, %5 : i1, i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.srem %arg0, %arg0 : i64 - %1 = llvm.trunc %0 : i64 to i32 - %2 = llvm.sext %1 : i32 to i64 - %3 = llvm.sdiv %2, %arg1 : i64 - %4 = llvm.sdiv %2, %3 : i64 - %5 = llvm.trunc %4 : i64 to i32 - %6 = llvm.zext %5 : i32 to i64 - %7 = llvm.trunc %6 : i64 to i1 - return %7 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { - %0 = llvm.sext %arg1 : i1 to i64 - %1 = llvm.srem %0, %0 : i64 - %2 = llvm.and %arg0, %1 : i64 - %3 = llvm.udiv %arg0, %arg2 : i64 - %4 = llvm.udiv %3, %3 : i64 - %5 = llvm.udiv %4, %3 : i64 - %6 = llvm.ashr %2, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { - %0 = llvm.icmp "sge" %arg0, %arg1 : i64 - %1 = llvm.select %0, %arg0, %arg2 : i1, i64 - %2 = llvm.or %1, %arg2 : i64 - %3 = llvm.srem %arg2, %arg1 : i64 - %4 = llvm.trunc %3 : i64 to i1 - %5 = llvm.sext %4 : i1 to i64 - %6 = llvm.ashr %2, %5 : i64 - %7 = llvm.trunc %6 : i64 to i32 - return %7 : i32 - } -} -// ----- diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/version_log.txt b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/version_log.txt deleted file mode 100644 index 9431f434b7..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/version_log.txt +++ /dev/null @@ -1 +0,0 @@ -MLIR-fuzz commit hash: 2210c14 diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/README.md b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/README.md deleted file mode 100644 index d797779c2f..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/README.md +++ /dev/null @@ -1,60 +0,0 @@ -# Benchmarks Generation - -### Dependencies - -This evaluation requires LLVM's static compiler (`llc`), either install it through your favourite -package manager, or, if you've built LLVM from source, add the `bin` directory -to your path. - -For example, if you've built LLVM at `~/llvm-project/build`, and you run bash as -your shell, you should run the following before you run the script: - -```bash -export PATH=$PATH:~/llvm-project/build/bin/ -``` - -Our evaluation also depends on [mlir-fuzz](https://github.com/opencompl/mlir-fuzz) to produce the initial synthetic programs, and it needs to be installed to run `generate_multi.py` - - -### How to run - -To generate the initial fuzzed programs, run: -``` -python3 generate_multi.py --num --max_size --min_size -``` - -For each `size` in the interval `[min_size, max_size]`, the script saves to `benchmarks/MLIR_multi` -a single file `out_size.mlir` containing `num` programs. -This will be the starting point of the conversion. - -To generate the remaining benchmarks, run: -``` -uv run generate.py --num --jobs --llvm_opt -``` - -The script `generate.py` populates the folders in `benchmarks` by running the following: -- For each file in `MLIR_multi`, extract `num` single MLIR modules and save them in `benchmarks/MLIR_single/`. Each file containing a single module will have two numbers that remain consistent throughout the lowering (e.g. `size_function_num`, where `size` is the initial program size specified in `generate_multi.py`). -- using `mlir-opt`, convert each of these files containing a single module to the LLVM dialect, save the result in `benchmarks/LLVM/*.ll` - -Then, the scripts lowers all the files using both LLVM and Lean-MLIR, to enable the comparison of the lowered RISCV assembly output. - -*LLVM toolchain* -- using `mlir-translate`, convert the `*.ll` files in LLVMIR, and save the result in `benchmarks/LLVMIR/*.mlir` -- using `llc` with `selectionDAG`, compile the LLVMIR files to the `riscv` backend and save the result in `benchmarks/LLC_ASM_selectiondag/*.s` -- using `llc`, compile the LLVMIR files to the `riscv` backend and save the result in `benchmarks/LLC_ASM_globalisel/*.s` - -*Lean-MLIR toolchain* -- extract the first block `bb0` from the `*.ll` files and save the result in `benchmarks/MLIR_bb0/*.mlir` -- run the Lean-MLIR lowering to RiscV and save the result in `benchmarks/LEANMLIR_ASM/*.mlir`, potentially in parallel by setting the `jobs` input argument (the default number is 1). -- run the Lean-MLIR optimized lowering to RiscV and save the result in `benchmarks/LEANMLIR_ASM_opt/*.mlir`, potentially in parallel by setting the `jobs` input argument (the default number is 1). -- remove `unrealized_cast` operations from the assembly file using XDSL, save the result in `benchmarks/XDSL_no_casts/*.mlir` -- remove `unrealized_cast` operations from the optimized assembly file using XDSL, save the result in `benchmarks/XDSL_no_casts_opt/*.mlir` -- perform register allocation using XDSL, save the result in `benchmarks/XDSL_reg_alloc/*.mlir` -- perform register allocation using XDSL on optimized assembly, save the result in `benchmarks/XDSL_reg_alloc_opt/*.mlir` -- lower to RISCV assembly using XDSL, save the result in `benchmarks/XDSL_ASM/*.mlir` -- lower optimized assembly to RISCV using XDSL, save the result in `benchmarks/XDSL_ASM_opt/*.mlir` - -Each step in `generate.py` produces a log file, which one can retrieve in `logs/`. The names in the log file contain the function and the pass that outputted that file. - -### How to reuse and customize -- to add new MLIR tests, add a file to `benchmarks/MLIR_multi`. Files in this folder at the moment are named according to the followign convention: `out_` + number of MLIR modules in the file + `.mlir`. \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/create_func.py b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/create_func.py deleted file mode 100644 index 2a7c41cfa3..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/create_func.py +++ /dev/null @@ -1,58 +0,0 @@ -import sys - -from xdsl.rewriter import Rewriter -from xdsl.xdsl_opt_main import xDSLOptMain -from xdsl.rewriter import InsertPoint -from xdsl.ir import Block - -from xdsl.dialects.builtin import ModuleOp, FunctionType -from xdsl.dialects import llvm -from xdsl.dialects import func - - -class MyOptMain(xDSLOptMain): - def process_module(self, module: ModuleOp): - module_args_types = module.body.block.arg_types - return_op = module.body.block.ops.last - return_op_types = [op.type for op in return_op.operands] - assert isinstance(return_op, llvm.ReturnOp) - - new_region = Rewriter().move_region_contents_to_new_regions(module.body) - func_type = FunctionType.from_lists(module_args_types, return_op_types) - new_func = func.FuncOp("main", func_type) - module.body.add_block(Block()) - Rewriter().insert_op(new_func, InsertPoint.at_end(module.body.block)) - new_func.regions = [new_region] - - Rewriter().replace_op(return_op, func.ReturnOp(*return_op.operands)) - - def run(self): - chunks, file_extension = self.prepare_input() - output_stream = self.prepare_output() - - try: - for i, (chunk, offset) in enumerate(chunks): - try: - if i > 0: - output_stream.write("// -----\n") - module = self.parse_chunk(chunk, file_extension, offset) - - if module is not None: - self.process_module(module) - output_stream.write(self.output_resulting_program(module)) - output_stream.flush() - finally: - chunk.close() - finally: - if output_stream is not sys.stdout: - output_stream.close() - - exit(0) - - -def main(): - MyOptMain().run() - - -if "__main__" == __name__: - main() diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/generate.py b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/generate.py deleted file mode 100755 index f36a89a510..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/generate.py +++ /dev/null @@ -1,635 +0,0 @@ -#!/usr/bin/env -S uv run --script -# -# /// script -# requires-python = ">=3.12" -# dependencies = ["xdsl"] -# -# [tool.uv.sources] -# xdsl = { git = "https://github.com/luisacicolini/xdsl.git", rev = "5e00c8487235fb56db9183bc3434b44baa4151cf" } -# /// - - -import sys -import os -import shutil -import subprocess -import re -import argparse -import concurrent.futures - - -ROOT_DIR_PATH = ( - subprocess.check_output(["git", "rev-parse", "--show-toplevel"]) - .decode("utf-8") - .strip() -) - -TIMEOUT_SEC = 1800 - -LLC_GLOBALISEL_ASM_DIR_PATH = ( - f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LLC_GlobalISel_ASM/" -) - -LLVM_DIR_PATH = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LLVM/" -LLVMIR_DIR_PATH = ( - f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LLVMIR/" -) -MLIR_bb0_DIR_PATH = ( - f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_bb0/" -) -MLIR_bb0_veIR_DIR_PATH = ( - f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_bb0_veIR/" -) -MLIR_single_DIR_PATH = ( - f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_single/" -) -MLIR_multi_DIR_PATH = ( - f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/" -) -isolated_instructions_DIR_PATH = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/" -LLC_ASM_selectiondag_DIR_PATH = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LLC_ASM_selectiondag/" -LLC_ASM_globalisel_DIR_PATH = ( - f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LLC_ASM_globalisel/" -) -LEANMLIR_ASM_DIR_PATH = ( - f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LEANMLIR_ASM/" -) -LEANMLIR_ASM_opt_DIR_PATH = ( - f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LEANMLIR_ASM_opt/" -) -XDSL_ASM_DIR_PATH = ( - f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/XDSL_ASM/" -) -XDSL_opt_ASM_DIR_PATH = ( - f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/XDSL_opt_ASM/" -) -XDSL_FUNC_ASM_DIR_PATH = ( - f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/XDSL_FUNC/" -) -XDSL_FUNC_opt_ASM_DIR_PATH = ( - f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/XDSL_FUNC_opt/" -) -LOGS_DIR_PATH = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/logs/" - - -AUTOGEN_DIR_PATHS = [ - LLVM_DIR_PATH, - LLVMIR_DIR_PATH, - MLIR_bb0_DIR_PATH, - MLIR_bb0_veIR_DIR_PATH, - MLIR_single_DIR_PATH, - LLC_ASM_selectiondag_DIR_PATH, - LLC_ASM_globalisel_DIR_PATH, - # XDSL_FUNC_ASM_DIR_PATH, - XDSL_FUNC_opt_ASM_DIR_PATH, - # LEANMLIR_ASM_DIR_PATH, - # XDSL_ASM_DIR_PATH, - LOGS_DIR_PATH, - LEANMLIR_ASM_opt_DIR_PATH, - XDSL_opt_ASM_DIR_PATH, -] - - -def setup_benchmarking_directories(): - """ - Create clean directories to store the benchmarks. - """ - for directory in AUTOGEN_DIR_PATHS: - if not os.path.exists(directory): - os.makedirs(directory) - else: - shutil.rmtree(directory) - os.makedirs(directory) - - -def replace_hyphens_in_variables(file_path): - """ - Reads a file, replaces hyphens (-) with underscores (_) within - MLIR variable names (starting with %), and overwrites the file. - """ - - if not os.path.exists(file_path): - print(f"Error: File not found at {file_path}") - return - - pattern = r"(%[a-zA-Z0-9_-]+)" - - def variable_replacer(match): - """Replace all hyphens with underscores in the matched variable name.""" - variable_name = match.group(0) - if "-" in variable_name: - return variable_name.replace("-", "_") - return variable_name - - try: - with open(file_path, "r") as f: - original_content = f.read() - - modified_content = re.sub(pattern, variable_replacer, original_content) - with open(file_path, "w") as f: - f.write(modified_content) - - except IOError as e: - print(f"Error processing file {file_path}: {e}") - except Exception as e: - print(f"An unexpected error occurred: {e}") - - -def run_command(cmd, log_file, timeout=TIMEOUT_SEC): - try: - ret_code = subprocess.Popen( - cmd, cwd=ROOT_DIR_PATH, stdout=log_file, stderr=log_file, shell=True - ).wait(timeout=timeout) - return ret_code - except subprocess.TimeoutExpired: - log_file.truncate(0) - log_file.write(f"timeout of {timeout} seconds reached\n") - print(f"{log_file} - timeout of {timeout} seconds reached") - - -def extract_helper(input_file, output_base, max_functions, base_name): - f = open(input_file, "r") - all_lines = f.readlines() - function_count = 0 - curr_program = [] - brackets_count = 0 - for line in all_lines: - if "{" in line: - brackets_count += 1 - if brackets_count == 2: - # remove indentation - curr_program.append(line[2:]) - if "}" in line: - brackets_count -= 1 - if brackets_count == 1 and len(curr_program) > 0: - # write file - out_f = open(output_base + f"{base_name}{function_count}.mlir", "w") - out_f.writelines(curr_program) - out_f.write("\n") - out_f.close() - curr_program = [] - function_count += 1 - curr_program = [] - if function_count >= max_functions: - print(f"Reached maximum of {max_functions} functions. Stopping extraction.") - break - - -def extract(input_dir, output_base, max_functions, type): - if type: - for filename in os.listdir(input_dir): - input_file = os.path.join(input_dir, filename) - instruction_name = "".join(filename.split(".")[0]) - extract_helper( - input_file, output_base, max_functions, f"{instruction_name}_" - ) - else: - size = input_dir.split("_")[-1].split(".")[0] - base_name = f"{size}_function_" - extract_helper(input_dir, output_base, max_functions, base_name) - - -def MLIR_opt_arith_llvm(input_file, output_file, log_file, pass_dict): - """ - Run mlir-opt and convert a file into LLVM dialect. - """ - cmd_base = ( - "mlir-opt -convert-arith-to-llvm -convert-func-to-llvm --mlir-print-op-generic " - ) - cmd = cmd_base + input_file + " -o " + output_file - ret_code = run_command(cmd, log_file) - pass_dict[output_file] = ret_code - - -def MLIR_translate_llvmir(input_file, output_file, log_file, pass_dict): - """ - Run mlir-translate and translate a file from LLVM dialect to LLVMIR. - """ - cmd_base = "mlir-translate --mlir-to-llvmir " - cmd = cmd_base + input_file + " -o " + output_file - ret_code = run_command(cmd, log_file) - pass_dict[output_file] = ret_code - - -def LLC_compile_riscv_selectiondag(input_file, output_file, log_file, pass_dict, opt): - """ - Compile LLVMIR to RISCV assembly with llc. - """ - cmd_base = ( - "llc -march=riscv64 -mcpu=generic-rv64 -mattr=+m,+b -filetype=asm " + opt + " " - ) - cmd = cmd_base + input_file + " -o " + output_file - ret_code = run_command(cmd, log_file) - pass_dict[output_file] = ret_code - - -def LLC_compile_riscv_globalisel(input_file, output_file, log_file, pass_dict, opt): - """ - Compile LLVMIR to RISCV assembly with llc using the GlobalISel framework. - """ - cmd_base = ( - "llc -march=riscv64 -mcpu=generic-rv64 --global-isel -mattr=+m,+b -filetype=asm " - + opt - + " " - ) - cmd = cmd_base + input_file + " -o " + output_file - ret_code = run_command(cmd, log_file) - pass_dict[output_file] = ret_code - - -def extract_bb0(input_file, output_file, log_file): - """ - Extract the first basic block from the MLIR file. - """ - o_f = open(output_file, "w") - in_block = False - try: - with open(input_file, "r") as f: - for line in f: - line = line.strip() - if "^bb0(" in line: - in_block = True - o_f.write("{\n") - o_f.write(line + "\n") - continue - if in_block: - o_f.write(line + "\n") - if '"llvm.return"' in line: - o_f.write("}" + "\n") - o_f.close() - return - - except FileNotFoundError: - print(f"Error: The file '{input_file}' was not found.", file=log_file) - sys.exit(1) - -def extract_bb0_veIR(input_file, output_file, log_file): - """ - Extract the first basic block from the MLIR file, print it in a `buildin.module`. - """ - o_f = open(output_file, "w") - o_f.write("\"builtin.module\"() ({\n") - in_block = False - try: - with open(input_file, "r") as f: - for line in f: - line = line.strip() - if "^bb0(" in line: - in_block = True - o_f.write("\t" + line + "\n") - continue - if in_block: - o_f.write("\t" + line + "\n") - if '"llvm.return"' in line: - o_f.write("}) : () -> ()\n") - o_f.close() - return - - except FileNotFoundError: - print(f"Error: The file '{input_file}' was not found.", file=log_file) - sys.exit(1) - - -def LAKE_compile_riscv64(jobs, pass_dict): - """ - Lower the input file to RISCV with Lean-MLIR, using multiple threads. - """ - with concurrent.futures.ThreadPoolExecutor(max_workers=jobs) as executor: - futures = {} - - for filename in os.listdir(MLIR_bb0_DIR_PATH): - input_file = os.path.join(MLIR_bb0_DIR_PATH, filename) - basename, _ = os.path.splitext(filename) - output_file = os.path.join(LEANMLIR_ASM_DIR_PATH, basename + ".mlir") - log_file = open(LOGS_DIR_PATH + basename + "_lake.mlir", "w") - cmd_base = f"cd {ROOT_DIR_PATH}; lake exe opt --passriscv64 " - cmd = cmd_base + input_file + " > " + output_file - future = executor.submit(run_command, cmd, log_file) - futures[future] = output_file - - total = len(futures) - for idx, future in enumerate(concurrent.futures.as_completed(futures)): - file_path = futures[future] - ret_code = future.result() - pass_dict[file_path] = ret_code - percentage = (float(idx) / float(total)) * 100 - print(f"compiling with lean-mlir {percentage:.2f}%") - - -def LAKE_compile_riscv64_opt(jobs, pass_dict): - """ - Lower the input file to RISCV with Lean-MLIR, using multiple threads. - """ - with concurrent.futures.ThreadPoolExecutor(max_workers=jobs) as executor: - futures = {} - - for filename in os.listdir(MLIR_bb0_DIR_PATH): - input_file = os.path.join(MLIR_bb0_DIR_PATH, filename) - basename, _ = os.path.splitext(filename) - output_file = os.path.join(LEANMLIR_ASM_opt_DIR_PATH, basename + ".mlir") - log_file = open(LOGS_DIR_PATH + basename + "_lake.mlir", "w") - cmd_base = f"cd {ROOT_DIR_PATH}; lake exe opt --passriscv64_optimized " - cmd = cmd_base + input_file + " > " + output_file - future = executor.submit(run_command, cmd, log_file) - futures[future] = output_file - - total = len(futures) - for idx, future in enumerate(concurrent.futures.as_completed(futures)): - file_path = futures[future] - ret_code = future.result() - pass_dict[file_path] = ret_code - percentage = (float(idx) / float(total)) * 100 - print(f"compiling with lean-mlir (optimized pass): {percentage:.2f}%") - - -def XDSL_create_func(input_file, output_file, log_file, pass_dict): - """ - Remove unrealized casts from the RISCV64 dialect MLIR files with xdsl. - """ - cmd_base = f"python3 {ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/create_func.py " - cmd = cmd_base + input_file + " > " + output_file - ret_code = run_command(cmd, log_file) - pass_dict[output_file] = ret_code - - -def XDSL_reg_alloc(input_file, output_file, log_file, pass_dict): - """ - Remove unrealized casts from the RISCV64 dialect MLIR files with xdsl. - """ - try: - from xdsl.xdsl_opt_main import xDSLOptMain - - xdsl_opt_main = xDSLOptMain( - args=f"{input_file} -p convert-func-to-riscv-func,reconcile-unrealized-casts,riscv-allocate-registers{{force-infinite=true}},riscv-allocate-infinite-registers,canonicalize-register-allocation -t riscv-asm -o {output_file}".split() - ) - xdsl_opt_main.run() - # cmd = cmd_base + input_file + " > " + output_file - # ret_code = run_command(cmd, log_file) - pass_dict[output_file] = 1 - except Exception as e: - print(f"XDSL_reg_alloc failed for {input_file} with error: {e}", file=log_file) - pass_dict[output_file] = 0 - - -def generate_benchmarks(num, jobs, llvm_opt, compare_lowering_patterns=False): - setup_benchmarking_directories() - - if compare_lowering_patterns: - print( - f"Using instruction-specific files from: {isolated_instructions_DIR_PATH}" - ) - extract( - isolated_instructions_DIR_PATH, - MLIR_single_DIR_PATH, - num, - compare_lowering_patterns, - ) - else: - # extract mlir blocks and put them all in separate files - # for each file with programs of a certain size - for file in os.listdir(MLIR_multi_DIR_PATH): - input_file = os.path.join(MLIR_multi_DIR_PATH, file) - replace_hyphens_in_variables(input_file) - extract(input_file, MLIR_single_DIR_PATH, num, compare_lowering_patterns) - - MLIR_opt_file2ret = dict() - idx = 0 - # Run mlir-opt and convert into LLVM dialect - for filename in os.listdir(MLIR_single_DIR_PATH): - input_file = os.path.join(MLIR_single_DIR_PATH, filename) - basename, _ = os.path.splitext(filename) - output_file = os.path.join(LLVM_DIR_PATH, basename + ".ll") - log_file = open(os.path.join(LOGS_DIR_PATH, basename + "_mlir_opt.log"), "w") - MLIR_opt_arith_llvm(input_file, output_file, log_file, MLIR_opt_file2ret) - idx += 1 - percentage = (float(idx) / float(len(os.listdir(MLIR_single_DIR_PATH)))) * 100 - print(f"translating to LLVM with mlir-opt: {percentage:.2f}%") - - MLIR_translate_file2ret = dict() - idx = 0 - # Run mlir-translate and convert LLVM into LLVMIR - for filename in os.listdir(LLVM_DIR_PATH): - input_file = os.path.join(LLVM_DIR_PATH, filename) - # only run the lowering if the previous pass was successful: - if MLIR_opt_file2ret[input_file] == 0: - basename, _ = os.path.splitext(filename) - output_file = os.path.join(LLVMIR_DIR_PATH, basename + ".mlir") - log_file = open( - os.path.join(LOGS_DIR_PATH, basename + "_mlir_translate.log"), "w" - ) - MLIR_translate_llvmir( - input_file, output_file, log_file, MLIR_translate_file2ret - ) - idx += 1 - percentage = (float(idx) / float(len(MLIR_opt_file2ret))) * 100 - print(f"translating to LLVMIR with mlir-translate: {percentage:.2f}%") - - LLC_file2ret = dict() - idx = 0 - # Use llc with `selectionDAG` to compile LLVMIR into RISCV - for filename in os.listdir(LLVMIR_DIR_PATH): - input_file = os.path.join(LLVMIR_DIR_PATH, filename) - # only run the lowering if the previous pass was successful: - if MLIR_translate_file2ret[input_file] == 0: - basename, _ = os.path.splitext(filename) - - if llvm_opt == "default": - output_file = os.path.join( - LLC_ASM_selectiondag_DIR_PATH, basename + ".s" - ) - log_file = open( - os.path.join(LOGS_DIR_PATH, basename + "_selectiondag_llc.log"), - "w", - ) - LLC_compile_riscv_selectiondag( - input_file, output_file, log_file, LLC_file2ret, "" - ) - else: - output_file = os.path.join( - LLC_ASM_selectiondag_DIR_PATH, basename + "_" + llvm_opt + ".s" - ) - log_file = open( - os.path.join( - LOGS_DIR_PATH, - basename + "_selectiondag_llc" + "_" + llvm_opt + ".log", - ), - "w", - ) - LLC_compile_riscv_selectiondag( - input_file, output_file, log_file, LLC_file2ret, "-" + llvm_opt - ) - idx += 1 - percentage = (float(idx) / float(len(MLIR_translate_file2ret))) * 100 - print(f"compiling with llc (selectionDAG {llvm_opt}): {percentage:.2f}%") - - LLC_GLOBALISEL_file2ret = dict() - idx = 0 - # Use llc with `GlobalISel` to compile LLVMIR into RISCV - for filename in os.listdir(LLVMIR_DIR_PATH): - input_file = os.path.join(LLVMIR_DIR_PATH, filename) - # only run the lowering if the previous pass was successful: - if MLIR_translate_file2ret[input_file] == 0: # previous pass succeded - if llvm_opt == "default": - basename, _ = os.path.splitext(filename) - output_file = os.path.join(LLC_ASM_globalisel_DIR_PATH, basename + ".s") - log_file = open( - os.path.join(LOGS_DIR_PATH, basename + "_globalisel_llc.log"), - "w", - ) - LLC_compile_riscv_globalisel( - input_file, output_file, log_file, LLC_GLOBALISEL_file2ret, "" - ) - else: - basename, _ = os.path.splitext(filename) - output_file = os.path.join( - LLC_ASM_globalisel_DIR_PATH, basename + "_" + llvm_opt + ".s" - ) - log_file = open( - os.path.join( - LOGS_DIR_PATH, - basename + "_globalisel_llc" + "_" + llvm_opt + ".log", - ), - "w", - ) - LLC_compile_riscv_globalisel( - input_file, - output_file, - log_file, - LLC_GLOBALISEL_file2ret, - "-" + llvm_opt, - ) - idx += 1 - percentage = (float(idx) / float(len(MLIR_translate_file2ret))) * 100 - print(f"compiling with llc (globalISel {llvm_opt}): {percentage:.2f}%") - - # Extract bb0 - idx = 0 - for filename in os.listdir(LLVM_DIR_PATH): - input_file = os.path.join(LLVM_DIR_PATH, filename) - basename, _ = os.path.splitext(filename) - output_file = os.path.join(MLIR_bb0_DIR_PATH, basename + ".mlir") - output_file_veIR = os.path.join(MLIR_bb0_veIR_DIR_PATH, basename + ".mlir") - log_file = open(os.path.join(LOGS_DIR_PATH, basename + "_bb0_extract.log"), "w") - log_file_veIR = open(os.path.join(LOGS_DIR_PATH, basename + "_bb0_extract_veIR.log"), "w") - extract_bb0(input_file, output_file, log_file) - extract_bb0_veIR(input_file, output_file_veIR, log_file_veIR) - idx += 1 - percentage = (float(idx) / float(len(os.listdir(LLVM_DIR_PATH)))) * 100 - print(f"extracting the first basic block: {percentage:.2f}%") - - # LAKE_file2ret = dict() - # # Run the lean pass in parallel - # LAKE_compile_riscv64(jobs, LAKE_file2ret) - - LAKE_file2ret_opt = dict() - # Run the optimized lean pass in parallel - LAKE_compile_riscv64_opt(jobs, LAKE_file2ret_opt) - - # XDSL_create_func_file2ret = dict() - # idx = 0 - # # Create `func.func` - # for filename in os.listdir(LEANMLIR_ASM_DIR_PATH): - # input_file = os.path.join(LEANMLIR_ASM_DIR_PATH, filename) - # if LAKE_file2ret[input_file] == 0: - # basename, _ = os.path.splitext(filename) - # output_file = os.path.join(XDSL_FUNC_ASM_DIR_PATH, basename + ".mlir") - # log_file = open( - # os.path.join(LOGS_DIR_PATH, basename + "_xdsl_create_func.log"), "w" - # ) - # XDSL_create_func( - # input_file, output_file, log_file, XDSL_create_func_file2ret - # ) - # idx += 1 - # percentage = (float(idx) / float(len(LAKE_file2ret))) * 100 - # print(f"creating func.func module: {percentage:.2f}%") - - XDSL_create_func_file2ret_opt = dict() - idx = 0 - # Create `func.func` - for filename in os.listdir(LEANMLIR_ASM_opt_DIR_PATH): - input_file = os.path.join(LEANMLIR_ASM_opt_DIR_PATH, filename) - if LAKE_file2ret_opt[input_file] == 0: - basename, _ = os.path.splitext(filename) - output_file = os.path.join(XDSL_FUNC_opt_ASM_DIR_PATH, basename + ".mlir") - log_file = open( - os.path.join(LOGS_DIR_PATH, basename + "_xdsl_create_func_opt.log"), "w" - ) - XDSL_create_func( - input_file, output_file, log_file, XDSL_create_func_file2ret_opt - ) - idx += 1 - percentage = (float(idx) / float(len(LAKE_file2ret_opt))) * 100 - print(f"creating func.func module (opt): {percentage:.2f}%") - - # XDSL_reg_alloc_file2ret = dict() - # idx = 0 - # # Register allocation with XDSL - # for filename in os.listdir(XDSL_FUNC_ASM_DIR_PATH): - # input_file = os.path.join(XDSL_FUNC_ASM_DIR_PATH, filename) - # if XDSL_create_func_file2ret[input_file] == 0: - # basename, _ = os.path.splitext(filename) - # output_file = os.path.join(XDSL_ASM_DIR_PATH, basename + ".mlir") - # log_file = open( - # os.path.join(LOGS_DIR_PATH, basename + "_xdsl_reg_alloc.log"), "w" - # ) - # XDSL_reg_alloc(input_file, output_file, log_file, XDSL_reg_alloc_file2ret) - # idx += 1 - # percentage = (float(idx) / float(len(XDSL_create_func_file2ret))) * 100 - # print(f"allocating registers and outputting assembly: {percentage:.2f}%") - - XDSL_reg_alloc_file2ret_opt = dict() - idx = 0 - # Register allocation with XDSL - for filename in os.listdir(XDSL_FUNC_opt_ASM_DIR_PATH): - input_file = os.path.join(XDSL_FUNC_opt_ASM_DIR_PATH, filename) - if XDSL_create_func_file2ret_opt[input_file] == 0: - basename, _ = os.path.splitext(filename) - output_file = os.path.join(XDSL_opt_ASM_DIR_PATH, basename + ".mlir") - log_file = open( - os.path.join(LOGS_DIR_PATH, basename + "_xdsl_reg_alloc.log"), "w" - ) - XDSL_reg_alloc( - input_file, output_file, log_file, XDSL_reg_alloc_file2ret_opt - ) - idx += 1 - percentage = (float(idx) / float(len(XDSL_create_func_file2ret_opt))) * 100 - print(f"allocating registers and outputting assembly (opt): {percentage:.2f}%") - - -def main(): - parser = argparse.ArgumentParser( - prog="generate", - description="Generate a new set of benchmarks in all the representations, from MLIR to RISCV assembly.", - ) - - parser.add_argument( - "-n", "--num", type=int, default=100, help="Number of benchmarks to generate. " - ) - - parser.add_argument( - "-j", "--jobs", type=int, default=1, help="Parallel jobs for all benchmarks" - ) - - parser.add_argument( - "-llvm", - "--llvm_opt", - help="Optimization level for LLVM.", - choices=["O3", "O2", "O1", "O0", "default", "all"], - default="default", - ) - - parser.add_argument( - "-l", - "--instruction_lowering", - help="Create files for instruction lowering patterns comparison.", - action="store_true", - default=False, - ) - - args = parser.parse_args() - - generate_benchmarks(args.num, args.jobs, args.llvm_opt, args.instruction_lowering) - - -if __name__ == "__main__": - main() diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/generate_multi.py b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/generate_multi.py deleted file mode 100644 index aff162dc17..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/generate_multi.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env python3 - -import subprocess -import os -import shutil -import argparse - -MLIR_fuzz_DIR_PATH = "~/mlir-fuzz" - -ROOT_DIR_PATH = ( - subprocess.check_output(["git", "rev-parse", "--show-toplevel"]) - .decode("utf-8") - .strip() -) - -MLIR_multi_DIR_PATH = ( - f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/" -) - - -def create_version_log(): - """ - Checks the git hash of `mlir-fuzz` and saves it to `MLIR_multi/version_log.txt`. - """ - - git_command = ["git", "rev-parse", "--short", "HEAD"] - external_repo = os.path.expanduser(MLIR_fuzz_DIR_PATH) - result = subprocess.run( - git_command, cwd=external_repo, capture_output=True, text=True, check=True - ) - - commit_hash = result.stdout.strip() - - log_file_path = os.path.join(MLIR_multi_DIR_PATH, "version_log.txt") - log_file = open(log_file_path, "w") - log_file.write(f"MLIR-fuzz commit hash: {commit_hash}\n") - log_file.close() - - -def generate_benchmarks(num_programs, min_size, max_size): - if not os.path.exists(MLIR_multi_DIR_PATH): - os.makedirs(MLIR_multi_DIR_PATH) - else: - shutil.rmtree(MLIR_multi_DIR_PATH) - os.makedirs(MLIR_multi_DIR_PATH) - - create_version_log() - - for size in range(min_size, max_size + 1): - output_file = f"{MLIR_multi_DIR_PATH}/output_{size}.mlir" - command = ( - f"{MLIR_fuzz_DIR_PATH}/build/bin/mlir-enumerate {MLIR_fuzz_DIR_PATH}/dialects/llvm.mlir " - + f"--exact-size=1 --max-num-ops={size} --min-constant-value=-50 --max-constant-value=50 --min-num-args=1 --strategy=random --max-programs={num_programs} --constant-kind=none" - + f"> {output_file}" - ) - - print(f"Generating benchmarks of size {size} into {output_file}") - print(command) - os.system(command) - - -def main(): - parser = argparse.ArgumentParser( - prog="generate", - description="Generate a new set of benchmarks in all the representations, from MLIR to RISCV assembly.", - ) - - parser.add_argument( - "--min_size", - type=int, - help="Min #ops of the synthesized programs. ", - ) - - parser.add_argument( - "--max_size", - type=int, - help="Max #ops of the synthesized programs. ", - ) - - parser.add_argument( - "--num", - type=int, - help="#programs for each size in the [min_size, max_size] interval. ", - ) - - args = parser.parse_args() - generate_benchmarks(args.num, args.min_size, args.max_size) - - -if __name__ == "__main__": - main() diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/README.md b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/README.md deleted file mode 100644 index 5bd7d82bbe..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# Benchmarks Generation - -### Dependencies - -This evaluation relies on dependencies from both `Evaluation/benchmarks` and `Evaluation/mca-analysis`. Therefore `llc` and `evallib` must be in the path. Evallib is added to the path in the given `run_comparison.sh` script. - -### How to run - -Use the `run_comparison.sh` script to run the comparisons. First make the script executable by: - -```bash -chmod +x ./run_comparison.sh -``` - -Then run the script by: -```bash -./run_comparison.sh -``` - -The results are logged in the `comparison.log` file. - -### Results -The comparison script performs a comprehensive analysis of instruction lowering patterns across multiple compilers and optimization levels, organized into three distinct phases. - -Phase 1: LLVM Compiler Consistency Check - The script begins by comparing SelectionDAG and GlobalISel. For each instruction variant, it examines all optimization levels (O0, O1, O2, O3) to verify consistency within each compiler. This internal consistency check ensures that the instruction lowering pattern remains stable across different optimization levels within the same compiler backend. -Phase 2: Cross-Compiler Comparison (LLVM) - After that, the script performs a cross-compiler comparison between SelectionDAG and GlobalISel outputs. For each optimization level, it compares the generated instruction sequences from both frameworks. This comparison reveals whether the two instruction selection approaches produce identical or different lowering patterns for the same input. -Phase 3: LEAN-MLIR vs LLVM Comparison - Finally, the script compares the LEAN-MLIR compiler outputs against LLVM's results at specific optimization levels. This comparison is performed in two stages: - -Unoptimized comparison: LEAN-MLIR output is compared against O0 outputs from both GlobalISel and SelectionDAG. -Optimized comparison: LEAN-MLIR-opt output is compared against O2 outputs from both GlobalISel and SelectionDAG. diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/compare_lowerings.py b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/compare_lowerings.py deleted file mode 100644 index f72d4cf0de..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/compare_lowerings.py +++ /dev/null @@ -1,440 +0,0 @@ -#!/usr/bin/env python3 - -import os -import re -import sys -import argparse -from pathlib import Path -from collections import defaultdict, Counter -import json -import subprocess -from datetime import datetime - -ROOT_DIR = ( - subprocess.check_output(["git", "rev-parse", "--show-toplevel"]) - .decode("utf-8") - .strip() -) - -MCA_LEANMLIR_DIR = ( - f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LEANMLIR/" -) -MCA_LEANMLIR_opt_DIR = ( - f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LEANMLIR_opt/" -) -MCA_LLVM_globalisel_DIR = ( - f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LLVM_globalisel/" -) -MCA_LLVM_selectiondag_DIR = ( - f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LLVM_selectiondag/" -) - -LOGS_DIR = f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns" - - -class Logger: - """Logger class to write to both console and file.""" - - def __init__(self, log_file): - self.log_file = log_file - self.file_handle = None - - def __enter__(self): - # Create logs directory if it doesn't exist - os.makedirs(os.path.dirname(self.log_file), exist_ok=True) - self.file_handle = open(self.log_file, 'w') - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - if self.file_handle: - self.file_handle.close() - - def log(self, message): - """Write message to both console and file.""" - print(message) - if self.file_handle: - self.file_handle.write(message + '\n') - self.file_handle.flush() - - -def parse_instructions(filename): - """ - Parse instructions from a compiler output file. - - Args: - filename: Path to the .out file - - Returns: - List of instruction names - """ - instructions = [] - in_instruction_section = False - - try: - with open(filename, 'r') as f: - for line in f: - if '[0] [1] [2] [3] [4] [5] [6] [7] Instructions:' in line: - in_instruction_section = True - continue - if in_instruction_section and line.strip(): - parts = line.split() - if len(parts) > 8: - instruction = parts[8] # inst name is in 9th column - instructions.append(instruction) - except FileNotFoundError: - print(f"Warning: File not found: {filename}") - return [] - except Exception as e: - print(f"Error parsing {filename}: {e}") - return [] - - return instructions - - -def collect_results_lean(base_dir): - results = {} - - if not os.path.exists(base_dir): - print(f"Warning: Directory not found: {base_dir}") - return results - - for filename in os.listdir(base_dir): - filepath = os.path.join(base_dir, filename) - basename = os.path.basename(filename) - pattern = r'llvm_(\w+)_(\d+)\.out' - match = re.match(pattern, basename) - - if match: - instruction_name = match.group(1) - variant = int(match.group(2)) - - instructions = parse_instructions(filepath) - - if instruction_name not in results: - results[instruction_name] = {} - - results[instruction_name][variant] = instructions - - return results - - - -def collect_results_llvm(base_dir): - results = {} - - if not os.path.exists(base_dir): - print(f"Warning: Directory not found: {base_dir}") - return results - - for filename in os.listdir(base_dir): - filepath = os.path.join(base_dir, filename) - basename = os.path.basename(filename) - pattern = r'llvm_(\w+)_(\d+)_(O[0-3]|default)\.out' - match = re.match(pattern, basename) - - if match: - instruction_name = match.group(1) - variant = int(match.group(2)) - opt_level = match.group(3) - - instructions = parse_instructions(filepath) - - if instruction_name not in results: - results[instruction_name] = {} - if variant not in results[instruction_name]: - results[instruction_name][variant] = {} - - results[instruction_name][variant][opt_level] = instructions - - return results - - -def log_instruction_diff(logger, instructions_list, labels): - """ - Log detailed differences between instruction lists. - - Args: - logger: Logger instance - instructions_list: List of instruction lists to compare - labels: Labels for each instruction list - """ - max_len = max(len(insts) for insts in instructions_list) - - logger.log("\n Instruction-by-instruction comparison:") - logger.log(" " + "-" * 80) - - # Print header - header = f" {'Index':<8}" - for label in labels: - header += f"{label:<25}" - logger.log(header) - logger.log(" " + "-" * 80) - - # Compare instruction by instruction - for i in range(max_len): - row = f" {i:<8}" - instructions_at_i = [] - - for insts in instructions_list: - if i < len(insts): - inst = insts[i] - instructions_at_i.append(inst) - row += f"{inst:<25}" - else: - instructions_at_i.append(None) - row += f"{'':<25}" - - # Highlight if instructions differ at this position - if len(set(inst for inst in instructions_at_i if inst is not None)) > 1: - logger.log(row + " DIFFERS") - else: - logger.log(row) - - logger.log(" " + "-" * 80) - - # Print summary - logger.log("\n Summary:") - for label, insts in zip(labels, instructions_list): - logger.log(f" {label}: {len(insts)} instructions") - logger.log("") - - -def compare_in_compiler(logger, results, op, var, compiler_name): - """ - Compare instruction sets across optimization levels within a single compiler. - - Args: - logger: Logger instance - results: List of instruction lists for different optimization levels - op: Operation name - var: Variant number - compiler_name: Name of the compiler - """ - all_equal = all(lst == results[0] for lst in results) - - if all_equal: - logger.log(f" ✓ All optimization levels produce the same instructions for " - f"{compiler_name} llvm.{op} variant {var}") - else: - logger.log(f"\n ✗ DIFFERENT instruction sets found across optimization levels for " - f"{compiler_name} llvm.{op} variant {var}") - - # Create labels for each optimization level - opt_levels = ['O0', 'O1', 'O2', 'O3', 'default'][:len(results)] - log_instruction_diff(logger, results, opt_levels) - - -def compare_llvm_compilers(logger, globalisel_results, selectiondag_results): - """ - Compare instruction sets between GlobalISel and SelectionDAG compilers. - """ - logger.log("\n" + "=" * 100) - logger.log("COMPARISON 1: GlobalISel vs SelectionDAG") - logger.log("=" * 100 + "\n") - - for operation in sorted(globalisel_results.keys()): - for variant in sorted(globalisel_results[operation].keys()): - logger.log(f"\n{'─' * 100}") - logger.log(f"Operation: llvm.{operation}, Variant: {variant}") - logger.log(f"{'─' * 100}") - - opt_results_globalisel = [] - opt_results_selectiondag = [] - opt_levels = sorted(globalisel_results[operation][variant].keys()) - - # Compare across optimization levels - for opt_level in opt_levels: - globalisel_insts = globalisel_results[operation][variant][opt_level] - selectiondag_insts = selectiondag_results[operation][variant][opt_level] - - opt_results_globalisel.append(globalisel_insts) - opt_results_selectiondag.append(selectiondag_insts) - - if globalisel_insts == selectiondag_insts: - logger.log(f" ✓ Same instructions at {opt_level}") - else: - logger.log(f"\n ✗ DIFFERENT instructions at {opt_level}") - log_instruction_diff( - logger, - [globalisel_insts, selectiondag_insts], - [f"GlobalISel-{opt_level}", f"SelectionDAG-{opt_level}"] - ) - - # Compare within each compiler across optimization levels - logger.log("") - compare_in_compiler(logger, opt_results_globalisel, operation, variant, "GlobalISel") - compare_in_compiler(logger, opt_results_selectiondag, operation, variant, "SelectionDAG") - - -def compare_lean_vs_llvm(logger, leanmlir_results, leanmlir_opt_results, - globalisel_results, selectiondag_results): - """ - Compare LEAN compilers with LLVM compilers. - - LEANMLIR vs O0 of GlobalISel and SelectionDAG - - LEANMLIR_opt vs O2 of GlobalISel and SelectionDAG - """ - logger.log("\n" + "=" * 100) - logger.log("COMPARISON 2: LEANMLIR vs LLVM at O0") - logger.log("=" * 100 + "\n") - - # Get all operations that exist in LEANMLIR - for operation in sorted(leanmlir_results.keys()): - for variant in sorted(leanmlir_results[operation].keys()): - logger.log(f"\n{'─' * 100}") - logger.log(f"Operation: llvm.{operation}, Variant: {variant}") - logger.log(f"{'─' * 100}") - - lean_insts = leanmlir_results[operation][variant] - - # Check if this operation/variant exists in LLVM results - if operation not in globalisel_results or variant not in globalisel_results[operation]: - logger.log(f" ✗ Operation/variant not found in GlobalISel results") - continue - - if operation not in selectiondag_results or variant not in selectiondag_results[operation]: - logger.log(f" ✗ Operation/variant not found in SelectionDAG results") - continue - - # Get O0 instructions from LLVM compilers - globalisel_o0 = globalisel_results[operation][variant].get('O0', []) - selectiondag_o0 = selectiondag_results[operation][variant].get('O0', []) - - if not globalisel_o0: - logger.log(f" ✗ O0 results not found for GlobalISel") - if not selectiondag_o0: - logger.log(f" ✗ O0 results not found for SelectionDAG") - - # Compare LEAN vs GlobalISel O0 - if globalisel_o0: - if lean_insts == globalisel_o0: - logger.log(f" ✓ LEANMLIR matches GlobalISel-O0") - else: - logger.log(f"\n ✗ LEANMLIR DIFFERS from GlobalISel-O0") - log_instruction_diff( - logger, - [lean_insts, globalisel_o0], - ["LEANMLIR", "GlobalISel-O0"] - ) - - # Compare LEAN vs SelectionDAG O0 - if selectiondag_o0: - if lean_insts == selectiondag_o0: - logger.log(f" ✓ LEANMLIR matches SelectionDAG-O0") - else: - logger.log(f"\n ✗ LEANMLIR DIFFERS from SelectionDAG-O0") - log_instruction_diff( - logger, - [lean_insts, selectiondag_o0], - ["LEANMLIR", "SelectionDAG-O0"] - ) - - # Compare all three at once for a comprehensive view - if globalisel_o0 and selectiondag_o0: - all_same = lean_insts == globalisel_o0 == selectiondag_o0 - if all_same: - logger.log(f"\n ✓ All three produce IDENTICAL instructions (LEANMLIR, GlobalISel-O0, SelectionDAG-O0)") - else: - logger.log(f"\n Comprehensive comparison of all three:") - log_instruction_diff( - logger, - [lean_insts, globalisel_o0, selectiondag_o0], - ["LEANMLIR", "GlobalISel-O0", "SelectionDAG-O0"] - ) - - logger.log("\n" + "=" * 100) - logger.log("COMPARISON 3: LEANMLIR_opt vs LLVM at O2") - logger.log("=" * 100 + "\n") - - # Get all operations that exist in LEANMLIR_opt - for operation in sorted(leanmlir_opt_results.keys()): - for variant in sorted(leanmlir_opt_results[operation].keys()): - logger.log(f"\n{'─' * 100}") - logger.log(f"Operation: llvm.{operation}, Variant: {variant}") - logger.log(f"{'─' * 100}") - - lean_opt_insts = leanmlir_opt_results[operation][variant] - - # Check if this operation/variant exists in LLVM results - if operation not in globalisel_results or variant not in globalisel_results[operation]: - logger.log(f" ✗ Operation/variant not found in GlobalISel results") - continue - - if operation not in selectiondag_results or variant not in selectiondag_results[operation]: - logger.log(f" ✗ Operation/variant not found in SelectionDAG results") - continue - - # Get O2 instructions from LLVM compilers - globalisel_o2 = globalisel_results[operation][variant].get('O2', []) - selectiondag_o2 = selectiondag_results[operation][variant].get('O2', []) - - if not globalisel_o2: - logger.log(f" ✗ O2 results not found for GlobalISel") - if not selectiondag_o2: - logger.log(f" ✗ O2 results not found for SelectionDAG") - - # Compare LEAN_opt vs GlobalISel O2 - if globalisel_o2: - if lean_opt_insts == globalisel_o2: - logger.log(f" ✓ LEANMLIR_opt matches GlobalISel-O2") - else: - logger.log(f"\n ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2") - log_instruction_diff( - logger, - [lean_opt_insts, globalisel_o2], - ["LEANMLIR_opt", "GlobalISel-O2"] - ) - - # Compare LEAN_opt vs SelectionDAG O2 - if selectiondag_o2: - if lean_opt_insts == selectiondag_o2: - logger.log(f" ✓ LEANMLIR_opt matches SelectionDAG-O2") - else: - logger.log(f"\n ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2") - log_instruction_diff( - logger, - [lean_opt_insts, selectiondag_o2], - ["LEANMLIR_opt", "SelectionDAG-O2"] - ) - - # Compare all three at once for a comprehensive view - if globalisel_o2 and selectiondag_o2: - all_same = lean_opt_insts == globalisel_o2 == selectiondag_o2 - if all_same: - logger.log(f"\n ✓ All three produce IDENTICAL instructions (LEANMLIR_opt, GlobalISel-O2, SelectionDAG-O2)") - else: - logger.log(f"\n Comprehensive comparison of all three:") - log_instruction_diff( - logger, - [lean_opt_insts, globalisel_o2, selectiondag_o2], - ["LEANMLIR_opt", "GlobalISel-O2", "SelectionDAG-O2"] - ) - - -def main(): - log_file = os.path.join(LOGS_DIR, f"comparison.log") - - # Collect results from all compilers - print(f"Collecting results... (log will be saved to {log_file})") - - globalisel_results = collect_results_llvm(MCA_LLVM_globalisel_DIR) - selectiondag_results = collect_results_llvm(MCA_LLVM_selectiondag_DIR) - leanmlir_results = collect_results_lean(MCA_LEANMLIR_DIR) - leanmlir_opt_results = collect_results_lean(MCA_LEANMLIR_opt_DIR) - - # Use logger context manager - with Logger(log_file) as logger: - # Compare LLVM compilers - compare_llvm_compilers(logger, globalisel_results, selectiondag_results) - - # Compare LEAN vs LLVM - compare_lean_vs_llvm(logger, leanmlir_results, leanmlir_opt_results, - globalisel_results, selectiondag_results) - - logger.log("\n" + "=" * 100) - logger.log("END OF ALL COMPARISONS") - logger.log("=" * 100 + "\n") - - print(f"\nLog file saved to: {log_file}") - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/comparison.log b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/comparison.log deleted file mode 100644 index 326c9e36d4..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/comparison.log +++ /dev/null @@ -1,5370 +0,0 @@ - -==================================================================================================== -COMPARISON 1: GlobalISel vs SelectionDAG -==================================================================================================== - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.add, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.add variant 0 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.add variant 0 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.add, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.add variant 1 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.add variant 1 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.add, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.add variant 2 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.add variant 2 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.and, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.and variant 0 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.and variant 0 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.ashr, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.ashr variant 0 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.ashr variant 0 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.icmp variant 0 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.icmp variant 0 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.icmp variant 1 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.icmp variant 1 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.icmp variant 2 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.icmp variant 2 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 3 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.icmp variant 3 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.icmp variant 3 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 4 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.icmp variant 4 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.icmp variant 4 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 5 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.icmp variant 5 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.icmp variant 5 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 6 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.icmp variant 6 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.icmp variant 6 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 7 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.icmp variant 7 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.icmp variant 7 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 8 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.icmp variant 8 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.icmp variant 8 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.mul, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.mul variant 0 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.mul variant 0 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.mul, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.mul variant 1 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.mul variant 1 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.mul, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.mul variant 2 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.mul variant 2 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.or, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.or variant 0 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.or variant 0 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.rem, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.rem variant 0 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.rem variant 0 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sdiv, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.sdiv variant 0 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.sdiv variant 0 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.select, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ DIFFERENT instructions at O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 addi addi - 1 sd sd - 2 andi mv ⚠️ DIFFERS - 3 sd andi ⚠️ DIFFERS - 4 bnez sd ⚠️ DIFFERS - 5 ld bnez ⚠️ DIFFERS - 6 sd ld ⚠️ DIFFERS - 7 ld sd ⚠️ DIFFERS - 8 addi ld ⚠️ DIFFERS - 9 ret addi ⚠️ DIFFERS - 10 ret - -------------------------------------------------------------------------------- - - Summary: - GlobalISel-O0: 10 instructions - SelectionDAG-O0: 11 instructions - - - ✗ DIFFERENT instructions at O1 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index GlobalISel-O1 SelectionDAG-O1 - -------------------------------------------------------------------------------- - 0 mv andi ⚠️ DIFFERS - 1 mv mv - 2 andi bnez ⚠️ DIFFERS - 3 bnez mv ⚠️ DIFFERS - 4 mv ret ⚠️ DIFFERS - 5 ret - -------------------------------------------------------------------------------- - - Summary: - GlobalISel-O1: 6 instructions - SelectionDAG-O1: 5 instructions - - - ✗ DIFFERENT instructions at O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv andi ⚠️ DIFFERS - 1 mv mv - 2 andi bnez ⚠️ DIFFERS - 3 bnez mv ⚠️ DIFFERS - 4 mv ret ⚠️ DIFFERS - 5 ret - -------------------------------------------------------------------------------- - - Summary: - GlobalISel-O2: 6 instructions - SelectionDAG-O2: 5 instructions - - - ✗ DIFFERENT instructions at O3 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index GlobalISel-O3 SelectionDAG-O3 - -------------------------------------------------------------------------------- - 0 mv andi ⚠️ DIFFERS - 1 mv mv - 2 andi bnez ⚠️ DIFFERS - 3 bnez mv ⚠️ DIFFERS - 4 mv ret ⚠️ DIFFERS - 5 ret - -------------------------------------------------------------------------------- - - Summary: - GlobalISel-O3: 6 instructions - SelectionDAG-O3: 5 instructions - - - - ✗ DIFFERENT instruction sets found across optimization levels for GlobalISel llvm.select variant 0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index O0 O1 O2 O3 - -------------------------------------------------------------------------------- - 0 addi mv mv mv ⚠️ DIFFERS - 1 sd mv mv mv ⚠️ DIFFERS - 2 andi andi andi andi - 3 sd bnez bnez bnez ⚠️ DIFFERS - 4 bnez mv mv mv ⚠️ DIFFERS - 5 ld ret ret ret ⚠️ DIFFERS - 6 sd - 7 ld - 8 addi - 9 ret - -------------------------------------------------------------------------------- - - Summary: - O0: 10 instructions - O1: 6 instructions - O2: 6 instructions - O3: 6 instructions - - - ✗ DIFFERENT instruction sets found across optimization levels for SelectionDAG llvm.select variant 0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index O0 O1 O2 O3 - -------------------------------------------------------------------------------- - 0 addi andi andi andi ⚠️ DIFFERS - 1 sd mv mv mv ⚠️ DIFFERS - 2 mv bnez bnez bnez ⚠️ DIFFERS - 3 andi mv mv mv ⚠️ DIFFERS - 4 sd ret ret ret ⚠️ DIFFERS - 5 bnez - 6 ld - 7 sd - 8 ld - 9 addi - 10 ret - -------------------------------------------------------------------------------- - - Summary: - O0: 11 instructions - O1: 5 instructions - O2: 5 instructions - O3: 5 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sext, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.sext variant 0 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.sext variant 0 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sext, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.sext variant 1 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.sext variant 1 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sext, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.sext variant 2 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.sext variant 2 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sext, Variant: 3 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.sext variant 3 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.sext variant 3 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.shl, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.shl variant 0 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.shl variant 0 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.shl, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.shl variant 1 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.shl variant 1 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.shl, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.shl variant 2 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.shl variant 2 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.shl, Variant: 3 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.shl variant 3 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.shl variant 3 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.srl, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.srl variant 0 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.srl variant 0 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sub, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.sub variant 0 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.sub variant 0 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sub, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.sub variant 1 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.sub variant 1 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sub, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.sub variant 2 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.sub variant 2 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.trunc, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.trunc variant 0 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.trunc variant 0 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.udiv, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.udiv variant 0 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.udiv variant 0 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.urem, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.urem variant 0 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.urem variant 0 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.xor, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.xor variant 0 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.xor variant 0 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.zext, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.zext variant 0 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.zext variant 0 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.zext, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.zext variant 1 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.zext variant 1 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.zext, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.zext variant 2 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.zext variant 2 - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.zext, Variant: 3 -──────────────────────────────────────────────────────────────────────────────────────────────────── - ✓ Same instructions at O0 - ✓ Same instructions at O1 - ✓ Same instructions at O2 - ✓ Same instructions at O3 - - ✓ All optimization levels produce the same instructions for GlobalISel llvm.zext variant 3 - ✓ All optimization levels produce the same instructions for SelectionDAG llvm.zext variant 3 - -==================================================================================================== -COMPARISON 2: LEANMLIR vs LLVM at O0 -==================================================================================================== - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.add, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv add ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 add - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv add ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 add - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv add add ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 add - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.add, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv add ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 add - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv add ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 add - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv add add ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 add - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.add, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv add ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 add - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv add ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 add - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv add add ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 add - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.and, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv and ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 and - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv and ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 and - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv and and ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 and - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.ashr, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv sra ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sra - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sra ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sra - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sra sra ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sra - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv sltu ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sltu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sltu ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sltu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sltu sltu ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sltu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv sltu ⚠️ DIFFERS - 1 mv xori ⚠️ DIFFERS - 2 sltu ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 6 instructions - GlobalISel-O0: 3 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sltu ⚠️ DIFFERS - 1 mv xori ⚠️ DIFFERS - 2 sltu ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 6 instructions - SelectionDAG-O0: 3 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sltu sltu ⚠️ DIFFERS - 1 mv xori xori ⚠️ DIFFERS - 2 sltu ret ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 6 instructions - GlobalISel-O0: 3 instructions - SelectionDAG-O0: 3 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv sltu ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sltu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sltu ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sltu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sltu sltu ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sltu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 3 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv sltu ⚠️ DIFFERS - 1 mv xori ⚠️ DIFFERS - 2 sltu ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 6 instructions - GlobalISel-O0: 3 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sltu ⚠️ DIFFERS - 1 mv xori ⚠️ DIFFERS - 2 sltu ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 6 instructions - SelectionDAG-O0: 3 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sltu sltu ⚠️ DIFFERS - 1 mv xori xori ⚠️ DIFFERS - 2 sltu ret ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 6 instructions - GlobalISel-O0: 3 instructions - SelectionDAG-O0: 3 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 4 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv slt ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 slt - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv slt ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 slt - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv slt slt ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 slt - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 5 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv slt ⚠️ DIFFERS - 1 mv xori ⚠️ DIFFERS - 2 slt ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 6 instructions - GlobalISel-O0: 3 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv slt ⚠️ DIFFERS - 1 mv xori ⚠️ DIFFERS - 2 slt ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 6 instructions - SelectionDAG-O0: 3 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv slt slt ⚠️ DIFFERS - 1 mv xori xori ⚠️ DIFFERS - 2 slt ret ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 6 instructions - GlobalISel-O0: 3 instructions - SelectionDAG-O0: 3 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 6 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv slt ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 slt - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv slt ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 slt - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv slt slt ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 slt - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 7 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv slt ⚠️ DIFFERS - 1 mv xori ⚠️ DIFFERS - 2 slt ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 6 instructions - GlobalISel-O0: 3 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv slt ⚠️ DIFFERS - 1 mv xori ⚠️ DIFFERS - 2 slt ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 6 instructions - SelectionDAG-O0: 3 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv slt slt ⚠️ DIFFERS - 1 mv xori xori ⚠️ DIFFERS - 2 slt ret ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 6 instructions - GlobalISel-O0: 3 instructions - SelectionDAG-O0: 3 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 8 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv xor ⚠️ DIFFERS - 1 mv seqz ⚠️ DIFFERS - 2 xor ret ⚠️ DIFFERS - 3 seqz - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 6 instructions - GlobalISel-O0: 3 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv xor ⚠️ DIFFERS - 1 mv seqz ⚠️ DIFFERS - 2 xor ret ⚠️ DIFFERS - 3 seqz - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 6 instructions - SelectionDAG-O0: 3 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv xor xor ⚠️ DIFFERS - 1 mv seqz seqz ⚠️ DIFFERS - 2 xor ret ret ⚠️ DIFFERS - 3 seqz - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 6 instructions - GlobalISel-O0: 3 instructions - SelectionDAG-O0: 3 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.mul, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv mul ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 mul - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv mul ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 mul - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv mul mul ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 mul - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.mul, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv mul ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 mul - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv mul ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 mul - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv mul mul ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 mul - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.mul, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv mul ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 mul - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv mul ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 mul - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv mul mul ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 mul - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.or, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv or ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 or - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv or ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 or - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv or or ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 or - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.rem, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv rem ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 rem - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv rem ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 rem - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv rem rem ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 rem - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sdiv, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv div ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 div - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv div ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 div - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv div div ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 div - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.select, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 addi - 1 sd - 2 andi - 3 sd - 4 bnez - 5 ld - 6 sd - 7 ld - 8 addi - 9 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 0 instructions - GlobalISel-O0: 10 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 addi - 1 sd - 2 mv - 3 andi - 4 sd - 5 bnez - 6 ld - 7 sd - 8 ld - 9 addi - 10 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 0 instructions - SelectionDAG-O0: 11 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 addi addi - 1 sd sd - 2 andi mv ⚠️ DIFFERS - 3 sd andi ⚠️ DIFFERS - 4 bnez sd ⚠️ DIFFERS - 5 ld bnez ⚠️ DIFFERS - 6 sd ld ⚠️ DIFFERS - 7 ld sd ⚠️ DIFFERS - 8 addi ld ⚠️ DIFFERS - 9 ret addi ⚠️ DIFFERS - 10 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 0 instructions - GlobalISel-O0: 10 instructions - SelectionDAG-O0: 11 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sext, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 slli - 1 srai - 2 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 0 instructions - GlobalISel-O0: 3 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 slli - 1 srai - 2 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 0 instructions - SelectionDAG-O0: 3 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 slli slli - 1 srai srai - 2 ret ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 0 instructions - GlobalISel-O0: 3 instructions - SelectionDAG-O0: 3 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sext, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 sext.b - 1 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 0 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 sext.b - 1 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 0 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 sext.b sext.b - 1 ret ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 0 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sext, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 sext.h - 1 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 0 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 sext.h - 1 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 0 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 sext.h sext.h - 1 ret ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 0 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sext, Variant: 3 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 sext.w - 1 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 0 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 sext.w - 1 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 0 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 sext.w sext.w - 1 ret ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 0 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.shl, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv sll ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sll ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sll sll ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.shl, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv sll ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sll ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sll sll ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.shl, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv sll ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sll ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sll sll ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.shl, Variant: 3 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv sll ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sll ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sll sll ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.srl, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv srl ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 srl - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv srl ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 srl - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv srl srl ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 srl - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sub, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv sub ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sub - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sub ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sub - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sub sub ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sub - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sub, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv sub ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sub - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sub ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sub - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sub sub ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sub - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sub, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv sub ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sub - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sub ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sub - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv sub sub ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sub - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.trunc, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv ret ⚠️ DIFFERS - 1 mv - 2 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 3 instructions - GlobalISel-O0: 1 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv ret ⚠️ DIFFERS - 1 mv - 2 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 3 instructions - SelectionDAG-O0: 1 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv ret ret ⚠️ DIFFERS - 1 mv - 2 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 3 instructions - GlobalISel-O0: 1 instructions - SelectionDAG-O0: 1 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.udiv, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv divu ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 divu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv divu ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 divu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv divu divu ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 divu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.urem, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv divu ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 divu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv divu ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 divu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv divu divu ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 divu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.xor, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv xor ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 xor - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv xor ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 xor - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv xor xor ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 xor - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 5 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.zext, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv andi ⚠️ DIFFERS - 1 andi ret ⚠️ DIFFERS - 2 mv - 3 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 4 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv andi ⚠️ DIFFERS - 1 andi ret ⚠️ DIFFERS - 2 mv - 3 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 4 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv andi andi ⚠️ DIFFERS - 1 andi ret ret ⚠️ DIFFERS - 2 mv - 3 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 4 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.zext, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv andi ⚠️ DIFFERS - 1 andi ret ⚠️ DIFFERS - 2 mv - 3 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 4 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv andi ⚠️ DIFFERS - 1 andi ret ⚠️ DIFFERS - 2 mv - 3 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 4 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv andi andi ⚠️ DIFFERS - 1 andi ret ret ⚠️ DIFFERS - 2 mv - 3 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 4 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.zext, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 mv zext.h ⚠️ DIFFERS - 1 zext.h ret ⚠️ DIFFERS - 2 mv - 3 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 4 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv zext.h ⚠️ DIFFERS - 1 zext.h ret ⚠️ DIFFERS - 2 mv - 3 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 4 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 mv zext.h zext.h ⚠️ DIFFERS - 1 zext.h ret ret ⚠️ DIFFERS - 2 mv - 3 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 4 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.zext, Variant: 3 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR DIFFERS from GlobalISel-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 - -------------------------------------------------------------------------------- - 0 zext.w - 1 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 0 instructions - GlobalISel-O0: 2 instructions - - - ✗ LEANMLIR DIFFERS from SelectionDAG-O0 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 zext.w - 1 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 0 instructions - SelectionDAG-O0: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 - -------------------------------------------------------------------------------- - 0 zext.w zext.w - 1 ret ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR: 0 instructions - GlobalISel-O0: 2 instructions - SelectionDAG-O0: 2 instructions - - -==================================================================================================== -COMPARISON 3: LEANMLIR_opt vs LLVM at O2 -==================================================================================================== - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.add, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv add ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 add - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv add ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 add - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv add add ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 add - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.add, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv add ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 add - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv add ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 add - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv add add ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 add - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.add, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv add ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 add - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv add ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 add - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv add add ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 add - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.and, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv and ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 and - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv and ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 and - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv and and ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 and - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.ashr, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv sra ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sra - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sra ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sra - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sra sra ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sra - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv sltu ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sltu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sltu ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sltu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sltu sltu ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sltu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv sltu ⚠️ DIFFERS - 1 mv xori ⚠️ DIFFERS - 2 sltu ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 6 instructions - GlobalISel-O2: 3 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sltu ⚠️ DIFFERS - 1 mv xori ⚠️ DIFFERS - 2 sltu ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 6 instructions - SelectionDAG-O2: 3 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sltu sltu ⚠️ DIFFERS - 1 mv xori xori ⚠️ DIFFERS - 2 sltu ret ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 6 instructions - GlobalISel-O2: 3 instructions - SelectionDAG-O2: 3 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv sltu ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sltu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sltu ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sltu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sltu sltu ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sltu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 3 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv sltu ⚠️ DIFFERS - 1 mv xori ⚠️ DIFFERS - 2 sltu ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 6 instructions - GlobalISel-O2: 3 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sltu ⚠️ DIFFERS - 1 mv xori ⚠️ DIFFERS - 2 sltu ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 6 instructions - SelectionDAG-O2: 3 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sltu sltu ⚠️ DIFFERS - 1 mv xori xori ⚠️ DIFFERS - 2 sltu ret ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 6 instructions - GlobalISel-O2: 3 instructions - SelectionDAG-O2: 3 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 4 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv slt ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 slt - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv slt ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 slt - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv slt slt ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 slt - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 5 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv slt ⚠️ DIFFERS - 1 mv xori ⚠️ DIFFERS - 2 slt ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 6 instructions - GlobalISel-O2: 3 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv slt ⚠️ DIFFERS - 1 mv xori ⚠️ DIFFERS - 2 slt ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 6 instructions - SelectionDAG-O2: 3 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv slt slt ⚠️ DIFFERS - 1 mv xori xori ⚠️ DIFFERS - 2 slt ret ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 6 instructions - GlobalISel-O2: 3 instructions - SelectionDAG-O2: 3 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 6 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv slt ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 slt - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv slt ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 slt - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv slt slt ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 slt - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 7 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv slt ⚠️ DIFFERS - 1 mv xori ⚠️ DIFFERS - 2 slt ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 6 instructions - GlobalISel-O2: 3 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv slt ⚠️ DIFFERS - 1 mv xori ⚠️ DIFFERS - 2 slt ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 6 instructions - SelectionDAG-O2: 3 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv slt slt ⚠️ DIFFERS - 1 mv xori xori ⚠️ DIFFERS - 2 slt ret ret ⚠️ DIFFERS - 3 xori - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 6 instructions - GlobalISel-O2: 3 instructions - SelectionDAG-O2: 3 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.icmp, Variant: 8 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv xor ⚠️ DIFFERS - 1 mv seqz ⚠️ DIFFERS - 2 xor ret ⚠️ DIFFERS - 3 seqz - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 6 instructions - GlobalISel-O2: 3 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv xor ⚠️ DIFFERS - 1 mv seqz ⚠️ DIFFERS - 2 xor ret ⚠️ DIFFERS - 3 seqz - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 6 instructions - SelectionDAG-O2: 3 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv xor xor ⚠️ DIFFERS - 1 mv seqz seqz ⚠️ DIFFERS - 2 xor ret ret ⚠️ DIFFERS - 3 seqz - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 6 instructions - GlobalISel-O2: 3 instructions - SelectionDAG-O2: 3 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.mul, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv mul ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 mul - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv mul ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 mul - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv mul mul ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 mul - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.mul, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv mul ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 mul - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv mul ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 mul - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv mul mul ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 mul - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.mul, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv mul ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 mul - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv mul ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 mul - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv mul mul ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 mul - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.or, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv or ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 or - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv or ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 or - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv or or ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 or - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.rem, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv rem ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 rem - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv rem ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 rem - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv rem rem ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 rem - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sdiv, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv div ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 div - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv div ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 div - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv div div ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 div - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.select, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv - 1 mv - 2 andi - 3 bnez - 4 mv - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 0 instructions - GlobalISel-O2: 6 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 andi - 1 mv - 2 bnez - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 0 instructions - SelectionDAG-O2: 5 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv andi ⚠️ DIFFERS - 1 mv mv - 2 andi bnez ⚠️ DIFFERS - 3 bnez mv ⚠️ DIFFERS - 4 mv ret ⚠️ DIFFERS - 5 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 0 instructions - GlobalISel-O2: 6 instructions - SelectionDAG-O2: 5 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sext, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 slli - 1 srai - 2 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 0 instructions - GlobalISel-O2: 3 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 slli - 1 srai - 2 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 0 instructions - SelectionDAG-O2: 3 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 slli slli - 1 srai srai - 2 ret ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 0 instructions - GlobalISel-O2: 3 instructions - SelectionDAG-O2: 3 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sext, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 sext.b - 1 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 0 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 sext.b - 1 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 0 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 sext.b sext.b - 1 ret ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 0 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sext, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 sext.h - 1 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 0 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 sext.h - 1 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 0 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 sext.h sext.h - 1 ret ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 0 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sext, Variant: 3 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 sext.w - 1 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 0 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 sext.w - 1 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 0 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 sext.w sext.w - 1 ret ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 0 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.shl, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv sll ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sll ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sll sll ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.shl, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv sll ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sll ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sll sll ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.shl, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv sll ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sll ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sll sll ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.shl, Variant: 3 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv sll ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sll ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sll sll ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sll - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.srl, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv srl ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 srl - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv srl ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 srl - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv srl srl ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 srl - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sub, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv sub ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sub - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sub ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sub - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sub sub ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sub - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sub, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv sub ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sub - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sub ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sub - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sub sub ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sub - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.sub, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv sub ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sub - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sub ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 sub - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv sub sub ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 sub - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.trunc, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv ret ⚠️ DIFFERS - 1 mv - 2 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 3 instructions - GlobalISel-O2: 1 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv ret ⚠️ DIFFERS - 1 mv - 2 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 3 instructions - SelectionDAG-O2: 1 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv ret ret ⚠️ DIFFERS - 1 mv - 2 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 3 instructions - GlobalISel-O2: 1 instructions - SelectionDAG-O2: 1 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.udiv, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv divu ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 divu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv divu ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 divu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv divu divu ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 divu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.urem, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv divu ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 divu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv divu ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 divu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv divu divu ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 divu - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.xor, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv xor ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 xor - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv xor ⚠️ DIFFERS - 1 mv ret ⚠️ DIFFERS - 2 xor - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv xor xor ⚠️ DIFFERS - 1 mv ret ret ⚠️ DIFFERS - 2 xor - 3 mv - 4 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 5 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.zext, Variant: 0 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv andi ⚠️ DIFFERS - 1 andi ret ⚠️ DIFFERS - 2 mv - 3 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 4 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv andi ⚠️ DIFFERS - 1 andi ret ⚠️ DIFFERS - 2 mv - 3 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 4 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv andi andi ⚠️ DIFFERS - 1 andi ret ret ⚠️ DIFFERS - 2 mv - 3 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 4 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.zext, Variant: 1 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv andi ⚠️ DIFFERS - 1 andi ret ⚠️ DIFFERS - 2 mv - 3 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 4 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv andi ⚠️ DIFFERS - 1 andi ret ⚠️ DIFFERS - 2 mv - 3 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 4 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv andi andi ⚠️ DIFFERS - 1 andi ret ret ⚠️ DIFFERS - 2 mv - 3 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 4 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.zext, Variant: 2 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 mv zext.h ⚠️ DIFFERS - 1 zext.h ret ⚠️ DIFFERS - 2 mv - 3 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 4 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv zext.h ⚠️ DIFFERS - 1 zext.h ret ⚠️ DIFFERS - 2 mv - 3 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 4 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 mv zext.h zext.h ⚠️ DIFFERS - 1 zext.h ret ret ⚠️ DIFFERS - 2 mv - 3 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 4 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -──────────────────────────────────────────────────────────────────────────────────────────────────── -Operation: llvm.zext, Variant: 3 -──────────────────────────────────────────────────────────────────────────────────────────────────── - - ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 - -------------------------------------------------------------------------------- - 0 zext.w - 1 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 0 instructions - GlobalISel-O2: 2 instructions - - - ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 zext.w - 1 ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 0 instructions - SelectionDAG-O2: 2 instructions - - - Comprehensive comparison of all three: - - Instruction-by-instruction comparison: - -------------------------------------------------------------------------------- - Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 - -------------------------------------------------------------------------------- - 0 zext.w zext.w - 1 ret ret - -------------------------------------------------------------------------------- - - Summary: - LEANMLIR_opt: 0 instructions - GlobalISel-O2: 2 instructions - SelectionDAG-O2: 2 instructions - - -==================================================================================================== -END OF ALL COMPARISONS -==================================================================================================== - diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_add.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_add.mlir deleted file mode 100644 index 167eda5101..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_add.mlir +++ /dev/null @@ -1,21 +0,0 @@ -// llvm.add -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.add %arg0, %arg1 overflow : i64 - return %0 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.add %arg0, %arg1 overflow : i64 - return %0 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.add %arg0, %arg1 overflow : i64 - return %0 : i64 - } -} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_and.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_and.mlir deleted file mode 100644 index 3b9428b43d..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_and.mlir +++ /dev/null @@ -1,7 +0,0 @@ -// llvm.and -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.and %arg0, %arg1 : i64 - return %0 : i64 - } -} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_ashr.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_ashr.mlir deleted file mode 100644 index e8441f4a41..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_ashr.mlir +++ /dev/null @@ -1,7 +0,0 @@ -// llvm.ashr -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.ashr %arg0, %arg1 : i64 - return %0 : i64 - } -} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_icmp.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_icmp.mlir deleted file mode 100644 index 5482fce1b1..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_icmp.mlir +++ /dev/null @@ -1,70 +0,0 @@ -// llvm.icmp -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.icmp "ugt" %arg0, %arg1 : i64 - return %0 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.icmp "uge" %arg0, %arg1 : i64 - return %0 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.icmp "ult" %arg0, %arg1 : i64 - return %0 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.icmp "ule" %arg0, %arg1 : i64 - return %0 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.icmp "sgt" %arg0, %arg1 : i64 - return %0 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.icmp "sge" %arg0, %arg1 : i64 - return %0 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.icmp "slt" %arg0, %arg1 : i64 - return %0 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.icmp "sle" %arg0, %arg1 : i64 - return %0 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.icmp "eq" %arg0, %arg1 : i64 - return %0 : i1 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i1 { - %0 = llvm.icmp "neq" %arg0, %arg1 : i64 - return %0 : i1 - } -} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_mul.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_mul.mlir deleted file mode 100644 index 1efd7b2fcd..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_mul.mlir +++ /dev/null @@ -1,21 +0,0 @@ -// llvm.mul -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.mul %arg0, %arg1 overflow : i64 - return %0 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.mul %arg0, %arg1 overflow : i64 - return %0 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.mul %arg0, %arg1 overflow : i64 - return %0 : i64 - } -} diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_or.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_or.mlir deleted file mode 100644 index 13162159f4..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_or.mlir +++ /dev/null @@ -1,7 +0,0 @@ -// llvm.or -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.or %arg0, %arg1 : i64 - return %0 : i64 - } -} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_rem.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_rem.mlir deleted file mode 100644 index 1f070de0ef..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_rem.mlir +++ /dev/null @@ -1,7 +0,0 @@ -// llvm.rem -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.srem %arg0, %arg1 : i64 - return %0 : i64 - } -} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sdiv.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sdiv.mlir deleted file mode 100644 index af5f06d6da..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sdiv.mlir +++ /dev/null @@ -1,7 +0,0 @@ -// llvm.sdiv -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.sdiv %arg0, %arg1 : i64 - return %0 : i64 - } -} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_select.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_select.mlir deleted file mode 100644 index 1e15a4102e..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_select.mlir +++ /dev/null @@ -1,7 +0,0 @@ -// llvm.select -module { - func.func @main(%cond : i1, %arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.select %cond, %arg0, %arg1 : i1, i64 - return %0 : i64 - } -} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sext.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sext.mlir deleted file mode 100644 index b6f36b0426..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sext.mlir +++ /dev/null @@ -1,28 +0,0 @@ -// llvm.sext -module { - func.func @main(%arg0: i1) -> i64 { - %0 = llvm.sext %arg0 : i1 to i64 - return %0 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i8) -> i64 { - %0 = llvm.sext %arg0 : i8 to i64 - return %0 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i16) -> i64 { - %0 = llvm.sext %arg0 : i16 to i64 - return %0 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i32) -> i64 { - %0 = llvm.sext %arg0 : i32 to i64 - return %0 : i64 - } -} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_shl.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_shl.mlir deleted file mode 100644 index ec86a8d33f..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_shl.mlir +++ /dev/null @@ -1,28 +0,0 @@ -// llvm.shl -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.shl %arg0, %arg1 : i64 - return %0 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.shl %arg0, %arg1 overflow : i64 - return %0 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.shl %arg0, %arg1 overflow : i64 - return %0 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.shl %arg0, %arg1 overflow : i64 - return %0 : i64 - } -} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_srl.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_srl.mlir deleted file mode 100644 index 3187cfa691..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_srl.mlir +++ /dev/null @@ -1,7 +0,0 @@ -// llvm.srl -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.lshr %arg0, %arg1 : i64 - return %0 : i64 - } -} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sub.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sub.mlir deleted file mode 100644 index 6f600d13ad..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sub.mlir +++ /dev/null @@ -1,21 +0,0 @@ -// llvm.sub -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.sub %arg0, %arg1 overflow : i64 - return %0 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.sub %arg0, %arg1 overflow : i64 - return %0 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.sub %arg0, %arg1 overflow : i64 - return %0 : i64 - } -} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_trunc.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_trunc.mlir deleted file mode 100644 index dc6700695a..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_trunc.mlir +++ /dev/null @@ -1,7 +0,0 @@ -// llvm.trunc -module { - func.func @main(%arg0: i64) -> i32 { - %0 = llvm.trunc %arg0 : i64 to i32 - return %0 : i32 - } -} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_udiv.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_udiv.mlir deleted file mode 100644 index 445b47437a..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_udiv.mlir +++ /dev/null @@ -1,7 +0,0 @@ -// llvm.udiv -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.udiv %arg0, %arg1 : i64 - return %0 : i64 - } -} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_urem.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_urem.mlir deleted file mode 100644 index 7f61c56d54..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_urem.mlir +++ /dev/null @@ -1,7 +0,0 @@ -// llvm.urem -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.udiv %arg0, %arg1 : i64 - return %0 : i64 - } -} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_xor.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_xor.mlir deleted file mode 100644 index c3586dfd71..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_xor.mlir +++ /dev/null @@ -1,7 +0,0 @@ -// llvm.xor -module { - func.func @main(%arg0: i64, %arg1: i64) -> i64 { - %0 = llvm.xor %arg0, %arg1 : i64 - return %0 : i64 - } -} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_zext.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_zext.mlir deleted file mode 100644 index e8127afbce..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_zext.mlir +++ /dev/null @@ -1,28 +0,0 @@ -// llvm.zext -module { - func.func @main(%arg0: i1) -> i64 { - %0 = llvm.zext %arg0 : i1 to i64 - return %0 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i8) -> i64 { - %0 = llvm.zext %arg0 : i8 to i64 - return %0 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i16) -> i64 { - %0 = llvm.zext %arg0 : i16 to i64 - return %0 : i64 - } -} -// ----- -module { - func.func @main(%arg0: i32) -> i64 { - %0 = llvm.zext %arg0 : i32 to i64 - return %0 : i64 - } -} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/run_comparison.sh b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/run_comparison.sh deleted file mode 100755 index 8373001af5..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/run_comparison.sh +++ /dev/null @@ -1,5 +0,0 @@ -#! /bin/bash -export PYTHONPATH=$PYTHONPATH:~/lean-mlir -python3 ../benchmarks/generate.py --num 10 --jobs 30 --llvm_opt all -l -python3 ../mca-analysis/run_mca.py -python3 compare_lowerings.py \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/.python-version b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/.python-version deleted file mode 100644 index 24ee5b1be9..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.13 diff --git a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/README.md b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/README.md deleted file mode 100644 index b2b13cd670..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/README.md +++ /dev/null @@ -1,42 +0,0 @@ - -# MCA Analysis - -## Dependencies - -This evaluation requires `llvm-mca`, either install it through your favourite -package manager, or, if you've built LLVM from source, add the `bin` directory -to your path. - -For example, if you've built LLVM at `~/llvm-project/build`, and you run bash as -your shell, you should run the following before you run the script: - -```bash -export PATH=$PATH:~/llvm-project/build/bin/ -``` - -To make sure that `evallib` is correctly imported, run: - -```bash -export PYTHONPATH=$PYTHONPATH:~/lean-mlir -``` - -## How to run - -To reproduce the mca analysis results, run: -``` -python3 run_mca.py -``` - - -This file will run LLVM's `llvm-mca` tool on the RISCV assembly files produced by LLVM with `globalISel`, LLVM with `selectionDAG`, Lean-MLIR + XDSL and Lean-MLIR with optimizations + XDSL using the following command: - -``` -llvm-mca -mtriple=riscv64 -mcpu=sifive-u74 -mattr=+m,+zba,+zbb,+zbs $input_file -``` - -The results of the analysis and the log of the tool are available in `results/`. - -To reproduce the plots, run -``` -python3 plot.py -``` \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/plot.py b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/plot.py deleted file mode 100755 index bb3e0007c9..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/plot.py +++ /dev/null @@ -1,1043 +0,0 @@ -#!/usr/bin/env python3 - -import subprocess -import os -import argparse -import shutil -import pandas as pd -import matplotlib -import matplotlib.pyplot as plt -import numpy as np -import math -from num2words import num2words - -matplotlib.rcParams["pdf.fonttype"] = 42 -matplotlib.rcParams["font.size"] = 20 - - -matplotlib.rcParams["figure.autolayout"] = True -matplotlib.rcParams["legend.frameon"] = False -matplotlib.rcParams["axes.spines.right"] = False -matplotlib.rcParams["axes.spines.top"] = False - -# matplotlib.rcParams['figure.figsize'] = 5, 2 - -light_gray = "#cacaca" -dark_gray = "#827b7b" -light_blue = "#a6cee3" -dark_blue = "#1f78b4" -light_green = "#b2df8a" -dark_green = "#33a02c" -light_red = "#fb9a99" -dark_red = "#e31a1c" -black = "#000000" -white = "#ffffff" - -colors_list = [ - light_gray, - dark_gray, - light_blue, - dark_blue, - light_green, - dark_green, - light_red, - dark_red, - black, - white, -] - -ROOT_DIR_PATH = ( - subprocess.check_output(["git", "rev-parse", "--show-toplevel"]) - .decode("utf-8") - .strip() -) - -LLVMIR_DIR_PATH = ( - f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LLVMIR/" -) - -LLVM_globalisel_results_DIR_PATH = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LLVM_globalisel/" -LLVM_selectiondag_results_DIR_PATH = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LLVM_selectiondag/" -LEANMLIR_results_DIR_PATH = ( - f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LEANMLIR/" -) -LEANMLIR_opt_results_DIR_PATH = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LEANMLIR_opt/" - -tables_dir = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/tables/" -data_dir = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/data/" -plots_dir = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/plots/" - - -def setup_benchmarking_directories(): - """ - Create clean directories to store the benchmarks. - """ - if not os.path.exists(data_dir): - os.makedirs(data_dir) - else: - shutil.rmtree(data_dir) - os.makedirs(data_dir) - - if not os.path.exists(plots_dir): - os.makedirs(plots_dir) - else: - shutil.rmtree(plots_dir) - os.makedirs(plots_dir) - - -parameters_match = { - "tot_instructions": "Instructions: ", - "tot_cycles": "Total Cycles: ", - "tot_uops": "Total uOps: ", - "similarity": "Instructions List: ", -} - -parameters_labels = { - "tot_instructions": "#Instructions", - "tot_cycles": "#Cycles", - "tot_uops": "#uOps", - "similarity": "Instructions List:", -} - -selector_labels = { - "LEANMLIR_opt": "Lean-MLIRISel", - "LLVM_globalisel_O1": "GlobalISel (O1)", - "LLVM_globalisel_O2": "GlobalISel (O2)", - "LLVM_globalisel_O3": "GlobalISel (O3)", - "LLVM_globalisel": "GlobalISel", - "LLVM_selectiondag_O1": "SelectionDAG (O1)", - "LLVM_selectiondag_O2": "SelectionDAG (O2)", - "LLVM_selectiondag_O3": "SelectionDAG (O3)", - "LLVM_selectiondag": "SelectionDAG", -} - - -def parse_instructions(filename): - instructions = [] - in_instruction_section = False - - with open(filename, "r") as f: - for line in f: - if ( - "[0] [1] [2] [3] [4] [5] [6] [7] Instructions:" - in line - ): - in_instruction_section = True - continue - - if in_instruction_section and line.strip(): - parts = line.split() - instruction = parts[8:] # inst name is in 9th column - instructions.append(instruction) - if len(instructions) == 0: - return None - return instructions - - -def extract_data(results_directory, benchmark_name, parameter): - """ - Parses the results of mca and saves the result in a DataFrame, then printed to `.csv` - """ - function_names = [] - parameter_numbers = [] - for filename in os.listdir(results_directory): - file_path = os.path.join(results_directory, filename) - try: - if parameter == "similarity": - with open(file_path, "r") as f: - file_lines = f.readlines() - instructions = parse_instructions(file_path) - if instructions is not None: - parameter_numbers.append(instructions) - function_names.append(filename.split(".")[0]) - else: - with open(file_path, "r") as f: - file_lines = f.readlines() - for line in file_lines: - if parameters_match[parameter] in line: - function_names.append(filename.split(".")[0]) - num = int(line.split(" ")[-1]) - if parameter == "tot_cycles": - parameter_numbers.append(int(num)) - else: - parameter_numbers.append(int(num / 100)) - except FileNotFoundError: - print(f"Warning: file not found at {file_path}. Skipping.") - df = pd.DataFrame( - { - "function_name": function_names, - benchmark_name + "_" + parameter: parameter_numbers, - } - ) - df.to_csv(data_dir + benchmark_name + "_" + parameter + ".csv") - - -def join_dataframes(dataframe_names, parameter): - """ - Joins multiple DataFrames on a common 'function_name' column. - """ - for idx, name in enumerate(dataframe_names): - df = pd.read_csv( - data_dir + name + "_" + parameter + ".csv", index_col=0, header=0 - ) - if idx == 0: - complete_df = df - else: - complete_df = pd.merge(complete_df, df, on="function_name", how="inner") - complete_df["instructions_number"] = complete_df["function_name"].apply( - lambda x: int(x.split("_")[0]) - ) - if parameter == "similarity": - complete_df["is_eqv_LLVM_globalisel"] = complete_df["LLVM_globalisel_" + parameter] == complete_df["LEANMLIR_opt_" + parameter] - complete_df["is_eqv_LLVM_selectiondag"] = complete_df["LLVM_selectiondag_" + parameter] == complete_df["LEANMLIR_opt_" + parameter] - # drop LLVM_globalisel_similarity and LLVM_selectiondag_similarity columns - complete_df = complete_df.drop( - ["LLVM_globalisel_" + parameter, "LLVM_selectiondag_" + parameter, "LEANMLIR_opt_" + parameter], axis=1 - ) - complete_df.to_csv(data_dir + parameter + ".csv") - - -def sorted_line_plot_all(parameter): - df = pd.read_csv(data_dir + parameter + ".csv") - - sorted_df = df.sort_values( - by=[ - "LEANMLIR_opt_" + parameter, - "LLVM_globalisel_" + parameter, - "LLVM_selectiondag_" + parameter, - ] - ) - - plt.plot( - range(len(sorted_df)), - sorted_df["LEANMLIR_opt_" + parameter], - label=selector_labels["LEANMLIR_opt"], - color=dark_green, - ) - plt.plot( - range(len(sorted_df)), - sorted_df["LLVM_globalisel_" + parameter], - label=selector_labels["LLVM_globalisel"], - color=light_blue, - ) - plt.plot( - range(len(sorted_df)), - sorted_df["LLVM_selectiondag_" + parameter], - label=selector_labels["LLVM_selectiondag"], - color=light_red, - ) - plot_max = ( - np.max( - [ - sorted_df["LEANMLIR_opt_" + parameter].min(), - sorted_df["LLVM_globalisel_" + parameter].min(), - sorted_df["LLVM_selectiondag_" + parameter].min(), - ] - ) - + 1 - ) - - plt.ylim(1, int(plot_max * 1.5) + 1) - plt.yticks(range(1, int(plot_max * 1.5) + 1, int((int(plot_max * 1.5) + 5) / 5))) - - plt.xlabel("Program Index") - plt.ylabel(parameter) - plt.figure(figsize=(10, 5)) - - # plt.title(f'{parameter} Per Program') - - plt.legend(ncols=2) - plt.tight_layout() - - pdf_filename = plots_dir + parameter + "_line.pdf" - plt.savefig(pdf_filename) - # print(f"\nPlot saved to '{pdf_filename}' in the current working directory.") - plt.close() - - -def scatter_plot(parameter, selector1, selector2): - df = pd.read_csv(data_dir + parameter + ".csv") - - if selector1 + "_" + parameter not in df.columns: - print(f"Error: the column {selector1} does not exist in the dataframe.") - return - if selector2 + "_" + parameter not in df.columns: - print(f"Error: the column {selector2} does not exist in the dataframe.") - - df_plot_comparison = df[ - [selector1 + "_" + parameter, selector2 + "_" + parameter] - ].dropna() - - frequencies = ( - df_plot_comparison.groupby( - [selector1 + "_" + parameter, selector2 + "_" + parameter] - ) - .size() - .reset_index(name="Frequency") - ) - df_plot_scaled = pd.merge( - df_plot_comparison, - frequencies, - on=[selector1 + "_" + parameter, selector2 + "_" + parameter], - how="left", - ) - - df_plot_scaled["Scaled_Size"] = np.sqrt((df_plot_scaled["Frequency"])) * 50 + 20 - - - plt.scatter( - df_plot_scaled[selector1 + "_" + parameter], - df_plot_scaled[selector2 + "_" + parameter], - s=df_plot_scaled["Scaled_Size"], - color=light_blue, - alpha=0.7, - edgecolors="w", - label="Function data points (Size by frequency)", - ) - - min_val = min( - df_plot_comparison[selector1 + "_" + parameter].min(), - df_plot_comparison[selector2 + "_" + parameter].min(), - ) - max_val = max( - df_plot_comparison[selector1 + "_" + parameter].max(), - df_plot_comparison[selector2 + "_" + parameter].max(), - ) - # Add a small buffer to the min/max values for better visualization - plot_min = max(0, min_val - 1) - plot_max = max_val + 1 - - plt.plot( - [plot_min, plot_max], - [plot_min, plot_max], - color="gray", - linestyle="--", - label="$x=y$ line", - ) - - plt.xlabel(selector_labels[selector1] + " - " + parameters_labels[parameter]) - plt.ylabel(selector_labels[selector2] + " - " + parameters_labels[parameter]) - - if ( - not (plot_min == plot_max) - and (0 < int(plot_min / 5)) - and (0 < int(plot_max / 5)) - ): - plt.xlim(plot_min, plot_max) - plt.ylim(plot_min, plot_max) - - plt.xticks(range(0, int(plot_max), int((plot_max) / 5))) - plt.yticks(range(0, int(plot_max), int((plot_max) / 5))) - - plt.gca().set_aspect("equal", adjustable="box") - - plt.tight_layout() - - pdf_filename = ( - plots_dir + f"{parameter}_scatter_plot_{selector1}_vs_{selector2}.pdf" - ) - plt.savefig(pdf_filename, bbox_inches='tight') - # print(f"\nScatter plot saved to '{pdf_filename}' in the current working directory.") - plt.close() - -def bar_plot(parameter, selector1, selector2): - df = pd.read_csv(data_dir + parameter + ".csv") - - col1 = selector1 + "_" + parameter - col2 = selector2 + "_" + parameter - - if col1 not in df.columns: - print(f"Error: the column {col1} does not exist in the dataframe.") - return - if col2 not in df.columns: - print(f"Error: the column {col2} does not exist in the dataframe.") - return - - # Compute the difference - df["diff"] = df[col1] / df[col2] - - # Classify the differences - def classify(diff): - if diff < 1: - return "<1x" - elif diff == 1: - return "1x" - elif diff < 1.5: - return "1x-1.5x" - elif diff < 2: - return "1.5x-2x" - else: - return ">2x" - - df["diff_class"] = df["diff"].apply(classify) - - df.to_csv(data_dir + parameter + f"_{selector1}_vs_{selector2}_classified.csv") - - # For each unique value of the initial `instructions_number`, compute the % of each diff_class - group = ( - df.groupby("instructions_number")["diff_class"] - .value_counts(normalize=True) - .unstack(fill_value=0) - * 100 - ) - - # Ensure all classes are present for consistent coloring/order - class_order = ["<1x", "1x", "1x-1.5x", "1.5x-2x", ">2x"] - - # for c in class_order: - # if c not in group.columns: - # group[c] = 0 - group = group[class_order] - - # Colors for each class - class_colors = { - "<1x": light_blue, - "1x": dark_green, - "1x-1.5x": light_green, - "1.5x-2x": light_red, - ">2x": dark_red, - } - - similarity_df = pd.read_csv(data_dir + "similarity.csv") - similarity_percentages = {} - col_name = f"is_eqv_{selector2}" - for instr_num, group_df in similarity_df.groupby("instructions_number"): - total_count = len(group_df) - true_count = group_df[col_name].sum() - percentage = (true_count / total_count) * 100 if total_count > 0 else 0.0 - similarity_percentages[int(instr_num)] = percentage - - - def plot_columns(with_similarity=False): - bottom = np.zeros(len(group)) - similarity_df = pd.read_csv(data_dir + "similarity.csv") - similarity_df_grouped = similarity_df.groupby("instructions_number") - x = group.index.astype(str) - plt.figure(figsize=(10, 5)) - for c in class_order: - if c == "1x" and with_similarity: - similarity_list = list(similarity_percentages.values()) - remaining = [a - b for a, b in zip(group[c], similarity_list)] - plt.bar( - x, similarity_list, bottom=bottom, color=class_colors[c], hatch="//" - ) - bottom += similarity_list - plt.bar( - x, remaining, bottom=bottom, label=f"{c}", color=class_colors[c] - ) - bottom += remaining - else: - plt.bar(x, group[c], bottom=bottom, label=f"{c}", color=class_colors[c]) - bottom += group[c].values - - plt.xlabel("#instructions - LLVM IR") - plt.ylabel( - "%Programs", rotation="horizontal", horizontalalignment="left", y=1.05 - ) - plt.legend(ncols=5, bbox_to_anchor=(0.5, -0.5), loc="lower center") - plt.subplots_adjust(bottom=0.4) - plt.tight_layout() - - name_extension = "_similarity_" if with_similarity else "_" - pdf_filename = ( - plots_dir - + f"{parameter}_stacked_bar{name_extension}{selector1}_vs_{selector2}.pdf" - ) - plt.savefig(pdf_filename) - # print( - # f"\nStacked bar plot saved to '{pdf_filename}' in the current working directory." - # ) - plt.close() - - plot_columns() - if parameter == "tot_instructions": - plot_columns(with_similarity=True) - - -def violin_plot(parameter, selector1, selector2): - df = pd.read_csv(data_dir + parameter + ".csv") - - col1 = selector1 + "_" + parameter - col2 = selector2 + "_" + parameter - - if col1 not in df.columns: - print(f"Error: the column {col1} does not exist in the dataframe.") - return - if col2 not in df.columns: - print(f"Error: the column {col2} does not exist in the dataframe.") - return - - df["ratio"] = df[col1] / df[col2] - - num_above_50 = sum(df["ratio"] > 50) - - print(f"Number of programs with ratio above 50: {num_above_50} out of {len(df)}") - - # extract the columns with ratio > 50 - - high_ratio_df =( df[df["ratio"] > 50]).groupby("instructions_number") - for instr_num, group in high_ratio_df: - print(f"LLVM #Instructions: {instr_num}, #programs with ratio > 50 : {len(group)}") - - # remove points above 50 for y-axis scaling - - grouped = df.groupby("instructions_number")["ratio"].apply(list).reset_index() - - violin_data = grouped["ratio"].values - positions = grouped["instructions_number"].values - - - plt.figure(figsize=(10, 5)) - parts = plt.violinplot( - violin_data, - positions, - showmedians=True - ) - - for pc in parts["bodies"]: - pc.set_facecolor(light_green) - pc.set_edgecolor(light_green) - pc.set_alpha(1.0) - - plt.axhline(1, color=black, linestyle="--", linewidth=1, label="1x") - plt.text(positions[-1]*1.08, 1.02, "1x", color=black, ha='center', fontsize=20) - - for partname in ('cbars', 'cmins', 'cmaxes'): - if partname in parts: - parts[partname].set_edgecolor(light_gray) - parts[partname].set_linewidth(1) - parts['cmedians'].set_edgecolor(dark_green) - - plt.xlabel(f"#Instructions - LLVM IR") - plt.ylabel( - f"$\\frac{{\\text{{{parameters_labels[parameter]}{selector_labels[selector1]}}}}}{{\\text{{{parameters_labels[parameter]}{selector_labels[selector2]}}}}}$", - fontsize = 26, - rotation="horizontal", horizontalalignment="left", y=1.05 - ) - - # add a marker at the top of every column indicating the number of outliers removed - - max_ratio = df["ratio"].max() - - print(f"Max ratio for {parameter} between {selector1} and {selector2} is {max_ratio}") - - - if max_ratio > 200: - plt.yticks(np.arange(0, 270, 50)) - else: - plt.yticks(np.arange(0, math.ceil(df["ratio"].max()) + 2, 2)) - - plt.tight_layout() - - pdf_filename = ( - plots_dir + f"{parameter}_violin_{selector1}_vs_{selector2}.pdf" - ) - plt.savefig(pdf_filename) - # print(f"\nViolin plot saved to '{pdf_filename}' in the current working directory.") - plt.close() - - -def sorted_line_plot(parameter, selector1, selector2): - df = pd.read_csv(data_dir + parameter + ".csv") - - sorted_df = df.sort_values( - by=[selector1 + "_" + parameter, selector2 + "_" + parameter] - ) - plt.figure(figsize=(12, 5)) - - plt.plot( - range(len(sorted_df)), - sorted_df[selector1 + "_" + parameter], - label=selector_labels[selector1], - color=light_green, - ) - plt.plot( - range(len(sorted_df)), - sorted_df[selector2 + "_" + parameter], - label=selector_labels[selector2], - color=dark_green, - ) - - plt.xlabel("Program Index") - plt.ylabel( - parameters_labels[parameter], - rotation="horizontal", - horizontalalignment="left", - y=1, - ) - # plt.title(f'{parameters_labels[parameter]} Per Program, {selector1} vs. {selector2}') - # plt.yticks(range(int(plot_min), int(plot_max + 1), 1)) - plt.legend() - plt.tight_layout() - - pdf_filename = plots_dir + parameter + f"_{selector1}_vs_{selector2}_line.pdf" - plt.savefig(pdf_filename, bbox_inches='tight') - # print(f"\nPlot saved to '{pdf_filename}' in the current working directory.") - plt.close() - - avg_diff = ( - sorted_df[selector1 + "_" + parameter] - sorted_df[selector2 + "_" + parameter] - ).mean() - # Clean names for LaTeX command - - - -def overhead_plot(parameter, selector1, selector2): - """ - Plots the overhead of employing `selector1` against `selector2` - """ - df = pd.read_csv(data_dir + parameter + ".csv") - - sorted_df = df.sort_values( - by=[selector1 + "_" + parameter, selector2 + "_" + parameter], - ascending=[True, True], - ) - plt.figure(figsize=(10, 5)) - - if 0 < len(sorted_df): - plt.stackplot( - range(0, len(sorted_df)), - sorted_df[selector1 + "_" + parameter], - labels=[selector_labels[selector1]], - color=light_green, - ) - plt.stackplot( - range(0, len(sorted_df)), - sorted_df[selector2 + "_" + parameter], - labels=[selector_labels[selector2]], - color=white, - edgecolor=light_red, - ) - - plt.xlabel("Program Index") - plt.ylabel( - parameters_labels[parameter], - rotation="horizontal", - horizontalalignment="left", - y=1, - ) - plt.xticks(range(0, len(sorted_df), int(np.ceil(len(sorted_df) / 5)))) - plt.legend() - plt.tight_layout() - - pdf_filename = ( - plots_dir + f"{parameter}_overhead_{selector1}_vs_{selector2}.pdf" - ) - plt.savefig(pdf_filename, bbox_inches='tight') - # print(f"\nPlot saved to '{pdf_filename}' in the current working directory.") - plt.close() - -def geomean_plot_tot_cycles(): - parameters = ("#cycles", "#instructions") - # tot_cycles - df_cycles = pd.read_csv(data_dir + "tot_cycles.csv") - plt.figure(figsize=(6, 5)) - df_cycles['ratio_gisel'] = df_cycles['LEANMLIR_opt_tot_cycles'] / df_cycles['LLVM_globalisel_tot_cycles'] - df_cycles['ratio_sdag'] = df_cycles['LEANMLIR_opt_tot_cycles'] / df_cycles['LLVM_selectiondag_tot_cycles'] - geomean_gisel_cycles = np.exp(np.mean(np.log(df_cycles["ratio_gisel"]))) - geomean_sdag_cycles = np.exp(np.mean(np.log(df_cycles["ratio_sdag"]))) - #tot_instructions - df_instructions = pd.read_csv(data_dir + "tot_instructions.csv") - df_instructions['ratio_gisel'] = df_instructions['LEANMLIR_opt_tot_instructions'] / df_instructions['LLVM_globalisel_tot_instructions'] - df_instructions['ratio_sdag'] = df_instructions['LEANMLIR_opt_tot_instructions'] / df_instructions['LLVM_selectiondag_tot_instructions'] - geomean_gisel_instructions = np.exp(np.mean(np.log(df_instructions["ratio_gisel"]))) - geomean_sdag_instructions= np.exp(np.mean(np.log(df_instructions["ratio_sdag"]))) - geomeans_gisel = [geomean_gisel_instructions, geomean_gisel_cycles] - geomeans_sdag = [geomean_sdag_instructions, geomean_sdag_cycles] - - x = np.arange(len(parameters)) - width = 0.35 - - plt.bar(x - width/2, geomeans_gisel, width, label=selector_labels["LLVM_globalisel"], color=light_blue) - plt.bar(x + width/2, geomeans_sdag, width, label=selector_labels["LLVM_selectiondag"], color=light_red) - plt.axhline(1, color=black, linestyle="--", linewidth=2) - - plt.ylabel( - 'Geomean Ratio', - rotation="horizontal", - horizontalalignment="left", - y=1, - ) - plt.xticks(x, parameters) - plt.legend() - plt.tight_layout() - - pdf_filename = plots_dir + "geomean_comparison.pdf" - plt.savefig(pdf_filename) - print(f"\nGeometric mean plot saved to '{pdf_filename}' in the current working directory.") - plt.close() - - -def equivalent_plot_perc(): - df_similarity = (pd.read_csv(data_dir + "similarity.csv")) - - df_eqv_gisel = ( - df_similarity.groupby("instructions_number")["is_eqv_LLVM_globalisel"] - .value_counts(normalize=True) - .unstack(fill_value=0) - * 100 - ) - - df_eqv_sdag = ( - df_similarity.groupby("instructions_number")["is_eqv_LLVM_selectiondag"] - .value_counts(normalize=True) - .unstack(fill_value=0) - * 100 - ) - plt.figure(figsize=(7, 5)) - - width = 0.4 - - plt.bar((df_eqv_gisel.index) - width/2, (df_eqv_gisel[True]).to_list(), width, label=selector_labels["LLVM_globalisel"], color=light_blue) - plt.bar((df_eqv_gisel.index) + width/2, (df_eqv_sdag[True]).to_list(), width, label=selector_labels["LLVM_selectiondag"], color=light_red) - - plt.ylabel( - '% Identical Outputs', - rotation="horizontal", - horizontalalignment="left", - y=1.05, - ) - plt.xlabel("#Instructions - LLVM IR") - - plt.legend() - plt.tight_layout() - - pdf_filename = plots_dir + "equivalent_outputs.pdf" - plt.savefig(pdf_filename) - print(f"\nGeometric mean plot saved to '{pdf_filename}' in the current working directory.") - plt.close() - - -def proportional_bar_plot(parameter, selector1, selector2): - df = pd.read_csv(data_dir + parameter + ".csv") - - plt.figure(figsize=(7, 5)) - - col1 = selector1 + "_" + parameter - col2 = selector2 + "_" + parameter - - if col1 not in df.columns or col2 not in df.columns: - print( - f"Error: One or both columns ({col1}, {col2}) do not exist in the dataframe." - ) - return - - df['ratios'] = df[col1] / df[col2] - - average_ratios_by_instruction = ( - df.groupby('instructions_number')['ratios'] - .apply(lambda x: np.exp(np.log(x).mean())) - .reset_index(name='average_ratio') - ) - - print(selector2) - print(parameter) - print(max(df['ratios'])) - - - width = 0.8 - - plt.bar( - average_ratios_by_instruction["instructions_number"], - average_ratios_by_instruction["average_ratio"], - color=light_green, - width=width, - label=f"Avg. {parameters_labels[parameter]},$\\frac{{\\text{{{selector_labels[selector1]}}}}}{{\\text{{{selector_labels[selector2]}}}}}$" - ) - - plt.axhline(1, color=black, linestyle="--", linewidth=2) - - - - plt.xlabel("#Instructions - LLVM IR") - - plt.ylabel( - f"$\\frac{{\\text{{{parameters_labels[parameter]},{selector_labels[selector1]}}}}}{{\\text{{{parameters_labels[parameter]}{selector_labels[selector2]}}}}}$", - fontsize=26, - rotation="horizontal", horizontalalignment="left", y=1.08 - ) - - # if max(average_ratios_by_instruction["average_ratio"]) < 10: - # plt.yticks(np.arange(0, math.ceil(max(average_ratios_by_instruction["average_ratio"])+1), 0.5)) - # else : - # plt.yticks(np.arange(0, math.ceil(max(average_ratios_by_instruction["average_ratio"])+1), 100)) - if (selector2 == "LLVM_globalisel") and (parameter == "tot_instructions"): - plt.yticks(np.arange(0, 2, 0.5)) - plt.text((((average_ratios_by_instruction["instructions_number"]).to_list())[-1])*1.15, 0.95, f"GISel", color=black, ha='center', fontsize=20) - elif (selector2 == "LLVM_selectiondag") and (parameter == "tot_instructions"): - plt.yticks(np.arange(0, 3, 1)) - plt.text((((average_ratios_by_instruction["instructions_number"]).to_list())[-1])*1.15, 0.95, f"SDAG", color=black, ha='center', fontsize=20) - - - plt.xticks(np.arange(3, 9, 1)) - - plt.tight_layout() - - # uncomment to have numbers on top of the bars - # for bar in bars: - # height = bar.get_height() - # plt.text(bar.get_x() + bar.get_width()/2., height, - # f'{height:.2f}', - # ha='center', va='bottom') - - pdf_filename = ( - plots_dir + f"{parameter}_proportional_bar_{selector1}_vs_{selector2}.pdf" - ) - plt.savefig(pdf_filename) - print( - f"\nProportional bar plot saved to '{pdf_filename}' in the current working directory." - ) - plt.close() - - - - -def create_latex_command(parameters, filename): - f = open(filename, 'w') - - git_command = ["git", "rev-parse", "--short", "HEAD"] - result = subprocess.run( - git_command, cwd=ROOT_DIR_PATH, capture_output=True, text=True, check=True - ) - - commit_hash = result.stdout.strip() - - f.write(f"% Lean-mlir commit hash: {commit_hash}\n") - - f.write(f"% In the following commands the following rules apply:\n") - f.write(f"% A: class <1x\n") - f.write(f"% B: class 1x\n") - f.write(f"% C: class 1x-1.5x\n") - f.write(f"% D: class 1.5x-2x\n") - f.write(f"% E: class >2x\n") - f.write('\n\n') - - # print the percentage of programs in each of the above classes, for each number of instructions - for p in parameters: - df = pd.read_csv(data_dir + p + ".csv") - - df['ratios_gisel'] = df['LEANMLIR_opt_' + p] / df['LLVM_globalisel_' + p] - df['ratios_sdag'] = df['LEANMLIR_opt_' + p] / df['LLVM_selectiondag_' + p] - df['ratios_gisel_sdag'] = df['LLVM_globalisel_' + p] / df['LLVM_selectiondag_' + p] - df['ratios_gisel_class'] = df['ratios_gisel'].apply(lambda x: 'A' if x < 1 else 'B' if x == 1 else 'C' if x < 1.5 else 'D' if x < 2 else 'E') - df['ratios_sdag_class'] = df['ratios_sdag'].apply(lambda x: 'A' if x < 1 else 'B' if x == 1 else 'C' if x < 1.5 else 'D' if x < 2 else 'E') - df['ratios_gisel_sdag_class'] = df['ratios_gisel_sdag'].apply(lambda x: 'A' if x < 1 else 'B' if x == 1 else 'C' if x < 1.5 else 'D' if x < 2 else 'E') - - # max and min values - max_ratio_gisel = df["ratios_gisel"].max() - max_ratio_sdag = df["ratios_sdag"].max() - max_ratio_gisel_sdag = df["ratios_gisel_sdag"].max() - min_ratio_gisel = df["ratios_gisel"].min() - min_ratio_sdag = df["ratios_sdag"].min() - min_ratio_gisel_sdag = df["ratios_gisel_sdag"].min() - - if p == "tot_cycles": - p = 'NumCycles' - else: - p = 'NumInstr' - latex_command_max_gisel = f"\\newcommand{{\\MaxRatioLeanmlirVsGiselParam{p}}}{{{max_ratio_gisel:.2f}}}\n" - latex_command_max_sdag = f"\\newcommand{{\\MaxRatioLeanmlirVsSdagParam{p}}}{{{max_ratio_sdag:.2f}}}\n" - latex_command_max_gisel_sdag = f"\\newcommand{{\\MaxRatioGiselVsSdagParam{p}}}{{{max_ratio_gisel_sdag:.2f}}}\n" - latex_command_min_gisel = f"\\newcommand{{\\MinRatioLeanmlirVsGiselParam{p}}}{{{min_ratio_gisel:.2f}}}\n" - latex_command_min_sdag = f"\\newcommand{{\\MinRatioLeanmlirVsSdagParam{p}}}{{{min_ratio_sdag:.2f}}}\n" - latex_command_min_gisel_sdag = f"\\newcommand{{\\MinRatioGiselVsSdagParam{p}}}{{{min_ratio_gisel_sdag:.2f}}}\n" - - f.write(latex_command_max_gisel) - f.write(latex_command_max_sdag) - f.write(latex_command_min_gisel) - f.write(latex_command_min_sdag) - f.write(latex_command_max_gisel_sdag) - f.write(latex_command_min_gisel_sdag) - - - # calculate % of elements in each class - df_grouped_gisel = df.groupby('instructions_number')['ratios_gisel_class'].value_counts(normalize=True) * 100 - df_grouped_sdag = df.groupby('instructions_number')['ratios_sdag_class'].value_counts(normalize=True) * 100 - df_grouped_gisel_sdag = df.groupby('instructions_number')['ratios_gisel_sdag_class'].value_counts(normalize=True) * 100 - - - - # print a latex command for each percentage, specify in the name the class it belongs to - # and the `instructions_number` - - df_grouped_gisel = df_grouped_gisel.reset_index() - df_grouped_sdag = df_grouped_sdag.reset_index() - df_grouped_gisel_sdag = df_grouped_gisel_sdag.reset_index() - - for _, row in df_grouped_gisel.iterrows(): - c = row['ratios_gisel_class'] - percentage = row['proportion'] - instructions_number = num2words(row['instructions_number']) - latex_command = f"\\newcommand{{\\PercLeanmlirVsGiselParam{p}Class{c}Instr{instructions_number}}}{{{int(percentage)}\%}}\n" - f.write(latex_command) - for _, row in df_grouped_sdag.iterrows(): - c = row['ratios_sdag_class'] - percentage = row['proportion'] - instructions_number = num2words(row['instructions_number']) - latex_command = f"\\newcommand{{\\PercLeanmlirVsSdagParam{p}Class{c}Instr{instructions_number}}}{{{int(percentage)}\%}}\n" - f.write(latex_command) - - for _, row in df_grouped_gisel_sdag.iterrows(): - c = row['ratios_gisel_sdag_class'] - percentage = row['proportion'] - instructions_number = num2words(row['instructions_number']) - latex_command = f"\\newcommand{{\\PercGiselVsSdagParam{p}Class{c}Instr{instructions_number}}}{{{int(percentage)}\%}}\n" - f.write(latex_command) - - # geomean ratios and total geomeans - - geomeans_gisel = df.groupby('instructions_number')['ratios_gisel'].apply( - lambda x: np.exp(np.log(x).mean()) - ) - for instr_num, geomean_value in geomeans_gisel.items(): - instructions_number = num2words(instr_num) - latex_command = f"\\newcommand{{\\GeomeanLeanmlirVsGiselParam{p}Instr{instructions_number}}}{{{geomean_value:.1f}}}\n" - f.write(latex_command) - - geomeans_sdag = df.groupby('instructions_number')['ratios_sdag'].apply( - lambda x: np.exp(np.log(x).mean()) - ) - for instr_num, geomean_value in geomeans_sdag.items(): - instructions_number = num2words(instr_num) - latex_command = f"\\newcommand{{\\GeomeanLeanmlirVsSdagParam{p}Instr{instructions_number}}}{{{geomean_value:.1f}}}\n" - f.write(latex_command) - - # total geomeans - - geomean_gisel_tot = np.exp(np.log(df['ratios_gisel']).mean()) - latex_command_gisel_geomean = f"\\newcommand{{\\GeomeanTotLeanmlirVsGisel{p}}}{{{geomean_gisel_tot:.1f}}}\n" - f.write(latex_command_gisel_geomean) - - geomean_gisel_tot_perc = (np.exp(np.log(df['ratios_gisel']).mean()) - 1) * 100 - latex_command_gisel_geomean_perc = f"\\newcommand{{\\GeomeanTotLeanmlirVsGiselSlowDownPerc{p}}}{{{geomean_gisel_tot_perc:.1f}\%}}\n" - f.write(latex_command_gisel_geomean_perc) - - geomean_sdag_tot = np.exp(np.log(df['ratios_sdag']).mean()) - latex_command_sdag_geomean = f"\\newcommand{{\\GeomeanTotLeanmlirVsSdag{p}}}{{{geomean_sdag_tot:.1f}}}\n" - f.write(latex_command_sdag_geomean) - - geomean_sdag_tot_perc = (np.exp(np.log(df['ratios_sdag']).mean()) - 1) * 100 - latex_command_sdag_geomean_perc = f"\\newcommand{{\\GeomeanTotLeanmlirVsSdagSlowDownPerc{p}}}{{{geomean_sdag_tot_perc:.1f}\%}}\n" - f.write(latex_command_sdag_geomean_perc) - - - # print the percentage of programs that are identical, for each number of instructions - - df_similarity = pd.read_csv(data_dir + "similarity.csv") - - df_similarity_gisel = df_similarity.groupby('instructions_number')['is_eqv_LLVM_globalisel'].value_counts(normalize=True) * 100 - df_similarity_sdag = df_similarity.groupby('instructions_number')['is_eqv_LLVM_selectiondag'].value_counts(normalize=True) * 100 - - df_similarity_gisel = df_similarity_gisel.reset_index() - df_similarity_sdag = df_similarity_sdag.reset_index() - - for idx, row in df_similarity_gisel.iterrows(): - if row['is_eqv_LLVM_globalisel']: - percentage = row['proportion'] - instructions_number = num2words(row['instructions_number']) - latex_command = f"\\newcommand{{\\PercIdenticalGiselInstr{instructions_number}}}{{{int(percentage)}\%}}\n" - f.write(latex_command) - for idx, row in df_similarity_sdag.iterrows(): - if row['is_eqv_LLVM_selectiondag']: - percentage = row['proportion'] - instructions_number = num2words(row['instructions_number']) - latex_command = f"\\newcommand{{\\PercIdenticalSdagInstr{instructions_number}}}{{{int(percentage)}\%}}\n" - f.write(latex_command) - - # total similarity - - tot_similarity_gisel_true = df_similarity['is_eqv_LLVM_globalisel'].sum()/len(df_similarity)*100 - tot_similarity_sdag_true = df_similarity['is_eqv_LLVM_selectiondag'].sum()/len(df_similarity)*100 - - latex_command_similarity_tot_gisel = f"\\newcommand{{\\PercIdenticalGiselTot}}{{{tot_similarity_gisel_true:.1f}\%}}\n" - f.write(latex_command_similarity_tot_gisel) - latex_command_similarity_tot_sdag = f"\\newcommand{{\\PercIdenticalSdagTot}}{{{tot_similarity_sdag_true:.1f}\%}}\n" - f.write(latex_command_similarity_tot_sdag) - f.close() - - - - - - -def main(): - parser = argparse.ArgumentParser( - prog="plot", - description="Produce the plots to evaluate the performance of the Lean-MLIR certified Instruction Selection.", - ) - - parser.add_argument( - "-p", - "--parameters", - nargs="+", - choices=["tot_instructions", "tot_cycles", "tot_uops", "similarity", "all"], - default="all" - ) - - parser.add_argument( - "-t", - "--plot_type", - nargs="+", - choices=["scatter", "sorted", "stacked", "overhead", "violin", "all"], - default="all" - ) - - args = parser.parse_args() - - params_to_evaluate = ( - ["similarity", "tot_instructions", "tot_cycles", "tot_uops"] - if "all" in args.parameters - else args.parameters - ) - - plots_to_produce = ( - ["scatter", "sorted", "stacked", "overhead", "proportional", "violin"] - if "all" in args.plot_type - else args.plot_type - ) - - setup_benchmarking_directories() - for parameter in params_to_evaluate: - extract_data(LLVM_globalisel_results_DIR_PATH, "LLVM_globalisel", parameter) - extract_data(LLVM_selectiondag_results_DIR_PATH, "LLVM_selectiondag", parameter) - extract_data(LEANMLIR_opt_results_DIR_PATH, "LEANMLIR_opt", parameter) - - to_join = ["LEANMLIR_opt", "LLVM_globalisel", "LLVM_selectiondag"] - join_dataframes(to_join, parameter) - if parameter == "similarity": - continue - else: - # if "scatter" in plots_to_produce or "all" in plots_to_produce: - # scatter_plot(parameter, "LEANMLIR_opt", "LLVM_globalisel") - # scatter_plot(parameter, "LEANMLIR_opt", "LLVM_selectiondag") - # # scatter_plot(parameter, 'LLVM_globalisel', 'LLVM_selectiondag') - # if "sorted" in plots_to_produce or "all" in plots_to_produce: - # sorted_line_plot_all(parameter) - # sorted_line_plot(parameter, "LEANMLIR_opt", "LLVM_globalisel") - # sorted_line_plot(parameter, "LEANMLIR_opt", "LLVM_selectiondag") - # # sorted_line_plot(parameter, 'LLVM_globalisel', 'LLVM_selectiondag') - # if "overhead" in plots_to_produce or "all" in plots_to_produce: - # overhead_plot(parameter, "LEANMLIR_opt", "LLVM_globalisel") - # overhead_plot(parameter, "LEANMLIR_opt", "LLVM_selectiondag") - # # overhead_plot(parameter, 'LLVM_globalisel', 'LLVM_selectiondag') - if "stacked" in plots_to_produce or "all" in plots_to_produce: - bar_plot(parameter, "LEANMLIR_opt", "LLVM_globalisel") - bar_plot(parameter, "LEANMLIR_opt", "LLVM_selectiondag") - # bar_plot(parameter, 'LLVM_globalisel', 'LLVM_selectiondag') - if "violin" in plots_to_produce or "all" in plots_to_produce: - violin_plot(parameter, "LEANMLIR_opt", "LLVM_globalisel") - violin_plot(parameter, "LEANMLIR_opt", "LLVM_selectiondag") - violin_plot(parameter, "LLVM_globalisel", "LLVM_selectiondag") - # bar_plot(parameter, 'LLVM_globalisel', 'LLVM_selectiondag') - if "proportional" in plots_to_produce or "all" in plots_to_produce: - proportional_bar_plot(parameter, "LEANMLIR_opt", "LLVM_globalisel") - proportional_bar_plot(parameter, "LEANMLIR_opt", "LLVM_selectiondag") - - # proportional_bar_plot(parameter, 'LLVM_globalisel', 'LLVM_selectiondag') - - geomean_plot_tot_cycles() - equivalent_plot_perc() - create_latex_command(['tot_cycles', 'tot_instructions'], plots_dir + 'numerical_commands.tex') - -if __name__ == "__main__": - main() diff --git a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/pyproject.toml b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/pyproject.toml deleted file mode 100644 index 51b655b812..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/pyproject.toml +++ /dev/null @@ -1,12 +0,0 @@ -[project] -name = "mca-analysis" -version = "0.1.0" -description = "Add your description here" -readme = "README.md" -requires-python = ">=3.13" -dependencies = [ - "evallib", -] - -[tool.uv.sources] -evallib = { path = "../../../../../evallib" } diff --git a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/run_mca.py b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/run_mca.py deleted file mode 100755 index eeac73c358..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/run_mca.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env python3 - -import os -import shutil -import subprocess -import argparse -from evallib import taskqueue - -ROOT_DIR = ( - subprocess.check_output(["git", "rev-parse", "--show-toplevel"]) - .decode("utf-8") - .strip() -) -TIMEOUT = 1800 # seconds - -LLC_ASM_globalisel_DIR = ( - f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LLC_ASM_globalisel/" -) -LLC_ASM_selectiondag_DIR = ( - f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LLC_ASM_selectiondag/" -) -LLC_ASM_DIR = f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LLC_ASM/" -XDSL_ASM_DIR = f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/XDSL_ASM/" -XDSL_opt_ASM_DIR = ( - f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/XDSL_opt_ASM/" -) -MCA_LEANMLIR_DIR = ( - f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LEANMLIR/" -) -MCA_LEANMLIR_opt_DIR = ( - f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LEANMLIR_opt/" -) -MCA_LLVM_globalisel_DIR = f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LLVM_globalisel/" -MCA_LLVM_selectiondag_DIR = f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LLVM_selectiondag/" -LOGS_DIR = f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/logs/" - - -AUTOGEN_DIR_PATHS = [ - MCA_LEANMLIR_DIR, - MCA_LEANMLIR_opt_DIR, - MCA_LLVM_globalisel_DIR, - MCA_LLVM_selectiondag_DIR, - LOGS_DIR, -] - - -def setup_benchmarking_directories(): - """ - Create clean directories to store the benchmarks. - """ - results_dir = f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/" - if not os.path.exists(results_dir): - os.makedirs(results_dir) - for directory in AUTOGEN_DIR_PATHS: - if not os.path.exists(directory): - os.makedirs(directory) - else: - shutil.rmtree(directory) - os.makedirs(directory) - - -def run_command(cmd, log_file, timeout=TIMEOUT): - try: - print(cmd) - subprocess.Popen( - cmd, cwd=ROOT_DIR, stdout=log_file, stderr=log_file, shell=True - ).wait(timeout=timeout) - except subprocess.TimeoutExpired: - log_file.truncate(0) - log_file.write(f"timeout of {timeout} seconds reached\n") - print(f"{log_file} - timeout of {timeout} seconds reached") - - -def mca_analysis(input_file, output_file, log_file): - """ - Run MCA performance analysis on the RISCV asm `input_file`. - """ - cmd_base = "llvm-mca -mtriple=riscv64 -mcpu=sifive-u74 -mattr=+m,+zba,+zbb,+zbs " - cmd = cmd_base + input_file + " > " + output_file - run_command(cmd, log_file) - - -def run_tests(): - # clear results directory - setup_benchmarking_directories() - - # Parse CLI arguments - parser = argparse.ArgumentParser() - taskqueue.add_cli_arguments(parser) - - # idx = 0 - # for filename in os.listdir(XDSL_ASM_DIR): - # input_file = os.path.join(XDSL_ASM_DIR, filename) - # basename, _ = os.path.splitext(filename) - # output_file = os.path.join(MCA_LEANMLIR_DIR, basename + '.out') - # log_file = open(os.path.join(LOGS_DIR, 'xdsl_' + filename),'w') - # mca_analysis(input_file, output_file, log_file) - # idx += 1 - # percentage = ((float(idx) + float(1)) / float(len(os.listdir(XDSL_ASM_DIR)))) * 100 - # print(f"running mca analysis on lean-mlir asm: {percentage:.2f}%") - - idx = 0 - for filename in os.listdir(XDSL_opt_ASM_DIR): - input_file = os.path.join(XDSL_opt_ASM_DIR, filename) - basename, _ = os.path.splitext(filename) - output_file = os.path.join(MCA_LEANMLIR_opt_DIR, basename + ".out") - log_file = open(os.path.join(LOGS_DIR, "xdsl_opt_" + filename), "w") - mca_analysis(input_file, output_file, log_file) - idx += 1 - percentage = ( - (float(idx) + float(1)) / float(len(os.listdir(XDSL_opt_ASM_DIR))) - ) * 100 - print(f"running mca analysis on lean-mlir asm (opt): {percentage:.2f}%") - - idx = 0 - for filename in os.listdir(LLC_ASM_globalisel_DIR): - input_file = os.path.join(LLC_ASM_globalisel_DIR, filename) - basename, _ = os.path.splitext(filename) - output_file = os.path.join(MCA_LLVM_globalisel_DIR, basename + ".out") - log_file = open(os.path.join(LOGS_DIR, "llvm_globalisel_" + filename), "w") - mca_analysis(input_file, output_file, log_file) - idx += 1 - percentage = ( - (float(idx) + float(1)) / float(len(os.listdir(LLC_ASM_globalisel_DIR))) - ) * 100 - print(f"running mca analysis on llc asm (globalISel): {percentage:.2f}%") - - idx = 0 - for filename in os.listdir(LLC_ASM_selectiondag_DIR): - input_file = os.path.join(LLC_ASM_selectiondag_DIR, filename) - basename, _ = os.path.splitext(filename) - output_file = os.path.join(MCA_LLVM_selectiondag_DIR, basename + ".out") - log_file = open(os.path.join(LOGS_DIR, "llvm_selectiondag_" + filename), "w") - mca_analysis(input_file, output_file, log_file) - idx += 1 - percentage = ( - (float(idx) + float(1)) / float(len(os.listdir(LLC_ASM_selectiondag_DIR))) - ) * 100 - print(f"running mca analysis on llc asm (selectionDAG): {percentage:.2f}%") - - -def main(): - run_tests() - - -if __name__ == "__main__": - main() diff --git a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/similarity.py b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/similarity.py deleted file mode 100644 index 2fb92676a9..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/similarity.py +++ /dev/null @@ -1,72 +0,0 @@ -import csv -import io - -def compute_similarity(file_path): - """ - Computes the similarity between the last two numerical columns of the provided data - from a file. - - Args: - file_path (str): The path to the file containing the data. The file must - be a CSV with a header row. - - Returns: - None: Prints the results directly to the console. - """ - total_runs = 0 - identical_runs = 0 - - # Use a try-except block to handle potential file errors, such as the file - # not being found. - try: - # Open the file and wrap it in a file-like object for the csv reader - with open(file_path, 'r') as data_file: - reader = csv.reader(data_file) - - # Skip the header row - header = next(reader) - print(f"Analyzing data from file '{file_path}' with columns: {', '.join(header)}") - - # Iterate through each row in the data - for row in reader: - # Skip any empty lines - if not row: - continue - - # Get the two numbers to compare. We use a try-except block to handle - # any potential errors in data format (e.g., non-numeric values). - try: - # The columns 'SelectionDAG' and 'our' are the third and fourth columns, - # which are at index 2 and 3 in a 0-based list. - value_selection_dag = float(row[2]) - value_our = float(row[3]) - - # Increment the total number of runs - total_runs += 1 - # Compare the two values and increment the identical_runs counter if they are the same - if value_selection_dag == value_our : - identical_runs += 1 - - except (ValueError, IndexError) as e: - print(f"Skipping row due to data format error: {row}. Error: {e}") - except FileNotFoundError: - print(f"Error: The file '{file_path}' was not found.") - return - except Exception as e: - print(f"An unexpected error occurred: {e}") - return - - # Calculate the similarity percentage if there were any runs - similarity_percentage = 0 - if total_runs > 0: - similarity_percentage = (identical_runs / total_runs) * 100 - - # Print the final results - print("-" * 30) - print(f"Total number of runs analyzed: {total_runs}") - print(f"Number of runs where values were identical: {identical_runs}") - print(f"Similarity Percentage: {similarity_percentage:.2f}%") - print("-" * 30) - -if __name__ == "__main__": - compute_similarity("pivoted_instructions_for_plot.csv") diff --git a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/uv.lock b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/uv.lock deleted file mode 100644 index d660d961d1..0000000000 --- a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/uv.lock +++ /dev/null @@ -1,46 +0,0 @@ -version = 1 -revision = 3 -requires-python = ">=3.13" - -[[package]] -name = "colorama" -version = "0.4.6" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, -] - -[[package]] -name = "evallib" -version = "0.1.0" -source = { directory = "../../../../../evallib" } -dependencies = [ - { name = "tqdm" }, -] - -[package.metadata] -requires-dist = [{ name = "tqdm", specifier = ">=4.67.1" }] - -[[package]] -name = "mca-analysis" -version = "0.1.0" -source = { virtual = "." } -dependencies = [ - { name = "evallib" }, -] - -[package.metadata] -requires-dist = [{ name = "evallib", directory = "../../../../../evallib" }] - -[[package]] -name = "tqdm" -version = "4.67.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737, upload-time = "2024-11-24T20:12:22.481Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540, upload-time = "2024-11-24T20:12:19.698Z" }, -] From afe932e6904480dbd8cbb427512e8c8586d131ae Mon Sep 17 00:00:00 2001 From: luisacicolini Date: Thu, 16 Jul 2026 16:57:29 +0100 Subject: [PATCH 09/13] undo changes --- SSA/Projects/LLVMRiscV/Evaluation/.gitignore | 17 + .../LLVM-bug-reports/issue_53252.lean | 47 + .../LLVM-bug-reports/issue_59876.lean | 48 + .../LLVM-bug-reports/thesis_ex.lean | 297 + .../Evaluation/LLVM-tests/add-imm.lean | 274 + .../LLVM-tests/add-imm64-to-sub.lean | 163 + .../LLVM-tests/add_sext_shl_constant.lean | 217 + .../Evaluation/LLVM-tests/alu16.lean | 525 ++ .../Evaluation/LLVM-tests/alu32.lean | 591 ++ .../Evaluation/LLVM-tests/alu64.lean | 649 ++ .../benchmarks/MLIR_multi/output_3.mlir | 900 +++ .../benchmarks/MLIR_multi/output_4.mlir | 1000 +++ .../benchmarks/MLIR_multi/output_5.mlir | 1100 ++++ .../benchmarks/MLIR_multi/output_6.mlir | 1200 ++++ .../benchmarks/MLIR_multi/output_7.mlir | 1300 ++++ .../benchmarks/MLIR_multi/output_8.mlir | 1400 +++++ .../benchmarks/MLIR_multi/version_log.txt | 1 + .../LLVMRiscV/Evaluation/benchmarks/README.md | 60 + .../Evaluation/benchmarks/create_func.py | 58 + .../Evaluation/benchmarks/generate.py | 635 ++ .../Evaluation/benchmarks/generate_multi.py | 91 + .../compare-lowering-patterns/README.md | 33 + .../compare_lowerings.py | 440 ++ .../compare-lowering-patterns/comparison.log | 5370 +++++++++++++++++ .../isolated_instructions/llvm_add.mlir | 21 + .../isolated_instructions/llvm_and.mlir | 7 + .../isolated_instructions/llvm_ashr.mlir | 7 + .../isolated_instructions/llvm_icmp.mlir | 70 + .../isolated_instructions/llvm_mul.mlir | 21 + .../isolated_instructions/llvm_or.mlir | 7 + .../isolated_instructions/llvm_rem.mlir | 7 + .../isolated_instructions/llvm_sdiv.mlir | 7 + .../isolated_instructions/llvm_select.mlir | 7 + .../isolated_instructions/llvm_sext.mlir | 28 + .../isolated_instructions/llvm_shl.mlir | 28 + .../isolated_instructions/llvm_srl.mlir | 7 + .../isolated_instructions/llvm_sub.mlir | 21 + .../isolated_instructions/llvm_trunc.mlir | 7 + .../isolated_instructions/llvm_udiv.mlir | 7 + .../isolated_instructions/llvm_urem.mlir | 7 + .../isolated_instructions/llvm_xor.mlir | 7 + .../isolated_instructions/llvm_zext.mlir | 28 + .../run_comparison.sh | 5 + .../Evaluation/mca-analysis/.python-version | 1 + .../Evaluation/mca-analysis/README.md | 42 + .../LLVMRiscV/Evaluation/mca-analysis/plot.py | 1043 ++++ .../Evaluation/mca-analysis/pyproject.toml | 12 + .../Evaluation/mca-analysis/run_mca.py | 147 + .../Evaluation/mca-analysis/similarity.py | 72 + .../LLVMRiscV/Evaluation/mca-analysis/uv.lock | 46 + 50 files changed, 18078 insertions(+) create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/.gitignore create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/issue_53252.lean create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/issue_59876.lean create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/thesis_ex.lean create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add-imm.lean create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add-imm64-to-sub.lean create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add_sext_shl_constant.lean create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu16.lean create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu32.lean create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu64.lean create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_3.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_4.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_5.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_6.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_7.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_8.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/version_log.txt create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/README.md create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/create_func.py create mode 100755 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/generate.py create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/benchmarks/generate_multi.py create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/README.md create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/compare_lowerings.py create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/comparison.log create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_add.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_and.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_ashr.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_icmp.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_mul.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_or.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_rem.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sdiv.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_select.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sext.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_shl.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_srl.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sub.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_trunc.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_udiv.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_urem.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_xor.mlir create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_zext.mlir create mode 100755 SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/run_comparison.sh create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/.python-version create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/README.md create mode 100755 SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/plot.py create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/pyproject.toml create mode 100755 SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/run_mca.py create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/similarity.py create mode 100644 SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/uv.lock diff --git a/SSA/Projects/LLVMRiscV/Evaluation/.gitignore b/SSA/Projects/LLVMRiscV/Evaluation/.gitignore new file mode 100644 index 0000000000..f98b5e7882 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/.gitignore @@ -0,0 +1,17 @@ +benchmarks/MLIR_single +benchmarks/MLIR_bb0 +benchmarks/LEANMLIR_ASM +benchmarks/LEANMLIR_ASM_opt +benchmarks/LLC_ASM_globalisel +benchmarks/LLC_ASM_selectiondag +benchmarks/LLVM +benchmarks/LLVMIR +benchmarks/logs +benchmarks/XDSL_ASM +benchmarks/XDSL_FUNC +benchmarks/XDSL_FUNC_opt +benchmarks/XDSL_opt_ASM +mca-analysis/results +mca-analysis/data +mca-analysis/tables +mca-analysis/plots \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/issue_53252.lean b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/issue_53252.lean new file mode 100644 index 0000000000..29cb72fca9 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/issue_53252.lean @@ -0,0 +1,47 @@ +import SSA.Projects.RISCV64.PrettyEDSL +import LeanMLIR.Framework +import SSA.Projects.LLVMRiscV.PeepholeRefine +import SSA.Projects.LLVMRiscV.Simpproc +import SSA.Projects.RISCV64.Tactic.SimpRiscV +import SSA.Projects.LLVMRiscV.Pipeline.mkRewrite + +/-! + Bug reported in https://github.com/llvm/llvm-project/issues/53252 + and fixed in https://github.com/llvm/llvm-project/commit/4041c44853588c1e4918ec4a160c053cf08432b5 +-/ + +namespace BitVec +open LLVMRiscV + +@[simp_denote] +def original := [LV| { + ^entry (%x : i32, %replacement_low : i32, %replacement_high : i32): + %0 = llvm.mlir.constant (0) : i32 + %t0 = llvm.icmp.slt %x, %0 : i32 + %t1 = llvm.select %t0, %replacement_low, %replacement_high : i32 + %65536 = llvm.mlir.constant (65536) : i32 + %t2 = llvm.icmp.ult %x, %65536 : i32 + %true = llvm.mlir.constant (true) : i1 + %1 = llvm.xor %t2, %true : i1 + %r = llvm.select %1, %x, %t1 : i32 + llvm.return %r : i32 +}] + +@[simp_denote] +def optimized_incorrect := [LV| { + ^entry (%x : i32, %replacement_low : i32, %replacement_high : i32): + %0 = llvm.mlir.constant (0) : i32 + %1 = llvm.icmp.slt %x, %0 : i32 + %65535 = llvm.mlir.constant (65535) : i32 + %2 = llvm.icmp.sgt %x, %65535 : i32 + %3 = llvm.select %1, %replacement_low, %x : i32 + %4 = llvm.select %2, %replacement_high, %3 : i32 + llvm.return %4 : i32 + }] + +def bug : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where + lhs:= original + rhs:= optimized_incorrect + correct := by + simp_lowering + <;> sorry diff --git a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/issue_59876.lean b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/issue_59876.lean new file mode 100644 index 0000000000..877a3acb45 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/issue_59876.lean @@ -0,0 +1,48 @@ +import SSA.Projects.RISCV64.PrettyEDSL +import LeanMLIR.Framework +import SSA.Projects.LLVMRiscV.PeepholeRefine +import SSA.Projects.LLVMRiscV.Simpproc +import SSA.Projects.RISCV64.Tactic.SimpRiscV +import SSA.Projects.LLVMRiscV.Pipeline.mkRewrite + +/-! + Bug reported in https://github.com/llvm/llvm-project/issues/59876 +-/ + +namespace BitVec +open LLVMRiscV + +@[simp_denote] +def original := [LV| { + ^entry (%x : i1): + %1 = llvm.mlir.constant (1) : i1 + %0 = llvm.mul %x, %1 : i1 + llvm.return %0 : i1 +}] + +@[simp_denote] +def optimized_incorrect := [LV| { + ^entry (%x : i1): + %0 = llvm.mlir.constant (0) : i1 + llvm.return %0 : i1 + }] + +@[simp_denote] +def optimized_correct := [LV| { + ^entry (%x : i1): + llvm.return %x : i1 + }] + +def bug : LLVMPeepholeRewriteRefine 1 [Ty.llvm (.bitvec 1)] where + lhs:= original + rhs:= optimized_incorrect + correct := by + simp_lowering + <;> sorry + +def fix : LLVMPeepholeRewriteRefine 1 [Ty.llvm (.bitvec 1)] where + lhs:= original + rhs:= optimized_correct + correct := by + simp_lowering + bv_decide diff --git a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/thesis_ex.lean b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/thesis_ex.lean new file mode 100644 index 0000000000..81ad3e1ea5 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-bug-reports/thesis_ex.lean @@ -0,0 +1,297 @@ +import SSA.Projects.RISCV64.PrettyEDSL +import LeanMLIR.Framework +import SSA.Projects.LLVMRiscV.PeepholeRefine +import SSA.Projects.LLVMRiscV.Simpproc +import SSA.Projects.RISCV64.Tactic.SimpRiscV +import SSA.Projects.LLVMRiscV.Pipeline.mkRewrite + +namespace BitVec +open LLVMRiscV +-- background LEAN +theorem add_eq_sll (a : Nat) : a + a = a <<< 1 := by omega -- + +-- implementing reported SelectionDAG bug +def original_sdiv_srem := [LV| { + ^entry (%a: i64, %b: i64): + %0= llvm.sdiv exact %a, %b : i64 + %1 = llvm.srem %a, %b : i64 + llvm.return %1 : i64 + }] + +def combined_sdiv_srem := [LV| { + ^entry (%a: i64, %b: i64): + %0= llvm.sdiv exact %a, %b : i64 + %1 = llvm.mul %b, %0 : i64 + %2 = llvm.sub %a, %1 : i64 + llvm.return %2 : i64 + }] + +theorem mul_sdiv_cancel_of_dvd_of_ne {w : Nat} {x y : BitVec w} + (h₁ : y.smod x = 0#_) + (h₂ : y ≠ intMin w ∨ x ≠ -1#w) : + x * y.sdiv x = y := by + apply eq_of_toInt_eq + simp only [toInt_mul] + rw [BitVec.toInt_sdiv_of_ne_or_ne _ _ h₂] + rw [← BitVec.toInt_inj, BitVec.toInt_smod, BitVec.toInt_zero] at h₁ + rw [Int.mul_tdiv_cancel' (Int.dvd_of_fmod_eq_zero h₁)] + exact toInt_bmod_cancel y + +theorem srem_eq_zero_of_smod {w : Nat} {x y : BitVec w} : + x.smod y = 0#_ → x.srem y = 0#_ := by + simp only [← toInt_inj, toInt_smod, toInt_zero, toInt_srem] + intro h + simp [Int.tmod_eq_fmod, Int.dvd_of_fmod_eq_zero h, h] + +def buggy_ISEL_pattern : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where + lhs:= original_sdiv_srem + rhs:= combined_sdiv_srem + correct := by + unfold original_sdiv_srem combined_sdiv_srem + simp_peephole + simp_alive_undef + simp_alive_ops + simp_alive_case_bash + intro x x1 + split + case value.value.isTrue ht => + simp [ht] + case value.value.isFalse hf => + simp + split + case isTrue ht => + simp [ht, hf] + simp at hf + obtain ⟨hf₁, hf₂⟩ := hf + replace hf₂ : x ≠ intMin _ ∨ x1 ≠ -1#64 := by + by_cases h : x = intMin _ + · exact .inr <| hf₂ h + · exact .inl h + simp only [mul_sdiv_cancel_of_dvd_of_ne ht hf₂, BitVec.sub_self] + apply srem_eq_zero_of_smod ht + case isFalse hf => + sorry + -- sorry -- this case shows how the pattern is wrong in the case of an exact flag. + +def original_sdiv_srem_correct := [LV| { + ^entry (%a: i64, %b: i64): + %0= llvm.sdiv %a, %b : i64 + %1 = llvm.srem %a, %b : i64 + llvm.return %1 : i64 + }] + +def combined_sdiv_srem_correct := [LV| { + ^entry (%a: i64, %b: i64): + %0= llvm.sdiv %a, %b : i64 + %1 = llvm.mul %b, %0 : i64 + %2 = llvm.sub %a, %1 : i64 + llvm.return %2 : i64 + }] + +theorem srem_eq_sub_sdiv (x y : BitVec w) (h1 : ¬y = 0#_ ) (hf₂ : x ≠ intMin w ∨ y ≠ -1#w) : + x.srem y = x - y * x.sdiv y := by + rw [← toInt_inj] + rw [BitVec.toInt_srem] + rw [BitVec.toInt_sub] + rw [BitVec.toInt_mul] + simp + rw [BitVec.toInt_sdiv_of_ne_or_ne x y (h:= hf₂)] + rw [ Int.bmod_eq_of_le (by sorry) (by sorry)] + rw [Int.tmod_def] +-- x x1 : BitVec 64 +-- hf₁ : ¬x1 = 0#64 +-- hf₂ : x ≠ intMin 64 ∨ x1 ≠ sorry +-- ⊢ x.srem x1 = x - x1 * x.sdiv x1 + + +def corrected_ISEL_pattern : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where + lhs:= original_sdiv_srem_correct + rhs:= combined_sdiv_srem_correct + correct := by + unfold original_sdiv_srem_correct combined_sdiv_srem_correct + simp_peephole + simp_alive_undef + simp_alive_ops + simp_alive_case_bash + intro x x1 + split + case value.value.isFalse hf => + simp at hf + obtain ⟨hf₁, hf₂⟩ := hf + replace hf₂ : x ≠ intMin _ ∨ x1 ≠ -1#64 := by + by_cases h : x = intMin _ + · exact .inr <| hf₂ h + · exact .inl h + simp only [PoisonOr.value_isRefinedBy_value, InstCombine.bv_isRefinedBy_iff] + --bv_decide + sorry + --simp [hf₁, hf₂] + case value.value.isTrue ht => + simp only [PoisonOr.isRefinedBy_self] + +def llvm_sub_self_ex := [LV| { + ^entry (%x: i64 ): + %1 = llvm.sub %x, %x : i64 + llvm.return %1 : i64 + }] + + -- simp riscv example + +@[simp_denote] +def sub_riscv_self_ex := [LV| { + ^entry (%x: i64): + %0 = "builtin.unrealized_conversion_cast"(%x) : (i64) -> (!i64) + %2 = sub %0, %0 : !i64 + %4 = sltu %0, %0 : !i64 + %3 = "builtin.unrealized_conversion_cast"(%2) : (!i64) -> (i64) + llvm.return %3 : i64 + }] + + + +def example00 := [RV64_com| { +^bb0(%0 : !riscv.reg, %1 : !riscv.reg): + %2 = "slt"(%0, %1) : (!riscv.reg, !riscv.reg) -> (!riscv.reg) + %3 = "andi" (%2){imm = 1 : !i64} : (!riscv.reg) -> (!riscv.reg) + %4 = "sra"(%0, %0) : (!riscv.reg, !riscv.reg) -> (!riscv.reg) + %5 = "add"(%0, %0) : (!riscv.reg, !riscv.reg) -> (!riscv.reg) + %6 = "sra"(%2, %5) : (!riscv.reg, !riscv.reg) -> (!riscv.reg) + "ret" (%0) : (!riscv.reg) -> () + }].denote + + +def example01 := [RV64_com| { +^bb0(%0 : !i64, %1 : !i64): + --%2 = "riscv.slt"(%0, %1) : (!riscv.reg, !riscv.reg) -> (!riscv.reg) + --%2 = "riscv.andi"(%2){immediate = 1 : i12 } : (!riscv.reg) -> (!riscv.reg) + -- %4 = "riscv.sra"(%0, %0) : (!riscv.reg, !riscv.reg) -> (!riscv.reg) + %5 = "add"(%0, %0) : (!i64, !i64) -> (!i64) + --%6 = "riscv.sra"(%2, %5) : (!riscv.reg, !riscv.reg) -> (!riscv.reg) + "ret" (%0) : (!i64) -> () + }] + + + +def llvm_sub_lower_riscv_no_flag_self: LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := llvm_sub_self_ex + rhs := sub_riscv_self_ex + correct := by + unfold llvm_sub_self_ex sub_riscv_self_ex + simp_peephole + simp_alive_undef + simp_alive_ops + simp_alive_case_bash + simp_riscv + simp_peephole + sorry + + +@[simp_denote] +def llvm_urem: Com LLVMPlusRiscV ⟨[.llvm (.bitvec 64), .llvm (.bitvec 64)]⟩ + .pure (.llvm (.bitvec 64)) := [LV| { + ^entry (%x: i64, %y: i64 ): + %1 = llvm.urem %x, %y : i64 + llvm.return %1 : i64 + }] +@[simp_denote] +def urem_riscv: Com LLVMPlusRiscV ⟨[.llvm (.bitvec 64), .llvm (.bitvec 64)]⟩ + .pure (.llvm (.bitvec 64)) := [LV| { + ^entry (%reg1: i64, %reg2: i64): + %0 = "builtin.unrealized_conversion_cast"(%reg1) : (i64) -> (!i64) + %1 = "builtin.unrealized_conversion_cast"(%reg2) : (i64) -> (!i64) + %2 = remu %0, %1 : !i64 + %3 = "builtin.unrealized_conversion_cast"(%2) : (!i64) -> (i64) + llvm.return %3 : i64 + }] + def llvm_urem_lower_riscv: LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] := + {lhs := llvm_urem, rhs := urem_riscv } + + +def intro_example_lhs := [LV| { + ^entry (%arg: i64, %amount: i64): + %0 = llvm.shl %arg, %amount : i64 + %1 = llvm.lshr %0, %amount : i64 + llvm.return %1 : i64 + }] + +def intro_example_rhs := [LV| { + ^entry (%arg: i64, %amount: i64): + llvm.return %arg : i64 + }] + +def rewrite00 : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where + lhs:= [LV| { + ^entry (%arg: i64, %amount: i64): + %0 = llvm.shl %arg, %amount : i64 + %1 = llvm.lshr %0, %amount : i64 + llvm.return %1 : i64 + }] + + rhs:= [LV| { + ^entry (%arg: i64, %amount: i64): + llvm.return %arg : i64 + }] + correct := by + simp_lowering + sorry + --bv_decide + +@[simp_denote] +def intro_example_correct_lhs := [LV| { + ^entry (%arg0: i64): + %c = llvm.mlir.constant (4) : i64 + %1 = llvm.mul %arg0, %c : i64 + llvm.return %1 : i64 + }] + +@[simp_denote] +def intro_example_correct_rhs := [LV| { + ^entry (%arg0: i64): + %r1 = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!riscv.reg) + %c = slli %r1, 2 : !riscv.reg + %rd = "builtin.unrealized_conversion_cast" (%c) : (!riscv.reg) -> (i64) + llvm.return %rd : i64 + }] + +def selection00 : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs:= [LV| { + ^entry (%arg0: i64): + %c = llvm.mlir.constant (4) : i64 + %1 = llvm.mul %arg0, %c : i64 + llvm.return %1 : i64 + }] + rhs:= [LV| { + ^entry (%arg0: i64): + %r1 = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!riscv.reg) + %c = slli %r1, 2 : !riscv.reg + %rd = "builtin.unrealized_conversion_cast" (%c) : (!riscv.reg) -> (i64) + llvm.return %rd : i64 + }] + + +/- Below are two example programs to test our instruction selector.-/ +def llvm00:= + [LV|{ + ^bb0(%X : i64, %Y : i64 ): + %1 = llvm.add %X, %Y : i64 + %2 = llvm.sub %X, %X : i64 + %3 = llvm.add %1, %Y : i64 + %4 = llvm.add %3, %Y : i64 + %5 = llvm.add %3, %4 : i64 + llvm.return %5 : i64 + }] +def llvm01:= + [LV|{ + ^bb0(%X : i64, %Y : i64 ): + %1 = llvm.icmp.eq %X, %Y : i64 + %2 = llvm.sub %X, %X : i64 + llvm.return %1 : i1 + }] + +def llvm02:= + [LV|{ + ^bb0(%X : i64, %Y : i64 ): + %1 = llvm.mlir.constant 9 : i64 + %2 = llvm.sub %X, %X : i64 + llvm.return %1 : i64 + }] diff --git a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add-imm.lean b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add-imm.lean new file mode 100644 index 0000000000..23952ce1d0 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add-imm.lean @@ -0,0 +1,274 @@ +import SSA.Projects.LLVMRiscV.Pipeline.InstructionLowering + +open LLVMRiscV + +/-! + This file implements the `add-imm.ll` test case in the LLVM test suite: + https://github.com/llvm/llvm-project/blob/b424207cdddfa2cbfc9129bbe0a31e47cb04e6dc/llvm/test/CodeGen/RISCV/add-imm.ll +-/ + + +/-- ### add_positive_low_bound_reject -/ +@[simp_denote] +def add_positive_low_bound_reject_llvm := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (2047) : i32 + %1 = llvm.add %a, %0 : i32 + llvm.return %1 :i32 + }] + +@[simp_denote] +def add_positive_low_bound_reject_riscv := + [LV| { + ^entry (%arg: i32): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %0 = addiw %a, 2047 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) + llvm.return %1 :i32 + }] + +def add_positive_low_bound_reject_test: LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := add_positive_low_bound_reject_llvm + rhs := add_positive_low_bound_reject_riscv + + +/-- ### add_positive_low_bound_accept -/ +@[simp_denote] +def add_positive_low_bound_accept_llvm := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (2048) : i32 + %1 = llvm.add %0, %a : i32 + llvm.return %1 :i32 + }] + +@[simp_denote] +def add_positive_low_bound_accept_riscv := + [LV| { + ^entry (%arg: i32): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %0 = addi %a, 2047 : !i64 + %1 = addiw %0, 1 : !i64 + %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) + llvm.return %2 :i32 + }] + +def add_positive_low_bound_accept_test: LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := add_positive_low_bound_accept_llvm + rhs := add_positive_low_bound_accept_riscv + +/-- ### add_positive_high_bound_accept -/ +@[simp_denote] +def add_positive_high_bound_accept_llvm := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (4094) : i32 + %1 = llvm.add %0, %a : i32 + llvm.return %1 :i32 + }] + +@[simp_denote] +def add_positive_high_bound_accept_riscv := + [LV| { + ^entry (%arg: i32): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %0 = addi %a, 2047 : !i64 + %1 = addiw %0, 2047 : !i64 + %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) + llvm.return %2 :i32 + }] + +def add_positive_high_bound_accept_test: LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := add_positive_high_bound_accept_llvm + rhs := add_positive_high_bound_accept_riscv + + +/-- ### add_positive_high_bound_reject -/ +@[simp_denote] +def add_positive_high_bound_reject_llvm := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (4095) : i32 + %1 = llvm.add %0, %a : i32 + llvm.return %1 :i32 + }] + +@[simp_denote] +def add_positive_high_bound_reject_riscv := + [LV| { + ^entry (%arg: i32): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %0 = li (843949575) : !i64 + %1 = "lui" (%0) {imm = 1 : !i64} : (!i64) -> (!i64) + %2 = "addi" (%1) {imm = -1 : !i64} : (!i64) -> (!i64) + %3 = addw %2, %a: !i64 + %4 = "builtin.unrealized_conversion_cast" (%3) : (!i64) -> (i32) + llvm.return %4 :i32 + }] + +def add_positive_high_bound_reject_test: LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := add_positive_high_bound_reject_llvm + rhs := add_positive_high_bound_reject_riscv + + +/-- ### add_negative_high_bound_reject -/ +@[simp_denote] +def add_negative_high_bound_reject_llvm := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (-2048) : i32 + %1 = llvm.add %a, %0 : i32 + llvm.return %1 :i32 + }] + +@[simp_denote] +def add_negative_high_bound_reject_riscv := + [LV| { + ^entry (%arg: i32): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %0 = "addiw" (%a) {imm = -2048 : !i64} : (!i64) -> (!i64) + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) + llvm.return %1 :i32 + }] + +def add_negative_high_bound_reject_test: LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := add_negative_high_bound_reject_llvm + rhs := add_negative_high_bound_reject_riscv + + +/-- ### add_negative_high_bound_accept -/ +@[simp_denote] +def add_negative_high_bound_accept_llvm := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (-2049) : i32 + %1 = llvm.add %a, %0 : i32 + llvm.return %1 : i32 +}] + +@[simp_denote] +def add_negative_high_bound_accept_riscv := [LV| { + ^entry (%arg: i32): + %0 = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %1 = "addiw" (%0) {imm = -2048 : !i64} : (!i64) -> (!i64) + %2 = "addiw" (%1) {imm = -1 : !i64} : (!i64) -> (!i64) + %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i32) + llvm.return %3 : i32 +}] + +def add_negative_high_bound_accept_test: LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := add_negative_high_bound_accept_llvm + rhs := add_negative_high_bound_accept_riscv + +/-- ### add_negative_low_bound_accept -/ +@[simp_denote] +def add_negative_low_bound_accept_llvm := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (-4096) : i32 + %1 = llvm.add %a, %0 : i32 + llvm.return %1 : i32 +}] + +@[simp_denote] +def add_negative_low_bound_accept_riscv := [LV| { + ^entry (%arg: i32): + %0 = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %1 = "addi" (%0) {imm = -2048 : !i64} : (!i64) -> (!i64) + %2 = "addiw" (%1) {imm = -2048 : !i64} : (!i64) -> (!i64) + %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i32) + llvm.return %3 : i32 +}] + +def add_negative_low_bound_accept_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := add_negative_low_bound_accept_llvm + rhs := add_negative_low_bound_accept_riscv + +/-- ### add_negative_low_bound_reject -/ +@[simp_denote] +def add_negative_low_bound_reject_llvm := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (-4097) : i32 + %1 = llvm.add %a, %0 : i32 + llvm.return %1 : i32 +}] + +@[simp_denote] +def add_negative_low_bound_reject_riscv := [LV| { + ^entry (%arg: i32): + %0 = li (843949575) : !i64 -- random value bc can make any assumption in the value of a1 + %1 = "lui" (%0) {imm = 1048575 : !i64} : (!i64) -> (!i64) + %2 = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %3 = "addi" (%1) {imm = -1 : !i64} : (!i64) -> (!i64) + %4 = addw %2, %3 : !i64 + %5 = "builtin.unrealized_conversion_cast" (%4) : (!i64) -> (i32) + llvm.return %5 : i32 +}] + +def add_negative_low_bound_reject_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := add_negative_low_bound_reject_llvm + rhs := add_negative_low_bound_reject_riscv + +/-- ### add32_accept -/ +@[simp_denote] +def add32_accept_llvm := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (2999) : i32 + %1 = llvm.add %a, %0 : i32 + llvm.return %1 : i32 +}] + +@[simp_denote] +def add32_accept_riscv := [LV| { + ^entry (%arg: i32): + %0 = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %1 = "addi" (%0) {imm = 2047 : !i64} : (!i64) -> (!i64) + %2 = addiw %1, 952 : !i64 + %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i32) + llvm.return %3 : i32 +}] + +def add32_accept_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := add32_accept_llvm + rhs := add32_accept_riscv + +/-- ### add32_sext_accept -/ +@[simp_denote] +def add32_sext_accept_llvm := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (2999) : i32 + %1 = llvm.add %a, %0 : i32 + llvm.return %1 : i32 +}] + +@[simp_denote] +def add32_sext_accept_riscv := [LV| { + ^entry (%arg: i32): + %0 = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64)-- sext performed here + %1 = "addi" (%0) {imm = 2047 : !i64} : (!i64) -> (!i64) + %2 = addiw %1, 952 : !i64 + %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i32) + llvm.return %3 : i32 +}] + +def add32_sext_accept_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := add32_sext_accept_llvm + rhs := add32_sext_accept_riscv + + +/-- ### add64_accept -/ +@[simp_denote] +def add64_accept_llvm := [LV| { + ^entry (%a: i64): + %0 = llvm.mlir.constant (2999) : i64 + %1 = llvm.add %a, %0 : i64 + llvm.return %1 : i64 +}] + +@[simp_denote] +def add64_accept_riscv := [LV| { + ^entry (%arg: i64): + %0 = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64)-- sext performed here + %1 = addi %0, 2047 : !i64 + %2 = addi %1, 952 : !i64 + %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i64) + llvm.return %3 : i64 +}] + +def add64_accept_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := add64_accept_llvm + rhs := add64_accept_riscv diff --git a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add-imm64-to-sub.lean b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add-imm64-to-sub.lean new file mode 100644 index 0000000000..9d07cf8148 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add-imm64-to-sub.lean @@ -0,0 +1,163 @@ +import SSA.Projects.LLVMRiscV.Pipeline.InstructionLowering + +open LLVMRiscV + +/-! + This file implements the `add-imm.ll` test case in the LLVM test suite: + https://github.com/llvm/llvm-project/blob/b424207cdddfa2cbfc9129bbe0a31e47cb04e6dc/llvm/test/CodeGen/RISCV/add-imm64-to-sub.ll +-/ + +/-- ### add_b31 -/ +@[simp_denote] +def add_b31_llvm_i64 := [LV| { + ^entry (%x: i64): + %0 = llvm.mlir.constant (2147483648) : i64 + %1 = llvm.add %x, %0 : i64 + llvm.return %1 : i64 + }] + +@[simp_denote] +def add_b31_riscv_i64 := + [LV| { + ^entry (%x: i64): + %random = li (574385585755) : !i64 + %0 = "lui" (%random) {imm = 524288 : !i64} : (!i64) -> (!i64) + %a0 = "builtin.unrealized_conversion_cast" (%x) : (i64) -> (!i64) + %1 = sub %a0, %0 : !i64 + %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i64) + llvm.return %2 : i64 + }] + +@[simp_denote] +def add_b31_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := add_b31_llvm_i64 + rhs := add_b31_riscv_i64 + + +/-- ### add_b32 -/ +@[simp_denote] +def add_b32_llvm_i64 := [LV| { + ^entry (%x: i64): + %0 = llvm.mlir.constant (-4294967296) : i64 + %1 = llvm.add %x, %0 : i64 + llvm.return %1 : i64 + }] + +@[simp_denote] +def add_b32_riscv_i64_no_ZBS := + [LV| { + ^entry (%x: i64): + %0 ="li"() {imm = -1 : !i64} : (!i64) -> (!i64) + %1 = slli %0, 32 : !i64 + %a0 = "builtin.unrealized_conversion_cast" (%x) : (i64) -> (!i64) + %2 = add %a0, %1 : !i64 + %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i64) + llvm.return %3 : i64 + }] + +@[simp_denote] +def add_b32_riscv_i64_ZBS := + [LV| { + ^entry (%x: i64): + %zero ="li"() {imm = 0 : !i64} : (!i64) -> (!i64) + %a1 = bseti %zero, 32 : !i64 + %a0 = "builtin.unrealized_conversion_cast" (%x) : (i64) -> (!i64) + %0 = sub %a0, %a1 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) + llvm.return %1 : i64 + }] + +def add_b32_test_no_ZBS_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := add_b32_llvm_i64 + rhs := add_b32_riscv_i64_no_ZBS + + +def add_b32_test_ZBS_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := add_b32_llvm_i64 + rhs := add_b32_riscv_i64_ZBS + + +/-- ### sub_0xffffffffff -/ +@[simp_denote] +def sub_0xffffffffff_llvm_i64 := [LV| { + ^entry (%x: i64): + %0 = llvm.mlir.constant (1099511627775) : i64 + %1 = llvm.sub %x, %0 : i64 + llvm.return %1 : i64 + }] + +@[simp_denote] +def sub_0xffffffffff_riscv_i64 := + [LV| { + ^entry (%x: i64): + %0 = "li"() {imm = -1 : !i64} : (!i64) -> (!i64) + %1 = srli %0, 24 : !i64 + %a0 = "builtin.unrealized_conversion_cast" (%x) : (i64) -> (!i64) + %2 = sub %a0, %1 : !i64 + %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i64) + llvm.return %3 : i64 + }] + +def sub_0xffffffffff_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := sub_0xffffffffff_llvm_i64 + rhs := sub_0xffffffffff_riscv_i64 + + +/-- ### add_multiuse -/ +@[simp_denote] +def add_multiuse_llvm_i64 := [LV| { + ^entry (%x: i64): + %0 = llvm.mlir.constant (-1099511627775) : i64 + %1 = llvm.add %x, %0 : i64 + %2 = llvm.and %1, %0 : i64 + llvm.return %2 : i64 + }] + +@[simp_denote] +def add_multiuse_riscv_i64 := + [LV| { + ^entry (%x: i64): + %0 = "li"() {imm = -1 : !i64} : (!i64) -> (!i64) + %1 = slli %0, 40 : !i64 + %2 = addi %1, 1 : !i64 + %a0 = "builtin.unrealized_conversion_cast" (%x) : (i64) -> (!i64) + %3 = add %a0, %2 : !i64 + %4 = and %3, %2 : !i64 + %5 = "builtin.unrealized_conversion_cast" (%4) : (!i64) -> (i64) + llvm.return %5 : i64 + }] + +def add_multiuse_riscv_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := add_multiuse_llvm_i64 + rhs := add_multiuse_riscv_i64 + + +/-- ### add_multiuse_const -/ +@[simp_denote] +def add_multiuse_const_llvm_i64 := [LV| { + ^entry (%x: i64, %y: i64): + %0 = llvm.mlir.constant (-1099511627775) : i64 + %1 = llvm.add %x, %0 : i64 + %2 = llvm.add %y, %0 : i64 + %3 = llvm.xor %1, %2 : i64 + llvm.return %3 : i64 + }] + +@[simp_denote] +def add_multiuse_const_riscv_i64 := + [LV| { + ^entry (%x: i64, %y: i64): + %0 = "li"() {imm = -1 : !i64} : (!i64) -> (!i64) + %1 = srli %0, 24 : !i64 + %a0 = "builtin.unrealized_conversion_cast" (%x) : (i64) -> (!i64) + %2 = sub %a0, %1 : !i64 + %a1 = "builtin.unrealized_conversion_cast" (%y) : (i64) -> (!i64) + %3 = sub %a1, %1 : !i64 + %4 = xor %2, %3 : !i64 + %5 = "builtin.unrealized_conversion_cast" (%4) : (!i64) -> (i64) + llvm.return %5 : i64 + }] + +def add_multiuse_const_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64) ] where + lhs := add_multiuse_const_llvm_i64 + rhs := add_multiuse_const_riscv_i64 diff --git a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add_sext_shl_constant.lean b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add_sext_shl_constant.lean new file mode 100644 index 0000000000..89bbba9c9e --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/add_sext_shl_constant.lean @@ -0,0 +1,217 @@ +import SSA.Projects.LLVMRiscV.Pipeline.InstructionLowering + +open LLVMRiscV + +/-! + This file implements the `add_sext_shl_constant.ll` test case in the LLVM test suite: + https://github.com/llvm/llvm-project/blob/b424207cdddfa2cbfc9129bbe0a31e47cb04e6dc/llvm/test/CodeGen/RISCV/add_sext_shl_constant.ll +-/ + +/-- ### add_shl_moreOneUse_sh1add -/ +@[simp_denote] +def add_shl_moreOneUse_sh1add := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (1) : i32 + %1 = llvm.or %a, %0 : i32 + %2 = llvm.shl %1, %0 : i32 + %3 = llvm.add %2, %1 : i32 + llvm.return %3 : i32 + }] + +@[simp_denote] +def add_shl_moreOneUse_sh1add_riscv_no_ZBA := [LV| { + ^entry (%a: i32): + %a0 = "builtin.unrealized_conversion_cast" (%a) : (i32) -> (!i64) + %0 = ori %a0, 1 : !i64 + %1 = slli %a0, 1 : !i64 + %2 = ori %1, 2 : !i64 + %3 = add %2, %0 : !i64 + %4 = "builtin.unrealized_conversion_cast" (%3) : (!i64) -> (i32) + llvm.return %4 : i32 + }] + +@[simp_denote] +def add_shl_moreOneUse_sh1add_riscv_ZBA := [LV| { + ^entry (%a: i32): + %a0 = "builtin.unrealized_conversion_cast" (%a) : (i32) -> (!i64) + %0 = ori %a0, 1 : !i64 + %1 = sh1add %0, %0 : !i64 + %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) + llvm.return %2 : i32 + }] + +def add_shl_moreOneUse_sh1add_ZBA_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := add_shl_moreOneUse_sh1add + rhs := add_shl_moreOneUse_sh1add_riscv_ZBA + + +def add_shl_moreOneUse_sh1add_no_ZBA_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := add_shl_moreOneUse_sh1add + rhs := add_shl_moreOneUse_sh1add_riscv_no_ZBA + +/-- ### add_shl_moreOneUse_sh2add -/ +@[simp_denote] +def add_shl_moreOneUse_sh2add := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (1) : i32 + %c2 = llvm.mlir.constant (2) : i32 + %1 = llvm.or %a, %0 : i32 + %2 = llvm.shl %1, %c2 : i32 + %3 = llvm.add %2, %1 : i32 + llvm.return %3 : i32 + }] + +@[simp_denote] +def add_shl_moreOneUse_sh2add_riscv_no_ZBA := [LV| { + ^entry (%a: i32): + %a0 = "builtin.unrealized_conversion_cast" (%a) : (i32) -> (!i64) + %0 = ori %a0, 1 : !i64 + %1 = slli %a0, 2 : !i64 + %2 = ori %1, 4 : !i64 + %3 = add %2, %0 : !i64 + %4 = "builtin.unrealized_conversion_cast" (%3) : (!i64) -> (i32) + llvm.return %4 : i32 + }] + +@[simp_denote] +def add_shl_moreOneUse_sh2add_riscv_ZBA := [LV| { + ^entry (%a: i32): + %a0 = "builtin.unrealized_conversion_cast" (%a) : (i32) -> (!i64) + %0 = ori %a0, 1 : !i64 + %1 = sh2add %0, %0 : !i64 + %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) + llvm.return %2 : i32 + }] + +def add_shl_moreOneUse_sh2add_ZBA_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := add_shl_moreOneUse_sh2add + rhs := add_shl_moreOneUse_sh2add_riscv_ZBA + +def add_shl_moreOneUse_sh2add_no_ZBA_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := add_shl_moreOneUse_sh2add + rhs := add_shl_moreOneUse_sh2add_riscv_no_ZBA + +/-- ### add_shl_moreOneUse_sh3add -/ +@[simp_denote] +def add_shl_moreOneUse_sh3add := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (1) : i32 + %c2 = llvm.mlir.constant (3) : i32 + %1 = llvm.or %a, %0 : i32 + %2 = llvm.shl %1, %c2 : i32 + %3 = llvm.add %2, %1 : i32 + llvm.return %3 : i32 + }] + +@[simp_denote] +def add_shl_moreOneUse_sh3add_riscv_no_ZBA := [LV| { + ^entry (%a: i32): + %a0 = "builtin.unrealized_conversion_cast" (%a) : (i32) -> (!i64) + %0 = ori %a0, 1 : !i64 + %1 = slli %a0, 3 : !i64 + %2 = ori %1, 8 : !i64 + %3 = add %2, %0 : !i64 + %4 = "builtin.unrealized_conversion_cast" (%3) : (!i64) -> (i32) + llvm.return %4 : i32 + }] + +@[simp_denote] +def add_shl_moreOneUse_sh3add_riscv_ZBA := [LV| { + ^entry (%a: i32): + %a0 = "builtin.unrealized_conversion_cast" (%a) : (i32) -> (!i64) + %0 = ori %a0, 1 : !i64 + %1 = sh3add %0, %0 : !i64 + %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) + llvm.return %2 : i32 + }] + +def add_shl_moreOneUse_sh3add_ZBA_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := add_shl_moreOneUse_sh3add + rhs := add_shl_moreOneUse_sh3add_riscv_ZBA + +def add_shl_moreOneUse_sh3add_no_ZBA_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := add_shl_moreOneUse_sh3add + rhs := add_shl_moreOneUse_sh3add_riscv_no_ZBA + + +/-- ### add_shl_sext -/ +@[simp_denote] +def add_shl_sext_llvm := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (3) : i32 + %1 = llvm.add %a, %0 : i32 + %2 = llvm.shl %1, %a : i32 + %3 = llvm.sext %2 : i32 to i64 + llvm.return %3 : i64 + }] + +@[simp_denote] +def add_shl_sext_riscv := [LV| { + ^entry (%a: i32): + %a0 = "builtin.unrealized_conversion_cast" (%a) : (i32) -> (!i64) + %0 = addi %a0, 3 : !i64 + %1 = sllw %0, %a0 : !i64 + %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i64) + llvm.return %2 : i64 + }] + +def add_shl_sext_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 32)] where + lhs := add_shl_sext_llvm + rhs := add_shl_sext_riscv + +/-- ### add_shl_moreOneUse_sh4add -/ +@[simp_denote] +def add_shl_moreOneUse_sh4add_llvm := [LV| { + ^entry (%a: i64): + %0 = llvm.mlir.constant (1) : i64 + %c4 = llvm.mlir.constant (4) : i64 + %1 = llvm.or %a, %0 : i64 + %2 = llvm.shl %1, %c4 : i64 + %3 = llvm.add %1, %2 : i64 + llvm.return %3 : i64 + }] + +@[simp_denote] +def add_shl_moreOneUse_sh4add_riscv := [LV| { + ^entry (%a: i64): + %a0 = "builtin.unrealized_conversion_cast" (%a) : (i64) -> (!i64) + %0 = ori %a0, 1 : !i64 + %1 = slli %a0, 4 : !i64 + %2 = ori %1, 16 : !i64 + %3 = add %2, %0 : !i64 + %4 = "builtin.unrealized_conversion_cast" (%3) : (!i64) -> (i64) + llvm.return %4 : i64 + }] + +def add_shl_moreOneUse_sh4add_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := add_shl_moreOneUse_sh4add_llvm + rhs :=add_shl_moreOneUse_sh4add_riscv + +/-- ### add_shl_rhs_constant -/ +@[simp_denote] +def add_shl_rhs_constant_llvm := [LV| { + ^entry (%a0: i64, %a1: i64): + %0 = llvm.mlir.constant (1) : i64 + %c3 = llvm.mlir.constant (3) : i64 + %c8 = llvm.mlir.constant (-8) : i64 + %1 = llvm.add %a0, %0 : i64 + %2 = llvm.add %a1, %1 : i64 + %3 = llvm.shl %2, %c3 : i64 + %4 = llvm.add %3, %c8 : i64 + llvm.return %4 : i64 + }] + +@[simp_denote] +def add_shl_rhs_constant_riscv := [LV| { + ^entry (%a: i64, %b: i64): + %a0 = "builtin.unrealized_conversion_cast" (%a) : (i64) -> (!i64) + %a1 = "builtin.unrealized_conversion_cast" (%b) : (i64) -> (!i64) + %0 = add %a0, %a1 : !i64 + %1 = slli %0, 3 : !i64 + %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i64) + llvm.return %2 : i64 + }] + +def add_shl_rhs_constant_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64),Ty.llvm (.bitvec 64) ] where + lhs := add_shl_rhs_constant_llvm + rhs := add_shl_rhs_constant_riscv diff --git a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu16.lean b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu16.lean new file mode 100644 index 0000000000..20d9c3afb1 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu16.lean @@ -0,0 +1,525 @@ +import SSA.Projects.LLVMRiscV.Pipeline.InstructionLowering + + +open LLVMRiscV + +/-! + This file implements the `alu16.ll` test case in the LLVM test suite: + https://github.com/llvm/llvm-project/blob/b424207cdddfa2cbfc9129bbe0a31e47cb04e6dc/llvm/test/CodeGen/RISCV/alu16.ll +-/ + + +/-- ### addi -/ +@[simp_denote] +def addi_llvm := [LV| { + ^entry (%a: i16): + %0 = llvm.mlir.constant (1) : i16 + %1 = llvm.add %a, %0 : i16 + llvm.return %1 :i16 + }] + +@[simp_denote] +def addi_riscv := + [LV| { + ^entry (%arg: i16): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) + %0 = addi %a, 1 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) + llvm.return %1 :i16 + }] + +def addi_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where + lhs := addi_llvm + rhs := addi_riscv + + +/-- ### slti -/ +@[simp_denote] +def slti_llvm := [LV| { + ^entry (%a: i16): + %0 = llvm.mlir.constant (2) : i16 + %1 = llvm.icmp.slt %a, %0 : i16 + %2 = llvm.zext %1: i1 to i16 + llvm.return %2 :i16 + }] + +@[simp_denote] +def slti_riscv := + [LV| { + ^entry (%arg: i16): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) + %0 = slli %a, 48 : !i64 + %1 = srai %0, 48 : !i64 + %2 = slti %1, 2 : !i64 + %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i16) + llvm.return %3 :i16 + }] + +def slti_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where + lhs := slti_llvm + rhs := slti_riscv + + +/-- ### sltiu -/ +@[simp_denote] +def sltiu_llvm := [LV| { + ^entry (%a: i16): + %0 = llvm.mlir.constant (3) : i16 + %1 = llvm.icmp.ult %a, %0 : i16 + %2 = llvm.zext %1: i1 to i16 + llvm.return %2 :i16 + }] + +@[simp_denote] +def sltiu_riscv := + [LV| { + ^entry (%arg: i16): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) + %0 = slli %a, 48 : !i64 + %1 = srli %0, 48 : !i64 + %2 = sltiu %1, 3 : !i64 + %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i16) + llvm.return %3 :i16 + }] + +def sltiu_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where + lhs := sltiu_llvm + rhs := sltiu_riscv + + +/-- ### sltiu_signext -/ +@[simp_denote] +def sltiu_signext_llvm := [LV| { + ^entry (%a: i16): + %0 = llvm.mlir.constant (10) : i16 + %1 = llvm.icmp.ult %a, %0 : i16 + %2 = llvm.zext %1: i1 to i16 + llvm.return %2 :i16 + }] + +@[simp_denote] +def sltiu_signext_riscv := + [LV| { + ^entry (%arg: i16): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) + %0 = sltiu %a, 10 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) + llvm.return %1 :i16 + }] + +def sltiu_signext_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where + lhs := sltiu_signext_llvm + rhs := sltiu_signext_riscv + + +/-- ### xori -/ +@[simp_denote] +def xori_llvm := [LV| { + ^entry (%a: i16): + %0 = llvm.mlir.constant (4) : i16 + %1 = llvm.xor %a, %0 : i16 + llvm.return %1 :i16 + }] + +@[simp_denote] +def xori_riscv := + [LV| { + ^entry (%arg: i16): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) + %0 =xori %a, 4 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) + llvm.return %1 :i16 + }] + +def xori_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where + lhs := xori_llvm + rhs := xori_riscv + + +/-- ### ori -/ +@[simp_denote] +def ori_llvm := [LV| { + ^entry (%a: i16): + %0 = llvm.mlir.constant (5) : i16 + %1 = llvm.or %a, %0 : i16 + llvm.return %1 :i16 + }] + +@[simp_denote] +def ori_riscv := + [LV| { + ^entry (%arg: i16): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) + %0 =ori %a, 5 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) + llvm.return %1 :i16 + }] + +def ori_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where + lhs := ori_llvm + rhs := ori_riscv + + +/-- ### andi -/ +@[simp_denote] +def andi_llvm := [LV| { + ^entry (%a: i16): + %0 = llvm.mlir.constant (6) : i16 + %1 = llvm.and %a, %0 : i16 + llvm.return %1 :i16 + }] + +@[simp_denote] +def andi_riscv := + [LV| { + ^entry (%arg: i16): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) + %0 =andi %a, 6 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) + llvm.return %1 :i16 + }] + +def andi_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where + lhs := andi_llvm + rhs := andi_riscv + + +/-- ### slli -/ +@[simp_denote] +def slli_llvm := [LV| { + ^entry (%a: i16): + %0 = llvm.mlir.constant (7) : i16 + %1 = llvm.shl %a, %0 : i16 + llvm.return %1 :i16 + }] + +@[simp_denote] +def slli_riscv := + [LV| { + ^entry (%arg: i16): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) + %0 =slli %a, 7 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) + llvm.return %1 :i16 + }] + +def slli_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where + lhs := slli_llvm + rhs := slli_riscv + + +/-- ### srli -/ +@[simp_denote] +def srli_llvm := [LV| { + ^entry (%a: i16): + %0 = llvm.mlir.constant (6) : i16 + %1 = llvm.lshr %a, %0 : i16 + llvm.return %1 :i16 + }] + +@[simp_denote] +def srli_riscv := + [LV| { + ^entry (%arg: i16): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) + %0 =slli %a, 48 : !i64 + %1 =srli %0, 54 : !i64 + %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i16) + llvm.return %2 :i16 + }] + +def srli_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where + lhs := srli_llvm + rhs := srli_riscv + + +/-- ### srai -/ +@[simp_denote] +def srai_llvm := [LV| { + ^entry (%a: i16): + %0 = llvm.mlir.constant (9) : i16 + %1 = llvm.ashr %a, %0 : i16 + llvm.return %1 :i16 + }] + +@[simp_denote] +def srai_riscv := + [LV| { + ^entry (%arg: i16): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i16) -> (!i64) + %0 =slli %a, 48 : !i64 + %1 =srai %0, 57 : !i64 + %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i16) + llvm.return %2 :i16 + }] + +def srai_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16)] where + lhs := srai_llvm + rhs := srai_riscv + + +/-- ### add -/ +@[simp_denote] +def add_llvm_i16:= [LV| { + ^entry (%a: i16,%b: i16 ): + %0 = llvm.add %a, %b : i16 + llvm.return %0 :i16 + }] + +@[simp_denote] +def add_riscv_i16 := + [LV| { + ^entry (%arg0: i16, %arg1: i16 ): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) + %0 =add %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) + llvm.return %1 :i16 + }] + +def add_i16_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where + lhs := add_llvm_i16 + rhs := add_riscv_i16 + + +/-- ### sub -/ +@[simp_denote] +def sub_llvm_i16:= [LV| { + ^entry (%a: i16,%b: i16 ): + %0 = llvm.sub %a, %b : i16 + llvm.return %0 :i16 + }] + +@[simp_denote] +def sub_riscv_i16 := + [LV| { + ^entry (%arg0: i16, %arg1: i16 ): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) + %0 =sub %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) + llvm.return %1 :i16 + }] + +def sub_i16_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where + lhs := sub_llvm_i16 + rhs := sub_riscv_i16 + correct := by + unfold sub_llvm_i16 sub_riscv_i16 + simp_peephole + simp_riscv + simp_alive_undef + simp_alive_case_bash + simp_alive_split + all_goals simp; bv_decide + + +/-- ### sll -/ +@[simp_denote] +def sll_llvm_i16:= [LV| { + ^entry (%a: i16,%b: i16 ): + %0 = llvm.shl %a, %b : i16 + llvm.return %0 :i16 + }] + +@[simp_denote] +def sll_riscv_i16 := + [LV| { + ^entry (%arg0: i16, %arg1: i16 ): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) + %0 =sll %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) + llvm.return %1 :i16 + }] + +def sll_i16_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where + lhs := sll_llvm_i16 + rhs := sll_riscv_i16 + correct := by + unfold sll_llvm_i16 sll_riscv_i16 + simp_lowering + bv_decide + + +/-- ### slt -/ +@[simp_denote] +def slt_llvm := [LV| { + ^entry (%a: i16, %b: i16 ): + %0 = llvm.icmp.slt %a, %b : i16 + %1 = llvm.zext %0: i1 to i16 + llvm.return %1 :i16 + }] + +@[simp_denote] +def slt_riscv := + [LV| { + ^entry (%arg0: i16, %arg1: i16 ): + %a0 = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) + %a1 = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) + %0 = slli %a1, 48 : !i64 + %1 = slli %a0, 48 : !i64 + %2 = srai %1, 48 : !i64 + %3 = srai %0, 48 : !i64 + %4 = slt %2, %3 : !i64 + %5 = "builtin.unrealized_conversion_cast" (%4) : (!i64) -> (i16) + llvm.return %5 :i16 + }] + +def slt_signext_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where + lhs := slt_llvm + rhs := slt_riscv + + +/-- ### sltu -/ +@[simp_denote] +def sltu_llvm := [LV| { + ^entry (%a: i16, %b: i16 ): + %0 = llvm.icmp.ult %a, %b : i16 + %1 = llvm.zext %0: i1 to i16 + llvm.return %1 :i16 + }] + +@[simp_denote] +def sltu_riscv := + [LV| { + ^entry (%arg0: i16, %arg1: i16): + %a0 = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) + %a1 = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) + %0 = li (149595403036) : !i64 -- random value bc reg can hold anything + %1 = "lui" (%0) {imm = 16 : !i64} : (!i64) -> (!i64) + %2 = "addi" (%1) {imm = -1 : !i64} : (!i64) -> (!i64) + %3 = and %2, %a1 : !i64 + %4 = and %2, %a0 : !i64 + %5 = sltu %4, %3 : !i64 + %6 = "builtin.unrealized_conversion_cast" (%5) : (!i64) -> (i16) + llvm.return %6 :i16 + }] + +def sltu_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where + lhs := sltu_llvm + rhs := sltu_riscv + + +/-- ### xor -/ +@[simp_denote] +def xor_llvm_i16:= [LV| { + ^entry (%a: i16,%b: i16 ): + %0 = llvm.xor %a, %b : i16 + llvm.return %0 :i16 + }] + +@[simp_denote] +def xor_riscv_i16 := + [LV| { + ^entry (%arg0: i16, %arg1: i16 ): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) + %0 = xor %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) + llvm.return %1 :i16 + }] + +def xor_i16_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where + lhs := xor_llvm_i16 + rhs := xor_riscv_i16 + + +/-- ### srl -/ +@[simp_denote] +def srl_llvm_i16 := [LV| { + ^entry (%a: i16, %b: i16 ): + %0 = llvm.lshr %a, %b : i16 + llvm.return %0 :i16 + }] + +@[simp_denote] +def srl_riscv_i16 := + [LV| { + ^entry (%arg0: i16, %arg1: i16): + %a0 = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) + %a1 = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) + %0 = slli %a0, 48 : !i64 + %1 = srli %0, 48 : !i64 + %2 = srl %1, %a1 : !i64 + %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i16) + llvm.return %3 :i16 + }] + +def srl_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where + lhs := srl_llvm_i16 + rhs := srl_riscv_i16 + + +/-- ### sra -/ +@[simp_denote] +def sra_llvm_i16 := [LV| { + ^entry (%a: i16, %b: i16 ): + %0 = llvm.ashr %a, %b : i16 + llvm.return %0 :i16 + }] + +@[simp_denote] +def sra_riscv_i16 := + [LV| { + ^entry (%arg0: i16, %arg1: i16): + %a0 = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) + %a1 = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) + %0 = slli %a0, 48 : !i64 + %1 = srai %0, 48 : !i64 + %2 = sra %1, %a1 : !i64 + %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i16) + llvm.return %3 :i16 + }] + +def sra_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where + lhs := sra_llvm_i16 + rhs := sra_riscv_i16 + + +/-- ### or -/ +@[simp_denote] +def or_llvm_i16:= [LV| { + ^entry (%a: i16,%b: i16 ): + %0 = llvm.or %a, %b : i16 + llvm.return %0 :i16 + }] + +@[simp_denote] +def or_riscv_i16 := + [LV| { + ^entry (%arg0: i16, %arg1: i16 ): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) + %0 = or %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) + llvm.return %1 :i16 + }] + +def or_i16_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where + lhs := or_llvm_i16 + rhs := or_riscv_i16 + + +/-- ### and -/ +@[simp_denote] +def and_llvm_i16:= [LV| { + ^entry (%a: i16,%b: i16 ): + %0 = llvm.and %a, %b : i16 + llvm.return %0 :i16 + }] + +@[simp_denote] +def and_riscv_i16 := + [LV| { + ^entry (%arg0: i16, %arg1: i16 ): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i16) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i16) -> (!i64) + %0 = and %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i16) + llvm.return %1 :i16 + }] + +def and_i16_test: LLVMPeepholeRewriteRefine 16 [Ty.llvm (.bitvec 16), Ty.llvm (.bitvec 16) ] where + lhs := and_llvm_i16 + rhs := and_riscv_i16 diff --git a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu32.lean b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu32.lean new file mode 100644 index 0000000000..b6cb530bd3 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu32.lean @@ -0,0 +1,591 @@ +import SSA.Projects.LLVMRiscV.Pipeline.InstructionLowering + +open LLVMRiscV + +/-! + This file implements the `alu32.ll` test case in the LLVM test suite: + https://github.com/llvm/llvm-project/blob/b424207cdddfa2cbfc9129bbe0a31e47cb04e6dc/llvm/test/CodeGen/RISCV/alu32.ll +-/ + +/-- addi -/ +@[simp_denote] +def addi_llvm_i32 := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (1) : i32 + %1 = llvm.add %a, %0 : i32 + llvm.return %1 : i32 + }] + +@[simp_denote] +def addi_riscv_i32 := + [LV| { + ^entry (%arg: i32): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %0 = addiw %a, 1 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) + llvm.return %1 : i32 + }] + +def addi_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := addi_llvm_i32 + rhs := addi_riscv_i32 + + +/-- ### slti -/ +@[simp_denote] +def slti_llvm_i32 := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (2) : i32 + %1 = llvm.icmp.slt %a, %0 : i32 + %2 = llvm.zext %1 : i1 to i32 + llvm.return %2 : i32 + }] + +@[simp_denote] +def slti_riscv_i32 := + [LV| { + ^entry (%arg: i32): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %0 = "sext.w" (%a) : (!i64) -> (!i64) + %1 = slti %0, 2 : !i64 + %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) + llvm.return %2 : i32 + }] + +def slti_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := slti_llvm_i32 + rhs := slti_riscv_i32 + + +/-- ### sltiu -/ +@[simp_denote] +def sltiu_llvm_i32 := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (3) : i32 + %1 = llvm.icmp.ult %a, %0 : i32 + %2 = llvm.zext %1 : i1 to i32 + llvm.return %2 : i32 + }] + +@[simp_denote] +def sltiu_riscv_i32 := + [LV| { + ^entry (%arg: i32): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %0 = "sext.w" (%a) :(!i64) -> (!i64) + %1 = sltiu %0, 3 : !i64 + %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) + llvm.return %2 : i32 + }] + +def sltiu_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := sltiu_llvm_i32 + rhs := sltiu_riscv_i32 + + +/-- ### xori -/ +@[simp_denote] +def xori_llvm_i32 := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (4) : i32 + %1 = llvm.xor %a, %0 : i32 + llvm.return %1 : i32 + }] + +@[simp_denote] +def xori_riscv_i32 := + [LV| { + ^entry (%arg: i32): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %0 = xori %a, 4 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) + llvm.return %1 : i32 + }] + +def xori_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := xori_llvm_i32 + rhs := xori_riscv_i32 + + +/-- ### ori -/ +@[simp_denote] +def ori_llvm_i32 := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (5) : i32 + %1 = llvm.or %a, %0 : i32 + llvm.return %1 : i32 + }] + +@[simp_denote] +def ori_riscv_i32 := + [LV| { + ^entry (%arg: i32): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %0 = ori %a, 5 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) + llvm.return %1 : i32 + }] + +def ori_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := ori_llvm_i32 + rhs := ori_riscv_i32 + + +/-- ### andi -/ +@[simp_denote] +def andi_llvm_i32 := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (6) : i32 + %1 = llvm.and %a, %0 : i32 + llvm.return %1 : i32 + }] + +@[simp_denote] +def andi_riscv_i32 := + [LV| { + ^entry (%arg: i32): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %0 = andi %a, 6 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) + llvm.return %1 : i32 + }] + +def andi_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := andi_llvm_i32 + rhs := andi_riscv_i32 + +/-- ### slli -/ +@[simp_denote] +def slli_llvm_i32 := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (7) : i32 + %1 = llvm.shl %a, %0 : i32 + llvm.return %1 : i32 + }] + +@[simp_denote] +def slli_riscv_i32 := + [LV| { + ^entry (%arg: i32): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %0 = slliw %a, 7 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) + llvm.return %1 : i32 + }] + +def slli_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := slli_llvm_i32 + rhs := slli_riscv_i32 + + +/-- ### srli -/ +@[simp_denote] +def srli_llvm_i32 := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (8) : i32 + %1 = llvm.lshr %a, %0 : i32 + llvm.return %1 : i32 + }] + +@[simp_denote] +def srli_riscv_i32 := + [LV| { + ^entry (%arg: i32): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %0 = srliw %a, 8 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) + llvm.return %1 : i32 + }] + +def srli_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := srli_llvm_i32 + rhs := srli_riscv_i32 + +/-- ### srli_demandedbits -/ +@[simp_denote] +def srli_demandedbits_llvm_i32 := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (3) : i32 + %1 = llvm.lshr %a, %0 : i32 + %2 = llvm.mlir.constant (1) : i32 + %3 = llvm.or %1, %2 : i32 + llvm.return %3 : i32 + }] + +@[simp_denote] +def srli_demandedbits_riscv_i32 := + [LV| { + ^entry (%arg: i32): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %0 = srliw %a, 3 : !i64 + %1 = ori %0, 1 : !i64 + %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) + llvm.return %2 : i32 + }] + +def srli_demandedbits_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := srli_demandedbits_llvm_i32 + rhs := srli_demandedbits_riscv_i32 + +/-- ### srai -/ +@[simp_denote] +def srai_llvm_i32 := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (9) : i32 + %1 = llvm.ashr %a, %0 : i32 + llvm.return %1 : i32 + }] + +@[simp_denote] +def srai_riscv_i32 := + [LV| { + ^entry (%arg: i32): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %0 = sraiw %a, 9 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) + llvm.return %1 : i32 + }] + +def srai_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := srai_llvm_i32 + rhs := srai_riscv_i32 + +/-- ### add -/ +@[simp_denote] +def add_llvm_i32 := [LV| { + ^entry (%a: i32, %b: i32): + %0 = llvm.add %a, %b : i32 + llvm.return %0 : i32 + }] + +@[simp_denote] +def add_riscv_i32 := + [LV| { + ^entry (%arg0: i32, %arg1: i32): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) + %0 = addw %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) + llvm.return %1 : i32 + }] + +def add_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where + lhs := add_llvm_i32 + rhs := add_riscv_i32 + +/-- ### sub -/ +@[simp_denote] +def sub_llvm_i32 := [LV| { + ^entry (%a: i32, %b: i32): + %0 = llvm.sub %a, %b : i32 + llvm.return %0 : i32 + }] + +@[simp_denote] +def sub_riscv_i32 := + [LV| { + ^entry (%arg0: i32, %arg1: i32): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) + %0 = subw %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) + llvm.return %1 : i32 + }] + +def sub_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where + lhs := sub_llvm_i32 + rhs := sub_riscv_i32 + + +/-- ### sub -/ +@[simp_denote] +def sub_negative_constant_lhs_llvm_i32 := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (-2) : i32 + %1 = llvm.sub %0, %a : i32 + llvm.return %1 : i32 + }] + +@[simp_denote] +def sub_negative_constant_lhs_riscv_i32 := + [LV| { + ^entry (%arg: i32): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %a1 = "li" () {imm = -2 : !i64} : (!i64) -> (!i64) + %1 = subw %a1, %a : !i64 + %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) + llvm.return %2 : i32 + }] + +def sub_negative_constant_lhs_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := sub_negative_constant_lhs_llvm_i32 + rhs := sub_negative_constant_lhs_riscv_i32 + +/-- ### sll -/ +@[simp_denote] +def sll_llvm_i32 := [LV| { + ^entry (%a: i32, %b: i32): + %0 = llvm.shl %a, %b : i32 + llvm.return %0 : i32 + }] + +@[simp_denote] +def sll_riscv_i32 := + [LV| { + ^entry (%arg0: i32, %arg1: i32): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) + %0 = sllw %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) + llvm.return %1 : i32 + }] + +def sll_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where + lhs := sll_llvm_i32 + rhs := sll_riscv_i32 + +/-- ### sll_negative_constant_lhs -/ +@[simp_denote] +def sll_negative_constant_lhs_llvm_i32 := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (-1) : i32 + %1 = llvm.shl %0, %a : i32 + llvm.return %1 : i32 + }] + +@[simp_denote] +def sll_negative_constant_lhs_riscv_i32 := + [LV| { + ^entry (%arg: i32): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %0 = "li" () {imm = -1 : !i64} : (!i64) -> (!i64) + %1 = sllw %0, %a : !i64 + %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) + llvm.return %2 : i32 + }] + +def sll_negative_constant_lhs_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := sll_negative_constant_lhs_llvm_i32 + rhs := sll_negative_constant_lhs_riscv_i32 + +/-- ### slt -/ +@[simp_denote] +def slt_llvm_i32 := [LV| { + ^entry (%a: i32, %b: i32): + %0 = llvm.icmp.slt %a, %b : i32 + %1 = llvm.zext %0 : i1 to i32 + llvm.return %1 : i32 + }] + +@[simp_denote] +def slt_riscv_i32 := + [LV| { + ^entry (%arg0: i32, %arg1: i32): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) + %0 = sext.w %a : !i64 + %1 = sext.w %b : !i64 + %2 = slt %0, %1 : !i64 + %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i32) + llvm.return %3 : i32 + }] + +def slt_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where + lhs := slt_llvm_i32 + rhs := slt_riscv_i32 + + +/-- ### sltu -/ +@[simp_denote] +def sltu_llvm_i32 := [LV| { + ^entry (%a: i32, %b: i32): + %0 = llvm.icmp.ult %a, %b : i32 + %1 = llvm.zext %0 : i1 to i32 + llvm.return %1 : i32 + }] + +@[simp_denote] +def sltu_riscv_i32 := + [LV| { + ^entry (%arg0: i32, %arg1: i32): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) + %0 = "sext.w" (%a) : (!i64) -> (!i64) + %1 = "sext.w" (%b) : (!i64) -> (!i64) + %2 = sltu %0, %1 : !i64 + %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i32) + llvm.return %3 : i32 + }] + +def sltu_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where + lhs := sltu_llvm_i32 + rhs := sltu_riscv_i32 + +/-- ### xor -/ +@[simp_denote] +def xor_llvm_i32 := [LV| { + ^entry (%a: i32, %b: i32): + %0 = llvm.xor %a, %b : i32 + llvm.return %0 : i32 + }] + +@[simp_denote] +def xor_riscv_i32 := + [LV| { + ^entry (%arg0: i32, %arg1: i32): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) + %0 = xor %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) + llvm.return %1 : i32 + }] + +def xor_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where + lhs := xor_llvm_i32 + rhs := xor_riscv_i32 + + +/-- ### srl -/ +@[simp_denote] +def srl_llvm_i32 := [LV| { + ^entry (%a: i32, %b: i32): + %0 = llvm.lshr %a, %b : i32 + llvm.return %0 : i32 + }] + +@[simp_denote] +def srl_riscv_i32 := + [LV| { + ^entry (%arg0: i32, %arg1: i32): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) + %0 = srlw %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) + llvm.return %1 : i32 + }] + +def srl_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where + lhs := srl_llvm_i32 + rhs := srl_riscv_i32 + + +/-- ### srl_negative_constant_lhs -/ +@[simp_denote] +def srl_negative_constant_lhs_llvm_i32 := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (-1) : i32 + %1 = llvm.lshr %0, %a : i32 + llvm.return %1 : i32 + }] + +@[simp_denote] +def srl_negative_constant_lhs_riscv_i32 := + [LV| { + ^entry (%arg: i32): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %0 = "li" () {imm = -1 : !i64} : (!i64) -> (!i64) + %1 = srlw %0, %a : !i64 + %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) + llvm.return %2 : i32 + }] + +def srl_negative_constant_lhs_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := srl_negative_constant_lhs_llvm_i32 + rhs := srl_negative_constant_lhs_riscv_i32 + + +/-- ### sra -/ +@[simp_denote] +def sra_llvm_i32 := [LV| { + ^entry (%a: i32, %b: i32): + %0 = llvm.ashr %a, %b : i32 + llvm.return %0 : i32 + }] + +@[simp_denote] +def sra_riscv_i32 := + [LV| { + ^entry (%arg0: i32, %arg1: i32): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) + %0 = sraw %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) + llvm.return %1 : i32 + }] + +def sra_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where + lhs := sra_llvm_i32 + rhs := sra_riscv_i32 + + +/-- ### sra_negative_constant_lhs -/ +@[simp_denote] +def sra_negative_constant_lhs_llvm_i32 := [LV| { + ^entry (%a: i32): + %0 = llvm.mlir.constant (2147483648) : i32 + %1 = llvm.ashr %0, %a : i32 + llvm.return %1 : i32 + }] + +@[simp_denote] +def sra_negative_constant_lhs_riscv_i32 := + [LV| { + ^entry (%arg: i32): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i32) -> (!i64) + %b = li (484394305) : !i64 + %0 = "lui" (%b) {imm = 524288 : !i64} : (!i64) -> (!i64) + %1 = sraw %0, %a : !i64 + %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i32) + llvm.return %2 : i32 + }] + +def sra_negative_constant_lhs_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32)] where + lhs := sra_negative_constant_lhs_llvm_i32 + rhs := sra_negative_constant_lhs_riscv_i32 + +/-- ### or -/ +@[simp_denote] +def or_llvm_i32 := [LV| { + ^entry (%a: i32, %b: i32): + %0 = llvm.or %a, %b : i32 + llvm.return %0 : i32 + }] + +@[simp_denote] +def or_riscv_i32 := + [LV| { + ^entry (%arg0: i32, %arg1: i32): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) + %0 = or %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) + llvm.return %1 : i32 + }] + +def or_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where + lhs := or_llvm_i32 + rhs := or_riscv_i32 + + +/-- ### and -/ +@[simp_denote] +def and_llvm_i32 := [LV| { + ^entry (%a: i32, %b: i32): + %0 = llvm.and %a, %b : i32 + llvm.return %0 : i32 + }] + +@[simp_denote] +def and_riscv_i32 := + [LV| { + ^entry (%arg0: i32, %arg1: i32): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) + %0 = and %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) + llvm.return %1 : i32 + }] + +def and_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where + lhs := and_llvm_i32 + rhs := and_riscv_i32 diff --git a/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu64.lean b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu64.lean new file mode 100644 index 0000000000..bb15739af6 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/LLVM-tests/alu64.lean @@ -0,0 +1,649 @@ +import SSA.Projects.LLVMRiscV.Pipeline.InstructionLowering + +open LLVMRiscV + +/-! + This file implements the `alu64.ll` test case in the LLVM test suite: + https://github.com/llvm/llvm-project/blob/b424207cdddfa2cbfc9129bbe0a31e47cb04e6dc/llvm/test/CodeGen/RISCV/alu64.ll +-/ + +/-- ### addi -/ +@[simp_denote] +def addi_llvm_i64 := [LV| { + ^entry (%a: i64): + %0 = llvm.mlir.constant (1) : i64 + %1 = llvm.add %a, %0 : i64 + llvm.return %1 : i64 + }] + +@[simp_denote] +def addi_riscv_i64 := + [LV| { + ^entry (%arg: i64): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64) + %0 = addi %a, 1 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) + llvm.return %1 : i64 + }] + +def addi_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := addi_llvm_i64 + rhs := addi_riscv_i64 + + +/-- ### slti -/ +@[simp_denote] +def slti_llvm_i64 := + [LV| { + ^entry (%a: i64): + %0 = llvm.mlir.constant (2) : i64 + %1 = llvm.icmp.slt %a, %0 : i64 + %2 = llvm.zext %1 : i1 to i64 + llvm.return %2 : i64 + }] + +@[simp_denote] +def slti_riscv_i64 := + [LV| { + ^entry (%arg: i64): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64) + %1 = slti %a, 2 : !i64 + %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i64) + llvm.return %2 : i64 + }] + +def slti_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := slti_llvm_i64 + rhs := slti_riscv_i64 + + +/-- ### sltiu -/ +@[simp_denote] +def sltiu_llvm_i64 := [LV| { + ^entry (%a: i64): + %0 = llvm.mlir.constant (3) : i64 + %1 = llvm.icmp.ult %a, %0 : i64 + %2 = llvm.zext %1 : i1 to i64 + llvm.return %2 : i64 + }] + +@[simp_denote] +def sltiu_riscv_i64 := + [LV| { + ^entry (%arg: i64): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64) + %1 = sltiu %a, 3 : !i64 + %2 = "builtin.unrealized_conversion_cast" (%1) : (!i64) -> (i64) + llvm.return %2 : i64 + }] + +def sltiu_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := sltiu_llvm_i64 + rhs := sltiu_riscv_i64 + + +/-- ### xori -/ +@[simp_denote] +def xori_llvm_i64 := [LV| { + ^entry (%a: i64): + %0 = llvm.mlir.constant (4) : i64 + %1 = llvm.xor %a, %0 : i64 + llvm.return %1 : i64 + }] + +@[simp_denote] +def xori_riscv_i64 := + [LV| { + ^entry (%arg: i64): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64) + %0 = xori %a, 4 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) + llvm.return %1 : i64 + }] + +def xori_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := xori_llvm_i64 + rhs := xori_riscv_i64 + + +/-- ### ori -/ +@[simp_denote] +def ori_llvm_i64 := [LV| { + ^entry (%a: i64): + %0 = llvm.mlir.constant (5) : i64 + %1 = llvm.or %a, %0 : i64 + llvm.return %1 : i64 + }] + +@[simp_denote] +def ori_riscv_i64 := + [LV| { + ^entry (%arg: i64): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64) + %0 = ori %a, 5 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) + llvm.return %1 : i64 + }] + +def ori_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := ori_llvm_i64 + rhs := ori_riscv_i64 + + +/-- ### andi -/ +@[simp_denote] +def andi_llvm_i64 := [LV| { + ^entry (%a: i64): + %0 = llvm.mlir.constant (6) : i64 + %1 = llvm.and %a, %0 : i64 + llvm.return %1 : i64 + }] + +@[simp_denote] +def andi_riscv_i64 := + [LV| { + ^entry (%arg: i64): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64) + %0 = andi %a, 6 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) + llvm.return %1 : i64 + }] + +def andi_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := andi_llvm_i64 + rhs := andi_riscv_i64 + + +/-- ### slli -/ +@[simp_denote] +def slli_llvm_i64 := [LV| { + ^entry (%a: i64): + %0 = llvm.mlir.constant (7) : i64 + %1 = llvm.shl %a, %0 : i64 + llvm.return %1 : i64 + }] + +@[simp_denote] +def slli_riscv_i64 := + [LV| { + ^entry (%arg: i64): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64) + %0 = slli %a, 7 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) + llvm.return %1 : i64 + }] + +def slli_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := slli_llvm_i64 + rhs := slli_riscv_i64 + + +/-- ### srli -/ +@[simp_denote] +def srli_llvm_i64 := [LV| { + ^entry (%a: i64): + %0 = llvm.mlir.constant (8) : i64 + %1 = llvm.lshr %a, %0 : i64 + llvm.return %1 : i64 + }] + +@[simp_denote] +def srli_riscv_i64 := + [LV| { + ^entry (%arg: i64): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64) + %0 = srli %a, 8 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) + llvm.return %1 : i64 + }] + +def srli_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := srli_llvm_i64 + rhs := srli_riscv_i64 + + +/-- ### srai -/ +@[simp_denote] +def srai_llvm_i64 := [LV| { + ^entry (%a: i64): + %0 = llvm.mlir.constant (9) : i64 + %1 = llvm.ashr %a, %0 : i64 + llvm.return %1 : i64 + }] + +@[simp_denote] +def srai_riscv_i64 := + [LV| { + ^entry (%arg: i64): + %a = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!i64) + %0 = srai %a, 9 : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) + llvm.return %1 : i64 + }] + +def srai_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := srai_llvm_i64 + rhs := srai_riscv_i64 + + +/-- ### add -/ +@[simp_denote] +def add_llvm_i64 := [LV| { + ^entry (%a: i64, %b: i64): + %0 = llvm.add %a, %b : i64 + llvm.return %0 : i64 + }] + +@[simp_denote] +def add_riscv_i64 := + [LV| { + ^entry (%arg0: i64, %arg1: i64): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i64) -> (!i64) + %0 = add %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) + llvm.return %1 : i64 + }] + +def add_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where + lhs := add_llvm_i64 + rhs := add_riscv_i64 + + +/-- ### sub -/ +@[simp_denote] +def sub_llvm_i64 := [LV| { + ^entry (%a: i64, %b: i64): + %0 = llvm.sub %a, %b : i64 + llvm.return %0 : i64 + }] + +@[simp_denote] +def sub_riscv_i64 := + [LV| { + ^entry (%arg0: i64, %arg1: i64): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i64) -> (!i64) + %0 = sub %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) + llvm.return %1 : i64 + }] + +def sub_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where + lhs := sub_llvm_i64 + rhs := sub_riscv_i64 + +/-- ### sll -/ +@[simp_denote] +def sll_llvm_i64 := [LV| { + ^entry (%a: i64, %b: i64): + %0 = llvm.shl %a, %b : i64 + llvm.return %0 : i64 + }] + +@[simp_denote] +def sll_riscv_i64 := + [LV| { + ^entry (%arg0: i64, %arg1: i64): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i64) -> (!i64) + %0 = sll %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) + llvm.return %1 : i64 + }] + +def sll_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where + lhs := sll_llvm_i64 + rhs := sll_riscv_i64 + +/-- ### slt -/ +@[simp_denote] +def slt_llvm_i64 := [LV| { + ^entry (%a: i64, %b: i64): + %0 = llvm.icmp.slt %a, %b : i64 + %1 = llvm.zext %0 : i1 to i64 + llvm.return %1 : i64 + }] + +@[simp_denote] +def slt_riscv_i64 := + [LV| { + ^entry (%arg0: i64, %arg1: i64): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i64) -> (!i64) + %2 = slt %a, %b : !i64 + %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i64) + llvm.return %3 : i64 + }] + +def slt_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where + lhs := slt_llvm_i64 + rhs := slt_riscv_i64 + + +/-- ### sltu -/ +@[simp_denote] +def sltu_llvm_i64 := [LV| { + ^entry (%a: i64, %b: i64): + %0 = llvm.icmp.ult %a, %b : i64 + %1 = llvm.zext %0 : i1 to i64 + llvm.return %1 : i64 + }] + +@[simp_denote] +def sltu_riscv_i64 := + [LV| { + ^entry (%arg0: i64, %arg1: i64): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i64) -> (!i64) + %2 = sltu %a, %b : !i64 + %3 = "builtin.unrealized_conversion_cast" (%2) : (!i64) -> (i64) + llvm.return %3 : i64 + }] + +def sltu_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where + lhs := sltu_llvm_i64 + rhs := sltu_riscv_i64 + + +/-- ### xor -/ +@[simp_denote] +def xor_llvm_i64 := [LV| { + ^entry (%a: i64, %b: i64): + %0 = llvm.xor %a, %b : i64 + llvm.return %0 : i64 + }] + +@[simp_denote] +def xor_riscv_i64 := + [LV| { + ^entry (%arg0: i64, %arg1: i64): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i64) -> (!i64) + %0 = xor %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) + llvm.return %1 : i64 + }] + +def xor_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where + lhs := xor_llvm_i64 + rhs := xor_riscv_i64 + + +/-- ### srl -/ +@[simp_denote] +def srl_llvm_i64 := [LV| { + ^entry (%a: i64, %b: i64): + %0 = llvm.lshr %a, %b : i64 + llvm.return %0 : i64 + }] + +@[simp_denote] +def srl_riscv_i64 := + [LV| { + ^entry (%arg0: i64, %arg1: i64): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i64) -> (!i64) + %0 = srl %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) + llvm.return %1 : i64 + }] + +def srl_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where + lhs := srl_llvm_i64 + rhs := srl_riscv_i64 + + +/-- ### sra -/ +@[simp_denote] +def sra_llvm_i64 := [LV| { + ^entry (%a: i64, %b: i64): + %0 = llvm.ashr %a, %b : i64 + llvm.return %0 : i64 + }] + +@[simp_denote] +def sra_riscv_i64 := + [LV| { + ^entry (%arg0: i64, %arg1: i64): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i64) -> (!i64) + %0 = sra %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) + llvm.return %1 : i64 + }] + +def sra_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where + lhs := sra_llvm_i64 + rhs := sra_riscv_i64 + + +/-- ### or -/ +@[simp_denote] +def or_llvm_i32 := [LV| { + ^entry (%a: i32, %b: i32): + %0 = llvm.or %a, %b : i32 + llvm.return %0 : i32 + }] + +@[simp_denote] +def or_riscv_i32 := + [LV| { + ^entry (%arg0: i32, %arg1: i32): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i32) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i32) -> (!i64) + %0 = or %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i32) + llvm.return %1 : i32 + }] + +def or_i32_test : LLVMPeepholeRewriteRefine 32 [Ty.llvm (.bitvec 32), Ty.llvm (.bitvec 32)] where + lhs := or_llvm_i32 + rhs := or_riscv_i32 + + +/-- ### and -/ +@[simp_denote] +def and_llvm_i64 := [LV| { + ^entry (%a: i64, %b: i64): + %0 = llvm.and %a, %b : i64 + llvm.return %0 : i64 + }] + +@[simp_denote] +def and_riscv_i64 := + [LV| { + ^entry (%arg0: i64, %arg1: i64): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!i64) + %b = "builtin.unrealized_conversion_cast" (%arg1) : (i64) -> (!i64) + %0 = and %a, %b : !i64 + %1 = "builtin.unrealized_conversion_cast" (%0) : (!i64) -> (i64) + llvm.return %1 : i64 + }] + +def and_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64), Ty.llvm (.bitvec 64)] where + lhs := and_llvm_i64 + rhs := and_riscv_i64 + + +/- ### addiw + Can't be implemented because Lean-MLIR does not support the intrinsic as in `i32 signext %a` +-/ + +/- ### slliw + Can't be implemented because Lean-MLIR does not support the intrinsic as in `i32 signext %a` +-/ + +/- ### srliw + Can't be implemented. + TODO: check why +-/ + + +/-- ### sraiw -/ +@[simp_denote] +def sraiw_llvm_i64 := [LV| { + ^entry (%a: i64): + %32 = llvm.mlir.constant (32) : i64 + %41 = llvm.mlir.constant (41) : i64 + %0 = llvm.shl %a, %32 : i64 + %1 = llvm.ashr %0, %41: i64 + llvm.return %1 : i64 + }] + +@[simp_denote] +def sraiw_riscv_i64 := [LV| { + ^entry (%arg: i64): + %0 = "builtin.unrealized_conversion_cast" (%arg) : (i64) -> (!riscv.reg) + %1 = sraiw %0, 9 : !riscv.reg + %2 = "builtin.unrealized_conversion_cast" (%1) : (!riscv.reg) -> (i64) + llvm.return %2 : i64 + }] + +def sraiw_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := sraiw_llvm_i64 + rhs := sraiw_riscv_i64 + + +/- ### sextw + Can't be implemented. + TODO: check why +-/ + +/- ### addw + Can't be implemented. + TODO: check why +-/ + +/- ### subw + Can't be implemented. + TODO: check why +-/ + +/- ### sllw + Can't be implemented. + TODO: check why +-/ + +/- ### srlw + Can't be implemented. + TODO: check why +-/ + + +/- ### sraw + Can't be implemented. + TODO: check why +-/ + + +/-- ### add_hi_and_lo_negone -/ +@[simp_denote] +def add_hi_and_lo_negone_llvm_i64 := [LV| { + ^entry (%arg: i64): + %1 = llvm.mlir.constant (-1) : i64 + %0 = llvm.add %arg, %1 overflow : i64 + llvm.return %0 : i64 + }] + +@[simp_denote] +def add_hi_and_lo_negone_riscv_i64 := + [LV| { + ^entry (%arg0: i64): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!riscv.reg) + %0 = li (0) : !riscv.reg + %1= li (1) : !riscv.reg + %2 = sub %0, %1 : !riscv.reg -- load -1 into %1 becaue can't encode (-1) for the moment + %3 = add %a, %2 : !riscv.reg + %4 = "builtin.unrealized_conversion_cast" (%3) : (!riscv.reg) -> (i64) + llvm.return %4 : i64 + }] + +def add_hi_and_lo_negone_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := add_hi_and_lo_negone_llvm_i64 + rhs := add_hi_and_lo_negone_riscv_i64 + + +/-- ### add_hi_zero_lo_negone -/ +@[simp_denote] +def add_hi_zero_lo_negone_llvm_i64 := [LV| { + ^entry (%0: i64): + %4294967295 = llvm.mlir.constant (4294967295) : i64 + %1 = llvm.add %0, %4294967295 : i64 + llvm.return %1 : i64 + }] + +@[simp_denote] +def add_hi_zero_lo_negone_riscv_i64 := + [LV| { + ^entry (%arg0: i64): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!riscv.reg) + %0 = li (0) : !riscv.reg + %1= li (1) : !riscv.reg + %2 = sub %0, %1 : !riscv.reg -- load -1 into %1 becaue can't encode (-1) for the moment + %3 = srli %2, 32 : !riscv.reg + %4 = add %a, %3 : !riscv.reg + %5 = "builtin.unrealized_conversion_cast" (%4) : (!riscv.reg) -> (i64) + llvm.return %5 : i64 + }] + +def add_hi_one_lo_negone_i32_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := add_hi_zero_lo_negone_llvm_i64 + rhs :=add_hi_zero_lo_negone_riscv_i64 + +/-- ### add_lo_negone -/ +@[simp_denote] +def add_lo_negone_llvm_i64 := [LV| { + ^entry (%arg: i64): + %4294967297 = llvm.mlir.constant (4294967297) : i64 + %0 = llvm.mlir.constant (0) : i64 + %1 =llvm.sub %0, %4294967297 : i64 + %2 = llvm.add %1, %arg overflow : i64 + llvm.return %2 : i64 + }] + +@[simp_denote] +def add_lo_negone_riscv_i64 := + [LV| { + ^entry (%arg0: i64): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!riscv.reg) + %0 = li (0) : !riscv.reg + %1= li (1) : !riscv.reg + %2 = sub %0, %1 : !riscv.reg -- load -1 into %1 becaue can't encode (-1) for the moment + %3 = slli %2, 32 : !riscv.reg + %4 = add %3, %2 : !riscv.reg + %5 = add %a, %4 : !riscv.reg + %6 = "builtin.unrealized_conversion_cast" (%5) : (!riscv.reg) -> (i64) + llvm.return %6 : i64 + }] + +def add_lo_negone_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := add_lo_negone_llvm_i64 + rhs := add_lo_negone_riscv_i64 + +/-- ### add_hi_one_lo_negone -/ +@[simp_denote] +def add_hi_one_lo_negone_llvm_i64 := [LV| { + ^entry (%arg: i64): + %8589934591 = llvm.mlir.constant (8589934591) : i64 + %1 = llvm.add %arg, %8589934591 overflow : i64 + llvm.return %1 : i64 + }] + +@[simp_denote] +def add_hi_one_lo_negone_riscv_i64 := + [LV| { + ^entry (%arg0: i64): + %a = "builtin.unrealized_conversion_cast" (%arg0) : (i64) -> (!riscv.reg) + %0 = li (0) : !riscv.reg + %1= li (1) : !riscv.reg + %2 = sub %0, %1 : !riscv.reg -- load -1 into %1 becaue can't encode (-1) for the moment + %3 = srli %2, 31 : !riscv.reg + %4 = add %3, %a : !riscv.reg + %5 = "builtin.unrealized_conversion_cast" (%4) : (!riscv.reg) -> (i64) + llvm.return %5 : i64 + }] + +def add_hi_one_lo_negone_i64_test : LLVMPeepholeRewriteRefine 64 [Ty.llvm (.bitvec 64)] where + lhs := add_hi_one_lo_negone_llvm_i64 + rhs := add_hi_one_lo_negone_riscv_i64 diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_3.mlir b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_3.mlir new file mode 100644 index 0000000000..448914c3b0 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_3.mlir @@ -0,0 +1,900 @@ +module { + func.func @main(%arg0: i64) -> i1 { + %0 = llvm.and %arg0, %arg0 : i64 + %1 = llvm.and %0, %arg0 : i64 + %2 = llvm.trunc %1 : i64 to i1 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32) -> i1 { + %0 = llvm.zext %arg1 : i32 to i64 + %1 = llvm.sdiv %arg0, %0 : i64 + %2 = llvm.icmp "ult" %arg0, %1 : i64 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.ashr %arg0, %arg0 : i64 + %1 = llvm.select %arg1, %0, %arg2 : i1, i64 + %2 = llvm.lshr %0, %1 : i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.or %arg2, %arg2 : i64 + %1 = llvm.or %arg1, %0 : i64 + %2 = llvm.icmp "ugt" %arg0, %1 : i64 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.zext %0 : i1 to i64 + %2 = llvm.trunc %1 : i64 to i1 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.urem %arg0, %arg1 : i64 + %1 = llvm.or %arg1, %arg2 : i64 + %2 = llvm.icmp "ugt" %0, %1 : i64 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.or %arg0, %arg1 : i64 + %1 = llvm.ashr %0, %arg1 : i64 + %2 = llvm.icmp "sle" %0, %1 : i64 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.ashr %arg1, %arg0 : i64 + %1 = llvm.icmp "ne" %arg0, %0 : i64 + %2 = llvm.zext %1 : i1 to i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.udiv %arg0, %arg1 : i64 + %1 = llvm.lshr %arg0, %0 : i64 + %2 = llvm.urem %arg0, %1 : i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.xor %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.icmp "sgt" %arg0, %arg1 : i64 + %1 = llvm.select %0, %arg2, %arg0 : i1, i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.sext %0 : i32 to i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.zext %arg0 : i1 to i64 + %1 = llvm.srem %arg1, %arg2 : i64 + %2 = llvm.icmp "eq" %0, %1 : i64 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.xor %arg0, %arg1 : i64 + %1 = llvm.sdiv %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.zext %0 : i32 to i64 + %2 = llvm.trunc %1 : i64 to i1 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.lshr %arg0, %arg1 : i64 + %1 = llvm.xor %0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.xor %arg0, %arg1 : i64 + %1 = llvm.ashr %0, %arg1 : i64 + %2 = llvm.trunc %1 : i64 to i1 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.srem %arg0, %arg1 : i64 + %1 = llvm.xor %0, %arg2 : i64 + %2 = llvm.icmp "slt" %1, %0 : i64 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1) -> i32 { + %0 = llvm.zext %arg0 : i1 to i64 + %1 = llvm.udiv %0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.udiv %arg0, %arg1 : i64 + %1 = llvm.srem %arg0, %0 : i64 + %2 = llvm.icmp "sgt" %1, %0 : i64 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.zext %0 : i32 to i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.trunc %1 : i64 to i1 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.select %arg0, %arg1, %arg2 : i1, i64 + %1 = llvm.sdiv %0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.xor %arg1, %arg2 : i64 + %1 = llvm.xor %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.or %arg1, %arg1 : i64 + %1 = llvm.udiv %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i1 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.icmp "ult" %arg0, %arg1 : i64 + %1 = llvm.zext %0 : i1 to i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.sext %0 : i32 to i64 + %2 = llvm.trunc %1 : i64 to i1 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.or %arg0, %arg0 : i64 + %1 = llvm.udiv %0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64) -> i32 { + %0 = llvm.xor %arg1, %arg1 : i64 + %1 = llvm.select %arg0, %0, %0 : i1, i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1) -> i32 { + %0 = llvm.zext %arg1 : i1 to i64 + %1 = llvm.xor %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.zext %0 : i32 to i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.zext %0 : i1 to i64 + %2 = llvm.trunc %1 : i64 to i1 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i1) -> i32 { + %0 = llvm.sext %arg2 : i1 to i64 + %1 = llvm.select %arg0, %arg1, %0 : i1, i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.and %arg1, %arg2 : i64 + %1 = llvm.lshr %arg0, %0 : i64 + %2 = llvm.ashr %1, %0 : i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.urem %arg0, %arg0 : i64 + %1 = llvm.lshr %0, %arg1 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.urem %arg0, %arg1 : i64 + %1 = llvm.lshr %0, %0 : i64 + %2 = llvm.and %0, %1 : i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.sext %0 : i32 to i64 + %2 = llvm.sdiv %1, %arg1 : i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.icmp "ugt" %arg0, %arg0 : i64 + %1 = llvm.zext %0 : i1 to i64 + %2 = llvm.udiv %1, %arg1 : i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.select %0, %arg1, %arg2 : i1, i64 + %2 = llvm.trunc %1 : i64 to i1 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.icmp "sge" %arg0, %arg1 : i64 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.trunc %1 : i64 to i1 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.urem %arg0, %arg0 : i64 + %1 = llvm.lshr %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.urem %arg0, %arg0 : i64 + %1 = llvm.urem %0, %arg1 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i64 { + %0 = llvm.urem %arg0, %arg0 : i64 + %1 = llvm.icmp "ne" %arg0, %0 : i64 + %2 = llvm.zext %1 : i1 to i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1) -> i32 { + %0 = llvm.sext %arg1 : i1 to i64 + %1 = llvm.udiv %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.and %arg1, %arg1 : i64 + %1 = llvm.urem %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.udiv %arg0, %arg0 : i64 + %1 = llvm.and %0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.and %arg0, %arg0 : i64 + %1 = llvm.sdiv %0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.urem %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.sext %1 : i32 to i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.ashr %arg0, %arg1 : i64 + %1 = llvm.or %0, %arg2 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { + %0 = llvm.select %arg1, %arg2, %arg0 : i1, i64 + %1 = llvm.and %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.udiv %arg0, %arg0 : i64 + %1 = llvm.xor %0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i32, %arg1: i64) -> i1 { + %0 = llvm.zext %arg0 : i32 to i64 + %1 = llvm.srem %0, %arg1 : i64 + %2 = llvm.trunc %1 : i64 to i1 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32) -> i1 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.sext %arg1 : i32 to i64 + %2 = llvm.icmp "eq" %0, %1 : i64 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { + %0 = llvm.select %arg1, %arg2, %arg2 : i1, i64 + %1 = llvm.udiv %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.icmp "ne" %arg0, %arg1 : i64 + %1 = llvm.or %arg2, %arg1 : i64 + %2 = llvm.select %0, %arg1, %1 : i1, i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.sdiv %arg0, %arg1 : i64 + %1 = llvm.sdiv %0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i64 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.srem %0, %0 : i64 + %2 = llvm.lshr %0, %1 : i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i32, %arg1: i64) -> i32 { + %0 = llvm.sext %arg0 : i32 to i64 + %1 = llvm.or %0, %arg1 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1) -> i64 { + %0 = llvm.xor %arg0, %arg0 : i64 + %1 = llvm.zext %arg1 : i1 to i64 + %2 = llvm.xor %0, %1 : i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.udiv %arg1, %arg2 : i64 + %1 = llvm.or %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1) -> i1 { + %0 = llvm.sext %arg1 : i1 to i64 + %1 = llvm.ashr %0, %0 : i64 + %2 = llvm.icmp "ule" %arg0, %1 : i64 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i1 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.udiv %0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i1 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.urem %arg1, %arg2 : i64 + %1 = llvm.xor %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i32) -> i1 { + %0 = llvm.sext %arg0 : i32 to i64 + %1 = llvm.srem %0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i1 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i32, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.zext %arg0 : i32 to i64 + %1 = llvm.or %arg1, %arg2 : i64 + %2 = llvm.urem %0, %1 : i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.urem %arg0, %arg1 : i64 + %1 = llvm.lshr %0, %arg1 : i64 + %2 = llvm.urem %0, %1 : i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.select %arg1, %arg2, %arg0 : i1, i64 + %1 = llvm.urem %arg0, %0 : i64 + %2 = llvm.xor %arg0, %1 : i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.udiv %arg0, %arg0 : i64 + %1 = llvm.urem %0, %arg0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.trunc %arg1 : i64 to i32 + %1 = llvm.zext %0 : i32 to i64 + %2 = llvm.icmp "eq" %arg0, %1 : i64 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i64 { + %0 = llvm.or %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.sext %1 : i1 to i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.icmp "ult" %arg0, %arg1 : i64 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.icmp "ne" %arg0, %1 : i64 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.zext %0 : i32 to i64 + %2 = llvm.trunc %1 : i64 to i1 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.ashr %0, %arg1 : i64 + %2 = llvm.trunc %1 : i64 to i1 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.udiv %arg0, %arg0 : i64 + %1 = llvm.lshr %0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.udiv %arg1, %arg2 : i64 + %1 = llvm.or %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.srem %arg1, %arg0 : i64 + %1 = llvm.srem %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.ashr %arg0, %arg0 : i64 + %1 = llvm.lshr %arg1, %arg2 : i64 + %2 = llvm.udiv %0, %1 : i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.zext %0 : i32 to i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64) -> i32 { + %0 = llvm.zext %arg0 : i1 to i64 + %1 = llvm.or %0, %arg1 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.xor %arg0, %arg0 : i64 + %1 = llvm.ashr %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.sdiv %arg1, %arg2 : i64 + %1 = llvm.or %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i64 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.zext %1 : i1 to i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1) -> i1 { + %0 = llvm.sext %arg1 : i1 to i64 + %1 = llvm.ashr %arg0, %0 : i64 + %2 = llvm.icmp "sle" %arg0, %1 : i64 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i1 { + %0 = llvm.ashr %arg0, %arg0 : i64 + %1 = llvm.srem %0, %arg0 : i64 + %2 = llvm.trunc %1 : i64 to i1 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.xor %arg1, %arg0 : i64 + %1 = llvm.sdiv %0, %arg2 : i64 + %2 = llvm.icmp "ule" %arg0, %1 : i64 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.sext %0 : i32 to i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.urem %arg1, %arg1 : i64 + %1 = llvm.xor %arg2, %0 : i64 + %2 = llvm.select %arg0, %arg1, %1 : i1, i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1) -> i64 { + %0 = llvm.zext %arg1 : i1 to i64 + %1 = llvm.icmp "sgt" %arg0, %0 : i64 + %2 = llvm.zext %1 : i1 to i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.urem %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.select %1, %0, %arg1 : i1, i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.icmp "sle" %arg0, %arg1 : i64 + %1 = llvm.select %0, %arg2, %arg0 : i1, i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { + %0 = llvm.select %arg1, %arg2, %arg0 : i1, i64 + %1 = llvm.srem %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + return %2 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.srem %arg0, %arg1 : i64 + %1 = llvm.xor %arg0, %0 : i64 + %2 = llvm.icmp "ne" %arg0, %1 : i64 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.and %1, %arg1 : i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1) -> i1 { + %0 = llvm.zext %arg1 : i1 to i64 + %1 = llvm.and %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i1 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i1 { + %0 = llvm.urem %arg0, %arg0 : i64 + %1 = llvm.lshr %arg0, %0 : i64 + %2 = llvm.icmp "sgt" %arg0, %1 : i64 + return %2 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1) -> i64 { + %0 = llvm.sext %arg0 : i1 to i64 + %1 = llvm.and %0, %0 : i64 + %2 = llvm.or %1, %1 : i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i64 { + %0 = llvm.and %arg0, %arg1 : i64 + %1 = llvm.select %arg2, %arg0, %0 : i1, i64 + %2 = llvm.udiv %0, %1 : i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.udiv %arg1, %arg1 : i64 + %1 = llvm.lshr %0, %arg2 : i64 + %2 = llvm.and %arg0, %1 : i64 + return %2 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.sdiv %0, %arg1 : i64 + %2 = llvm.trunc %1 : i64 to i1 + return %2 : i1 + } +} +// ----- diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_4.mlir b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_4.mlir new file mode 100644 index 0000000000..fe44514a5b --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_4.mlir @@ -0,0 +1,1000 @@ +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.xor %arg0, %arg0 : i64 + %1 = llvm.srem %arg1, %arg1 : i64 + %2 = llvm.urem %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i1 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.sext %0 : i32 to i64 + %2 = llvm.ashr %1, %arg1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.xor %arg0, %arg1 : i64 + %1 = llvm.or %arg2, %0 : i64 + %2 = llvm.sdiv %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i32, %arg1: i64) -> i32 { + %0 = llvm.zext %arg0 : i32 to i64 + %1 = llvm.xor %0, %arg1 : i64 + %2 = llvm.lshr %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.urem %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.sext %1 : i1 to i64 + %3 = llvm.trunc %2 : i64 to i1 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.srem %arg1, %arg1 : i64 + %1 = llvm.select %arg0, %0, %arg2 : i1, i64 + %2 = llvm.xor %1, %arg1 : i64 + %3 = llvm.trunc %2 : i64 to i1 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.and %arg1, %arg2 : i64 + %1 = llvm.xor %0, %arg1 : i64 + %2 = llvm.urem %arg1, %arg1 : i64 + %3 = llvm.select %arg0, %1, %2 : i1, i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.and %arg0, %arg0 : i64 + %1 = llvm.urem %arg0, %arg1 : i64 + %2 = llvm.srem %0, %1 : i64 + %3 = llvm.icmp "sle" %2, %arg1 : i64 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 + %1 = llvm.lshr %arg2, %arg1 : i64 + %2 = llvm.and %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1) -> i32 { + %0 = llvm.zext %arg0 : i1 to i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.sext %1 : i1 to i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { + %0 = llvm.select %arg1, %arg2, %arg2 : i1, i64 + %1 = llvm.xor %0, %arg2 : i64 + %2 = llvm.lshr %arg0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.and %arg1, %arg2 : i64 + %1 = llvm.or %arg0, %0 : i64 + %2 = llvm.lshr %1, %0 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.ashr %arg1, %arg2 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.sext %1 : i1 to i64 + %3 = llvm.or %arg0, %2 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.udiv %arg1, %arg2 : i64 + %1 = llvm.srem %0, %arg1 : i64 + %2 = llvm.xor %0, %1 : i64 + %3 = llvm.srem %arg0, %2 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i32, %arg1: i64) -> i1 { + %0 = llvm.sext %arg0 : i32 to i64 + %1 = llvm.ashr %arg1, %arg1 : i64 + %2 = llvm.urem %arg1, %1 : i64 + %3 = llvm.icmp "uge" %0, %2 : i64 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1) -> i1 { + %0 = llvm.sext %arg0 : i1 to i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.sext %1 : i1 to i64 + %3 = llvm.trunc %2 : i64 to i1 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.xor %arg1, %arg2 : i64 + %2 = llvm.urem %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i1 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.lshr %arg1, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.zext %1 : i32 to i64 + %3 = llvm.icmp "sge" %arg0, %2 : i64 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i32) -> i32 { + %0 = llvm.zext %arg2 : i32 to i64 + %1 = llvm.lshr %arg1, %0 : i64 + %2 = llvm.srem %arg0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.and %arg0, %arg1 : i64 + %1 = llvm.srem %arg0, %0 : i64 + %2 = llvm.lshr %1, %arg2 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i64 { + %0 = llvm.ashr %arg0, %arg0 : i64 + %1 = llvm.urem %arg0, %0 : i64 + %2 = llvm.and %1, %1 : i64 + %3 = llvm.and %0, %2 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.or %arg0, %arg1 : i64 + %1 = llvm.and %0, %arg2 : i64 + %2 = llvm.lshr %arg0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.select %0, %arg0, %arg1 : i1, i64 + %2 = llvm.or %arg2, %arg0 : i64 + %3 = llvm.icmp "ule" %1, %2 : i64 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.lshr %0, %arg1 : i64 + %2 = llvm.trunc %1 : i64 to i1 + %3 = llvm.select %2, %arg2, %arg0 : i1, i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.urem %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.sext %1 : i32 to i64 + %3 = llvm.or %2, %arg0 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.or %arg0, %arg1 : i64 + %1 = llvm.or %arg2, %0 : i64 + %2 = llvm.ashr %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { + %0 = llvm.select %arg1, %arg0, %arg2 : i1, i64 + %1 = llvm.sdiv %arg0, %0 : i64 + %2 = llvm.lshr %1, %0 : i64 + %3 = llvm.icmp "sgt" %arg0, %2 : i64 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i32, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.sext %arg0 : i32 to i64 + %1 = llvm.lshr %arg1, %arg2 : i64 + %2 = llvm.srem %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i32, %arg1: i64) -> i64 { + %0 = llvm.zext %arg0 : i32 to i64 + %1 = llvm.xor %arg1, %0 : i64 + %2 = llvm.icmp "sle" %0, %1 : i64 + %3 = llvm.zext %2 : i1 to i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.udiv %arg0, %arg1 : i64 + %1 = llvm.sdiv %0, %arg2 : i64 + %2 = llvm.urem %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.icmp "ult" %arg0, %arg0 : i64 + %1 = llvm.udiv %arg1, %arg2 : i64 + %2 = llvm.select %0, %1, %arg0 : i1, i64 + %3 = llvm.trunc %2 : i64 to i1 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.ashr %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.sext %1 : i32 to i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i32, %arg1: i64) -> i32 { + %0 = llvm.zext %arg0 : i32 to i64 + %1 = llvm.icmp "sge" %0, %arg1 : i64 + %2 = llvm.zext %1 : i1 to i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.or %arg0, %arg1 : i64 + %1 = llvm.sdiv %arg0, %0 : i64 + %2 = llvm.sdiv %1, %arg2 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.sdiv %arg0, %arg0 : i64 + %1 = llvm.trunc %arg1 : i64 to i1 + %2 = llvm.zext %1 : i1 to i64 + %3 = llvm.srem %0, %2 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i1) -> i1 { + %0 = llvm.sext %arg0 : i1 to i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.sext %1 : i1 to i64 + %3 = llvm.trunc %2 : i64 to i1 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.sdiv %arg0, %arg1 : i64 + %3 = llvm.and %1, %2 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.sdiv %arg1, %arg1 : i64 + %1 = llvm.lshr %arg0, %0 : i64 + %2 = llvm.srem %1, %arg2 : i64 + %3 = llvm.trunc %2 : i64 to i1 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.or %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.zext %1 : i32 to i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.select %arg1, %arg2, %arg2 : i1, i64 + %1 = llvm.udiv %0, %0 : i64 + %2 = llvm.srem %arg0, %1 : i64 + %3 = llvm.sdiv %arg0, %2 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { + %0 = llvm.sdiv %arg0, %arg0 : i64 + %1 = llvm.sdiv %arg0, %arg0 : i64 + %2 = llvm.select %arg1, %arg2, %1 : i1, i64 + %3 = llvm.icmp "ne" %0, %2 : i64 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32) -> i32 { + %0 = llvm.urem %arg0, %arg0 : i64 + %1 = llvm.zext %arg1 : i32 to i64 + %2 = llvm.srem %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1, %arg3: i32) -> i64 { + %0 = llvm.and %arg0, %arg1 : i64 + %1 = llvm.zext %arg3 : i32 to i64 + %2 = llvm.select %arg2, %0, %1 : i1, i64 + %3 = llvm.udiv %0, %2 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i1 { + %0 = llvm.udiv %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.select %1, %0, %arg0 : i1, i64 + %3 = llvm.trunc %2 : i64 to i1 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.select %0, %arg1, %arg2 : i1, i64 + %2 = llvm.ashr %arg2, %arg2 : i64 + %3 = llvm.icmp "ne" %1, %2 : i64 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { + %0 = llvm.zext %arg1 : i1 to i64 + %1 = llvm.srem %arg0, %0 : i64 + %2 = llvm.srem %arg2, %1 : i64 + %3 = llvm.icmp "ule" %1, %2 : i64 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.and %arg0, %arg0 : i64 + %1 = llvm.and %arg0, %arg0 : i64 + %2 = llvm.xor %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.sext %arg1 : i1 to i64 + %1 = llvm.srem %arg2, %arg0 : i64 + %2 = llvm.udiv %0, %1 : i64 + %3 = llvm.udiv %arg0, %2 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.zext %0 : i32 to i64 + %2 = llvm.udiv %1, %arg1 : i64 + %3 = llvm.xor %1, %2 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.or %arg1, %arg1 : i64 + %1 = llvm.sdiv %arg0, %0 : i64 + %2 = llvm.srem %1, %0 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.srem %arg0, %arg1 : i64 + %1 = llvm.trunc %arg2 : i64 to i32 + %2 = llvm.zext %1 : i32 to i64 + %3 = llvm.xor %0, %2 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.udiv %arg0, %arg1 : i64 + %1 = llvm.or %0, %arg0 : i64 + %2 = llvm.udiv %1, %arg2 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i1) -> i32 { + %0 = llvm.lshr %arg1, %arg1 : i64 + %1 = llvm.zext %arg2 : i1 to i64 + %2 = llvm.select %arg0, %0, %1 : i1, i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i64 { + %0 = llvm.sdiv %arg1, %arg0 : i64 + %1 = llvm.zext %arg2 : i1 to i64 + %2 = llvm.urem %0, %1 : i64 + %3 = llvm.ashr %arg0, %2 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i64 { + %0 = llvm.icmp "uge" %arg0, %arg0 : i64 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.lshr %arg1, %arg2 : i64 + %1 = llvm.select %arg0, %arg1, %arg1 : i1, i64 + %2 = llvm.sdiv %1, %1 : i64 + %3 = llvm.select %arg0, %0, %2 : i1, i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.sext %0 : i32 to i64 + %2 = llvm.udiv %1, %arg1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.lshr %1, %arg0 : i64 + %3 = llvm.select %0, %arg0, %2 : i1, i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1) -> i32 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.sext %arg1 : i1 to i64 + %2 = llvm.urem %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.zext %0 : i32 to i64 + %2 = llvm.srem %1, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i1) -> i1 { + %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 + %1 = llvm.sext %arg2 : i1 to i64 + %2 = llvm.urem %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i1 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.sext %0 : i32 to i64 + %2 = llvm.lshr %1, %arg0 : i64 + %3 = llvm.sdiv %2, %1 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64) -> i32 { + %0 = llvm.zext %arg0 : i1 to i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.select %1, %arg1, %0 : i1, i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i64 { + %0 = llvm.udiv %arg0, %arg0 : i64 + %1 = llvm.srem %0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.zext %2 : i32 to i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.select %arg1, %arg2, %arg0 : i1, i64 + %1 = llvm.srem %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i1 + %3 = llvm.select %2, %arg0, %0 : i1, i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.ashr %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.zext %1 : i32 to i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.ashr %arg0, %arg0 : i64 + %1 = llvm.xor %arg1, %arg2 : i64 + %2 = llvm.sdiv %0, %1 : i64 + %3 = llvm.icmp "ule" %2, %arg1 : i64 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.or %arg1, %arg0 : i64 + %1 = llvm.or %0, %arg2 : i64 + %2 = llvm.sdiv %arg0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.or %arg0, %arg0 : i64 + %1 = llvm.srem %arg1, %arg2 : i64 + %2 = llvm.urem %0, %1 : i64 + %3 = llvm.ashr %2, %arg1 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.udiv %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.zext %1 : i1 to i64 + %3 = llvm.urem %2, %arg0 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.icmp "sle" %arg0, %arg0 : i64 + %1 = llvm.select %0, %arg1, %arg2 : i1, i64 + %2 = llvm.urem %arg0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.or %0, %0 : i64 + %2 = llvm.udiv %arg0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.lshr %arg0, %arg1 : i64 + %1 = llvm.urem %arg2, %arg2 : i64 + %2 = llvm.udiv %1, %arg2 : i64 + %3 = llvm.ashr %0, %2 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.udiv %arg0, %arg0 : i64 + %2 = llvm.ashr %arg0, %arg0 : i64 + %3 = llvm.select %0, %1, %2 : i1, i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.ashr %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.zext %1 : i1 to i64 + %3 = llvm.trunc %2 : i64 to i1 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.or %0, %arg0 : i64 + %2 = llvm.lshr %arg0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.xor %arg0, %arg2 : i64 + %1 = llvm.sdiv %arg1, %0 : i64 + %2 = llvm.lshr %arg0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.ashr %arg2, %arg2 : i64 + %1 = llvm.ashr %arg1, %0 : i64 + %2 = llvm.and %arg0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i1 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.urem %arg1, %arg0 : i64 + %2 = llvm.or %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.zext %0 : i32 to i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.zext %2 : i32 to i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i32, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.zext %arg0 : i32 to i64 + %1 = llvm.srem %arg1, %arg2 : i64 + %2 = llvm.srem %1, %0 : i64 + %3 = llvm.srem %0, %2 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.sdiv %1, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.select %arg0, %arg1, %arg2 : i1, i64 + %1 = llvm.udiv %0, %arg1 : i64 + %2 = llvm.udiv %1, %1 : i64 + %3 = llvm.lshr %0, %2 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i32) -> i64 { + %0 = llvm.sext %arg2 : i32 to i64 + %1 = llvm.or %arg1, %0 : i64 + %2 = llvm.urem %1, %0 : i64 + %3 = llvm.xor %arg0, %2 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i32, %arg1: i64) -> i1 { + %0 = llvm.sext %arg0 : i32 to i64 + %1 = llvm.and %0, %arg1 : i64 + %2 = llvm.or %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i1 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.and %arg2, %arg2 : i64 + %1 = llvm.urem %arg1, %0 : i64 + %2 = llvm.select %arg0, %1, %arg1 : i1, i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.select %arg1, %arg2, %arg0 : i1, i64 + %1 = llvm.and %arg0, %arg0 : i64 + %2 = llvm.urem %0, %1 : i64 + %3 = llvm.xor %arg0, %2 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i64 { + %0 = llvm.sext %arg1 : i32 to i64 + %1 = llvm.and %arg2, %0 : i64 + %2 = llvm.udiv %0, %1 : i64 + %3 = llvm.and %arg0, %2 : i64 + return %3 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { + %0 = llvm.udiv %arg0, %arg0 : i64 + %1 = llvm.select %arg1, %arg2, %0 : i1, i64 + %2 = llvm.lshr %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { + %0 = llvm.select %arg1, %arg0, %arg2 : i1, i64 + %1 = llvm.srem %0, %arg2 : i64 + %2 = llvm.srem %1, %1 : i64 + %3 = llvm.icmp "slt" %arg0, %2 : i64 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.lshr %arg1, %arg1 : i64 + %1 = llvm.sdiv %arg0, %0 : i64 + %2 = llvm.sdiv %1, %arg2 : i64 + %3 = llvm.trunc %2 : i64 to i1 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { + %0 = llvm.select %arg1, %arg2, %arg0 : i1, i64 + %1 = llvm.or %arg0, %0 : i64 + %2 = llvm.ashr %1, %1 : i64 + %3 = llvm.trunc %2 : i64 to i1 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.trunc %arg1 : i64 to i32 + %1 = llvm.sext %0 : i32 to i64 + %2 = llvm.ashr %arg0, %1 : i64 + %3 = llvm.icmp "uge" %2, %arg1 : i64 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.lshr %arg0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.urem %arg1, %arg1 : i64 + %1 = llvm.urem %0, %arg2 : i64 + %2 = llvm.ashr %arg0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i1 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.and %arg0, %arg0 : i64 + %1 = llvm.udiv %arg1, %arg1 : i64 + %2 = llvm.and %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.or %arg0, %arg1 : i64 + %1 = llvm.icmp "sgt" %0, %arg0 : i64 + %2 = llvm.zext %1 : i1 to i64 + %3 = llvm.trunc %2 : i64 to i1 + return %3 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.sdiv %arg0, %arg0 : i64 + %1 = llvm.xor %arg1, %0 : i64 + %2 = llvm.urem %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.lshr %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.zext %1 : i32 to i64 + %3 = llvm.trunc %2 : i64 to i32 + return %3 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.and %arg0, %arg1 : i64 + %2 = llvm.sext %0 : i1 to i64 + %3 = llvm.select %0, %1, %2 : i1, i64 + return %3 : i64 + } +} +// ----- diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_5.mlir b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_5.mlir new file mode 100644 index 0000000000..2245149cb7 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_5.mlir @@ -0,0 +1,1100 @@ +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1, %arg3: i32) -> i1 { + %0 = llvm.zext %arg2 : i1 to i64 + %1 = llvm.srem %arg1, %0 : i64 + %2 = llvm.xor %arg0, %1 : i64 + %3 = llvm.sext %arg3 : i32 to i64 + %4 = llvm.icmp "sge" %2, %3 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.urem %0, %arg1 : i64 + %2 = llvm.trunc %1 : i64 to i1 + %3 = llvm.zext %2 : i1 to i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 + %1 = llvm.and %0, %arg1 : i64 + %2 = llvm.udiv %arg2, %arg1 : i64 + %3 = llvm.ashr %1, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.icmp "eq" %0, %arg1 : i64 + %2 = llvm.select %1, %arg2, %arg2 : i1, i64 + %3 = llvm.xor %arg0, %2 : i64 + %4 = llvm.srem %3, %arg1 : i64 + return %4 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { + %0 = llvm.and %arg2, %arg0 : i64 + %1 = llvm.ashr %0, %arg0 : i64 + %2 = llvm.select %arg1, %1, %0 : i1, i64 + %3 = llvm.and %arg0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.select %0, %arg0, %arg0 : i1, i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.zext %2 : i32 to i64 + %4 = llvm.icmp "eq" %3, %arg0 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.xor %arg0, %arg0 : i64 + %1 = llvm.sdiv %0, %arg0 : i64 + %2 = llvm.udiv %1, %1 : i64 + %3 = llvm.urem %2, %arg1 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.and %arg0, %arg0 : i64 + %1 = llvm.urem %arg0, %0 : i64 + %2 = llvm.and %arg0, %1 : i64 + %3 = llvm.ashr %arg1, %arg2 : i64 + %4 = llvm.icmp "ugt" %2, %3 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.icmp "ne" %arg0, %arg1 : i64 + %1 = llvm.select %0, %arg0, %arg0 : i1, i64 + %2 = llvm.sdiv %arg0, %1 : i64 + %3 = llvm.udiv %arg0, %arg2 : i64 + %4 = llvm.icmp "ne" %2, %3 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i1) -> i1 { + %0 = llvm.sext %arg1 : i1 to i64 + %1 = llvm.select %arg2, %arg0, %0 : i1, i64 + %2 = llvm.urem %0, %1 : i64 + %3 = llvm.udiv %arg0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i32) -> i1 { + %0 = llvm.sdiv %arg0, %arg0 : i64 + %1 = llvm.sext %arg2 : i32 to i64 + %2 = llvm.and %arg1, %1 : i64 + %3 = llvm.and %0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.trunc %arg2 : i64 to i32 + %1 = llvm.zext %0 : i32 to i64 + %2 = llvm.lshr %arg1, %1 : i64 + %3 = llvm.or %arg0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.select %arg0, %arg1, %arg2 : i1, i64 + %1 = llvm.and %0, %arg2 : i64 + %2 = llvm.sext %arg0 : i1 to i64 + %3 = llvm.udiv %1, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.select %arg1, %arg2, %arg2 : i1, i64 + %1 = llvm.select %arg0, %0, %arg2 : i1, i64 + %2 = llvm.and %arg2, %arg2 : i64 + %3 = llvm.and %1, %2 : i64 + %4 = llvm.udiv %3, %1 : i64 + return %4 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.urem %arg0, %arg1 : i64 + %1 = llvm.sdiv %arg0, %0 : i64 + %2 = llvm.urem %0, %1 : i64 + %3 = llvm.lshr %arg2, %2 : i64 + %4 = llvm.udiv %2, %3 : i64 + return %4 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1) -> i32 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.sdiv %arg0, %0 : i64 + %2 = llvm.select %arg1, %arg0, %arg0 : i1, i64 + %3 = llvm.and %1, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.srem %arg1, %arg2 : i64 + %1 = llvm.udiv %arg0, %0 : i64 + %2 = llvm.sdiv %arg1, %1 : i64 + %3 = llvm.udiv %2, %arg0 : i64 + %4 = llvm.icmp "ule" %1, %3 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.or %arg0, %arg1 : i64 + %1 = llvm.ashr %0, %arg2 : i64 + %2 = llvm.urem %1, %1 : i64 + %3 = llvm.ashr %2, %arg0 : i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.udiv %arg0, %arg0 : i64 + %1 = llvm.urem %0, %arg0 : i64 + %2 = llvm.udiv %1, %arg1 : i64 + %3 = llvm.sdiv %1, %2 : i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.urem %arg0, %arg1 : i64 + %1 = llvm.icmp "sge" %arg1, %arg2 : i64 + %2 = llvm.sext %1 : i1 to i64 + %3 = llvm.sdiv %0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.trunc %arg1 : i64 to i1 + %1 = llvm.select %0, %arg1, %arg2 : i1, i64 + %2 = llvm.and %arg0, %1 : i64 + %3 = llvm.or %arg2, %arg2 : i64 + %4 = llvm.icmp "sge" %2, %3 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i1 { + %0 = llvm.lshr %arg0, %arg1 : i64 + %1 = llvm.sext %arg3 : i1 to i64 + %2 = llvm.or %arg2, %1 : i64 + %3 = llvm.urem %arg0, %2 : i64 + %4 = llvm.icmp "sgt" %0, %3 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.urem %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.sext %1 : i1 to i64 + %3 = llvm.lshr %arg1, %0 : i64 + %4 = llvm.icmp "sle" %2, %3 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.trunc %arg2 : i64 to i32 + %1 = llvm.sext %0 : i32 to i64 + %2 = llvm.ashr %arg1, %1 : i64 + %3 = llvm.srem %arg0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.urem %arg1, %arg0 : i64 + %1 = llvm.srem %0, %arg1 : i64 + %2 = llvm.or %arg0, %1 : i64 + %3 = llvm.xor %arg0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.xor %arg0, %arg1 : i64 + %1 = llvm.urem %arg0, %arg0 : i64 + %2 = llvm.icmp "ule" %0, %1 : i64 + %3 = llvm.sext %2 : i1 to i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { + %0 = llvm.select %arg1, %arg2, %arg0 : i1, i64 + %1 = llvm.and %arg0, %0 : i64 + %2 = llvm.urem %arg0, %1 : i64 + %3 = llvm.and %2, %arg0 : i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i1) -> i32 { + %0 = llvm.sext %arg2 : i1 to i64 + %1 = llvm.srem %0, %arg0 : i64 + %2 = llvm.select %arg1, %0, %1 : i1, i64 + %3 = llvm.srem %arg0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.and %arg0, %arg1 : i64 + %1 = llvm.or %arg0, %0 : i64 + %2 = llvm.urem %arg2, %arg2 : i64 + %3 = llvm.lshr %1, %2 : i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { + %0 = llvm.select %arg1, %arg2, %arg2 : i1, i64 + %1 = llvm.sdiv %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.sext %arg1 : i1 to i64 + %1 = llvm.ashr %arg0, %0 : i64 + %2 = llvm.xor %arg2, %1 : i64 + %3 = llvm.xor %1, %2 : i64 + %4 = llvm.udiv %3, %0 : i64 + return %4 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i32) -> i64 { + %0 = llvm.zext %arg0 : i32 to i64 + %1 = llvm.srem %0, %0 : i64 + %2 = llvm.urem %1, %0 : i64 + %3 = llvm.or %1, %2 : i64 + %4 = llvm.srem %3, %0 : i64 + return %4 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.sdiv %arg0, %arg1 : i64 + %1 = llvm.and %0, %arg0 : i64 + %2 = llvm.ashr %1, %arg2 : i64 + %3 = llvm.trunc %2 : i64 to i32 + %4 = llvm.zext %3 : i32 to i64 + return %4 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.sdiv %arg0, %arg1 : i64 + %1 = llvm.icmp "uge" %arg2, %arg2 : i64 + %2 = llvm.select %1, %0, %0 : i1, i64 + %3 = llvm.lshr %0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.udiv %arg1, %arg0 : i64 + %1 = llvm.udiv %arg0, %0 : i64 + %2 = llvm.xor %1, %0 : i64 + %3 = llvm.lshr %arg0, %0 : i64 + %4 = llvm.icmp "ne" %2, %3 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.icmp "slt" %arg0, %arg0 : i64 + %1 = llvm.zext %0 : i1 to i64 + %2 = llvm.udiv %1, %arg1 : i64 + %3 = llvm.sdiv %arg0, %2 : i64 + %4 = llvm.icmp "eq" %arg0, %3 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i32) -> i1 { + %0 = llvm.zext %arg0 : i1 to i64 + %1 = llvm.lshr %0, %arg1 : i64 + %2 = llvm.zext %arg2 : i32 to i64 + %3 = llvm.and %1, %2 : i64 + %4 = llvm.icmp "slt" %0, %3 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.and %arg0, %arg1 : i64 + %1 = llvm.lshr %0, %arg0 : i64 + %2 = llvm.sdiv %1, %arg2 : i64 + %3 = llvm.or %0, %2 : i64 + %4 = llvm.lshr %3, %arg1 : i64 + return %4 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.ashr %arg0, %arg1 : i64 + %1 = llvm.xor %arg0, %0 : i64 + %2 = llvm.icmp "slt" %1, %arg2 : i64 + %3 = llvm.lshr %0, %arg2 : i64 + %4 = llvm.select %2, %arg0, %3 : i1, i64 + return %4 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.zext %0 : i32 to i64 + %2 = llvm.zext %arg1 : i32 to i64 + %3 = llvm.xor %1, %2 : i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.ashr %arg2, %arg0 : i64 + %1 = llvm.xor %arg1, %0 : i64 + %2 = llvm.udiv %arg0, %1 : i64 + %3 = llvm.lshr %1, %2 : i64 + %4 = llvm.icmp "ne" %2, %3 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.or %arg1, %arg2 : i64 + %1 = llvm.and %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i1 + %3 = llvm.sext %2 : i1 to i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.udiv %arg0, %arg0 : i64 + %1 = llvm.or %arg0, %0 : i64 + %2 = llvm.urem %arg2, %1 : i64 + %3 = llvm.select %arg1, %2, %arg2 : i1, i64 + %4 = llvm.lshr %arg0, %3 : i64 + return %4 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64) -> i32 { + %0 = llvm.or %arg1, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.sext %1 : i32 to i64 + %3 = llvm.select %arg0, %2, %2 : i1, i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { + %0 = llvm.sext %arg1 : i1 to i64 + %1 = llvm.select %arg1, %arg2, %0 : i1, i64 + %2 = llvm.trunc %1 : i64 to i1 + %3 = llvm.select %2, %arg0, %arg0 : i1, i64 + %4 = llvm.icmp "sge" %arg0, %3 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.xor %arg0, %arg0 : i64 + %1 = llvm.sdiv %arg0, %0 : i64 + %2 = llvm.lshr %arg1, %arg2 : i64 + %3 = llvm.and %1, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.urem %arg0, %arg0 : i64 + %1 = llvm.urem %arg1, %0 : i64 + %2 = llvm.urem %1, %0 : i64 + %3 = llvm.udiv %0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1) -> i32 { + %0 = llvm.and %arg0, %arg0 : i64 + %1 = llvm.or %0, %arg0 : i64 + %2 = llvm.select %arg1, %arg0, %1 : i1, i64 + %3 = llvm.and %0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { + %0 = llvm.lshr %arg2, %arg2 : i64 + %1 = llvm.select %arg1, %arg2, %0 : i1, i64 + %2 = llvm.srem %arg0, %1 : i64 + %3 = llvm.or %arg0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i32, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.sext %arg0 : i32 to i64 + %1 = llvm.urem %arg1, %arg2 : i64 + %2 = llvm.xor %0, %1 : i64 + %3 = llvm.and %0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 + %1 = llvm.ashr %arg1, %arg2 : i64 + %2 = llvm.udiv %1, %1 : i64 + %3 = llvm.and %0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.ashr %arg0, %arg0 : i64 + %1 = llvm.ashr %0, %0 : i64 + %2 = llvm.sdiv %arg1, %arg2 : i64 + %3 = llvm.and %1, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.icmp "sgt" %arg0, %arg1 : i64 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.ashr %arg0, %1 : i64 + %3 = llvm.udiv %2, %1 : i64 + %4 = llvm.or %1, %3 : i64 + return %4 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i64 { + %0 = llvm.srem %arg0, %arg1 : i64 + %1 = llvm.sext %arg2 : i1 to i64 + %2 = llvm.and %arg1, %1 : i64 + %3 = llvm.urem %2, %1 : i64 + %4 = llvm.udiv %0, %3 : i64 + return %4 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i1) -> i1 { + %0 = llvm.sext %arg0 : i1 to i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.zext %1 : i32 to i64 + %3 = llvm.xor %0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.udiv %arg0, %arg0 : i64 + %1 = llvm.trunc %arg0 : i64 to i1 + %2 = llvm.zext %1 : i1 to i64 + %3 = llvm.udiv %0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.udiv %0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i1 + %3 = llvm.select %2, %arg1, %arg0 : i1, i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.xor %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.sext %1 : i32 to i64 + %3 = llvm.xor %0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.sdiv %arg0, %arg1 : i64 + %1 = llvm.xor %arg0, %arg1 : i64 + %2 = llvm.urem %1, %arg2 : i64 + %3 = llvm.or %0, %2 : i64 + %4 = llvm.or %3, %arg2 : i64 + return %4 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.ashr %arg0, %arg0 : i64 + %1 = llvm.udiv %arg1, %arg0 : i64 + %2 = llvm.icmp "ult" %0, %1 : i64 + %3 = llvm.zext %2 : i1 to i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.ashr %arg0, %arg1 : i64 + %1 = llvm.or %arg2, %arg0 : i64 + %2 = llvm.srem %arg1, %1 : i64 + %3 = llvm.or %0, %2 : i64 + %4 = llvm.icmp "sge" %3, %1 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.icmp "sle" %arg0, %arg1 : i64 + %1 = llvm.select %0, %arg2, %arg0 : i1, i64 + %2 = llvm.and %arg0, %arg0 : i64 + %3 = llvm.ashr %1, %2 : i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.srem %arg1, %arg0 : i64 + %1 = llvm.ashr %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.zext %2 : i32 to i64 + %4 = llvm.udiv %3, %0 : i64 + return %4 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.and %arg0, %arg0 : i64 + %1 = llvm.udiv %arg1, %arg0 : i64 + %2 = llvm.trunc %1 : i64 to i1 + %3 = llvm.select %2, %arg2, %arg1 : i1, i64 + %4 = llvm.icmp "ult" %0, %3 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32, %arg2: i64, %arg3: i1) -> i1 { + %0 = llvm.sext %arg1 : i32 to i64 + %1 = llvm.lshr %arg0, %0 : i64 + %2 = llvm.srem %1, %arg2 : i64 + %3 = llvm.select %arg3, %arg2, %0 : i1, i64 + %4 = llvm.icmp "ne" %2, %3 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.xor %arg0, %arg1 : i64 + %1 = llvm.sdiv %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.zext %2 : i32 to i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.xor %arg1, %arg2 : i64 + %1 = llvm.xor %arg0, %0 : i64 + %2 = llvm.sdiv %arg2, %1 : i64 + %3 = llvm.and %1, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64) -> i32 { + %0 = llvm.zext %arg0 : i1 to i64 + %1 = llvm.trunc %arg1 : i64 to i1 + %2 = llvm.sext %1 : i1 to i64 + %3 = llvm.ashr %0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.zext %arg0 : i1 to i64 + %1 = llvm.udiv %0, %arg1 : i64 + %2 = llvm.lshr %arg2, %1 : i64 + %3 = llvm.or %1, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.select %0, %arg1, %arg0 : i1, i64 + %2 = llvm.xor %arg0, %1 : i64 + %3 = llvm.xor %arg2, %2 : i64 + %4 = llvm.lshr %2, %3 : i64 + return %4 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.srem %arg0, %arg1 : i64 + %1 = llvm.ashr %arg0, %0 : i64 + %2 = llvm.sdiv %1, %arg1 : i64 + %3 = llvm.or %0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.ashr %arg0, %arg0 : i64 + %1 = llvm.udiv %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32) -> i1 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.urem %0, %0 : i64 + %2 = llvm.zext %arg1 : i32 to i64 + %3 = llvm.urem %1, %2 : i64 + %4 = llvm.icmp "slt" %1, %3 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64) -> i64 { + %0 = llvm.ashr %arg1, %arg1 : i64 + %1 = llvm.and %arg1, %0 : i64 + %2 = llvm.select %arg0, %1, %1 : i1, i64 + %3 = llvm.trunc %2 : i64 to i32 + %4 = llvm.sext %3 : i32 to i64 + return %4 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.xor %arg0, %arg0 : i64 + %1 = llvm.sdiv %0, %arg1 : i64 + %2 = llvm.sdiv %0, %1 : i64 + %3 = llvm.and %1, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.sext %0 : i32 to i64 + %2 = llvm.trunc %1 : i64 to i1 + %3 = llvm.zext %2 : i1 to i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.xor %arg2, %arg1 : i64 + %1 = llvm.icmp "eq" %arg2, %0 : i64 + %2 = llvm.sext %1 : i1 to i64 + %3 = llvm.select %arg0, %arg1, %2 : i1, i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { + %0 = llvm.sext %arg2 : i1 to i64 + %1 = llvm.ashr %arg0, %0 : i64 + %2 = llvm.lshr %arg1, %1 : i64 + %3 = llvm.xor %2, %1 : i64 + %4 = llvm.icmp "ult" %arg0, %3 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.srem %arg1, %arg2 : i64 + %1 = llvm.ashr %arg0, %0 : i64 + %2 = llvm.icmp "ule" %1, %arg2 : i64 + %3 = llvm.zext %2 : i1 to i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.urem %arg0, %arg0 : i64 + %1 = llvm.and %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i1 + %3 = llvm.sext %2 : i1 to i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.or %0, %0 : i64 + %2 = llvm.udiv %1, %arg1 : i64 + %3 = llvm.udiv %2, %arg2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.select %0, %arg1, %arg2 : i1, i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.ashr %arg1, %arg2 : i64 + %1 = llvm.urem %arg1, %0 : i64 + %2 = llvm.ashr %arg1, %0 : i64 + %3 = llvm.select %arg0, %1, %2 : i1, i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { + %0 = llvm.trunc %arg1 : i64 to i1 + %1 = llvm.select %0, %arg2, %arg2 : i1, i64 + %2 = llvm.sext %arg3 : i32 to i64 + %3 = llvm.select %arg0, %1, %2 : i1, i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32, %arg2: i1) -> i32 { + %0 = llvm.sext %arg1 : i32 to i64 + %1 = llvm.udiv %arg0, %0 : i64 + %2 = llvm.sext %arg2 : i1 to i64 + %3 = llvm.xor %1, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.srem %arg0, %arg1 : i64 + %1 = llvm.icmp "ne" %0, %arg2 : i64 + %2 = llvm.zext %1 : i1 to i64 + %3 = llvm.sdiv %2, %0 : i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.srem %arg1, %arg2 : i64 + %1 = llvm.or %arg2, %arg1 : i64 + %2 = llvm.select %arg0, %0, %1 : i1, i64 + %3 = llvm.sdiv %2, %0 : i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i64 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.sext %1 : i32 to i64 + %3 = llvm.trunc %2 : i64 to i32 + %4 = llvm.sext %3 : i32 to i64 + return %4 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.or %arg0, %arg0 : i64 + %1 = llvm.xor %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.icmp "sgt" %arg0, %arg1 : i64 + %1 = llvm.icmp "uge" %arg0, %arg2 : i64 + %2 = llvm.xor %arg0, %arg1 : i64 + %3 = llvm.select %1, %2, %2 : i1, i64 + %4 = llvm.select %0, %3, %3 : i1, i64 + return %4 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1) -> i64 { + %0 = llvm.sext %arg1 : i1 to i64 + %1 = llvm.ashr %0, %arg0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.zext %2 : i32 to i64 + %4 = llvm.sdiv %arg0, %3 : i64 + return %4 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { + %0 = llvm.sext %arg2 : i1 to i64 + %1 = llvm.icmp "ult" %0, %arg1 : i64 + %2 = llvm.zext %1 : i1 to i64 + %3 = llvm.urem %arg1, %2 : i64 + %4 = llvm.icmp "ugt" %arg0, %3 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.and %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.sext %1 : i32 to i64 + %3 = llvm.urem %arg2, %arg1 : i64 + %4 = llvm.xor %2, %3 : i64 + return %4 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.ashr %arg0, %arg1 : i64 + %1 = llvm.sdiv %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { + %0 = llvm.icmp "ule" %arg0, %arg0 : i64 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.select %arg1, %arg2, %arg0 : i1, i64 + %3 = llvm.ashr %1, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + return %4 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.zext %0 : i1 to i64 + %2 = llvm.and %arg0, %arg1 : i64 + %3 = llvm.udiv %1, %2 : i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i1 { + %0 = llvm.xor %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.zext %1 : i1 to i64 + %3 = llvm.sdiv %arg0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.sdiv %arg1, %arg1 : i64 + %1 = llvm.urem %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i1 + %3 = llvm.zext %2 : i1 to i64 + %4 = llvm.trunc %3 : i64 to i1 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { + %0 = llvm.ashr %arg0, %arg0 : i64 + %1 = llvm.select %arg1, %arg2, %arg2 : i1, i64 + %2 = llvm.trunc %1 : i64 to i1 + %3 = llvm.sext %2 : i1 to i64 + %4 = llvm.icmp "ule" %0, %3 : i64 + return %4 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.sext %0 : i32 to i64 + %2 = llvm.or %1, %arg1 : i64 + %3 = llvm.zext %0 : i32 to i64 + %4 = llvm.icmp "ugt" %2, %3 : i64 + return %4 : i1 + } +} +// ----- diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_6.mlir b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_6.mlir new file mode 100644 index 0000000000..12bd88c709 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_6.mlir @@ -0,0 +1,1200 @@ +module { + func.func @main(%arg0: i64, %arg1: i1) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.zext %0 : i32 to i64 + %2 = llvm.ashr %1, %arg0 : i64 + %3 = llvm.urem %1, %2 : i64 + %4 = llvm.zext %arg1 : i1 to i64 + %5 = llvm.icmp "ult" %3, %4 : i64 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.ashr %arg1, %arg0 : i64 + %1 = llvm.sdiv %0, %arg2 : i64 + %2 = llvm.sdiv %arg2, %arg1 : i64 + %3 = llvm.sdiv %1, %2 : i64 + %4 = llvm.icmp "slt" %arg0, %3 : i64 + %5 = llvm.sext %4 : i1 to i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32) -> i1 { + %0 = llvm.zext %arg1 : i32 to i64 + %1 = llvm.srem %0, %0 : i64 + %2 = llvm.udiv %1, %0 : i64 + %3 = llvm.ashr %2, %arg0 : i64 + %4 = llvm.or %arg0, %3 : i64 + %5 = llvm.trunc %4 : i64 to i1 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.and %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.sext %1 : i32 to i64 + %3 = llvm.lshr %arg0, %arg1 : i64 + %4 = llvm.srem %2, %3 : i64 + %5 = llvm.udiv %2, %4 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.srem %arg0, %1 : i64 + %3 = llvm.sext %arg1 : i32 to i64 + %4 = llvm.sdiv %2, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 + %1 = llvm.srem %arg2, %0 : i64 + %2 = llvm.urem %1, %arg2 : i64 + %3 = llvm.icmp "ult" %0, %2 : i64 + %4 = llvm.select %3, %1, %0 : i1, i64 + %5 = llvm.trunc %4 : i64 to i1 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.xor %arg0, %arg1 : i64 + %1 = llvm.lshr %arg2, %arg1 : i64 + %2 = llvm.and %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + %4 = llvm.sext %3 : i32 to i64 + %5 = llvm.icmp "sge" %4, %arg1 : i64 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.trunc %arg1 : i64 to i32 + %1 = llvm.zext %0 : i32 to i64 + %2 = llvm.xor %arg1, %1 : i64 + %3 = llvm.lshr %2, %arg1 : i64 + %4 = llvm.lshr %arg0, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 + %1 = llvm.udiv %arg1, %arg2 : i64 + %2 = llvm.sdiv %arg1, %1 : i64 + %3 = llvm.urem %arg2, %2 : i64 + %4 = llvm.lshr %0, %3 : i64 + %5 = llvm.udiv %4, %2 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.and %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.sext %1 : i32 to i64 + %3 = llvm.trunc %2 : i64 to i1 + %4 = llvm.sext %3 : i1 to i64 + %5 = llvm.trunc %4 : i64 to i1 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.udiv %arg0, %arg0 : i64 + %1 = llvm.or %0, %0 : i64 + %2 = llvm.lshr %0, %arg1 : i64 + %3 = llvm.or %2, %0 : i64 + %4 = llvm.ashr %1, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { + %0 = llvm.sdiv %arg2, %arg2 : i64 + %1 = llvm.select %arg1, %0, %0 : i1, i64 + %2 = llvm.ashr %0, %arg0 : i64 + %3 = llvm.xor %1, %2 : i64 + %4 = llvm.xor %arg0, %3 : i64 + %5 = llvm.icmp "sle" %4, %arg0 : i64 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i32 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.ashr %arg1, %arg1 : i64 + %2 = llvm.lshr %0, %1 : i64 + %3 = llvm.select %arg2, %1, %2 : i1, i64 + %4 = llvm.lshr %2, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1) -> i1 { + %0 = llvm.urem %arg0, %arg0 : i64 + %1 = llvm.zext %arg1 : i1 to i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + %4 = llvm.srem %0, %3 : i64 + %5 = llvm.trunc %4 : i64 to i1 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i1 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.zext %1 : i32 to i64 + %3 = llvm.trunc %2 : i64 to i32 + %4 = llvm.zext %3 : i32 to i64 + %5 = llvm.trunc %4 : i64 to i1 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.udiv %arg0, %arg1 : i64 + %1 = llvm.xor %arg0, %arg2 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.zext %2 : i32 to i64 + %4 = llvm.sdiv %0, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.urem %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.zext %1 : i32 to i64 + %3 = llvm.trunc %2 : i64 to i1 + %4 = llvm.sext %3 : i1 to i64 + %5 = llvm.ashr %4, %0 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.srem %arg1, %arg2 : i64 + %1 = llvm.sdiv %0, %arg2 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + %4 = llvm.udiv %3, %0 : i64 + %5 = llvm.select %arg0, %0, %4 : i1, i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i64 { + %0 = llvm.ashr %arg0, %arg1 : i64 + %1 = llvm.srem %0, %arg2 : i64 + %2 = llvm.or %arg1, %arg2 : i64 + %3 = llvm.lshr %arg0, %arg1 : i64 + %4 = llvm.select %arg3, %2, %3 : i1, i64 + %5 = llvm.srem %1, %4 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.sext %0 : i32 to i64 + %2 = llvm.ashr %arg0, %arg2 : i64 + %3 = llvm.sdiv %2, %arg2 : i64 + %4 = llvm.lshr %arg1, %3 : i64 + %5 = llvm.icmp "ugt" %1, %4 : i64 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.udiv %arg0, %0 : i64 + %2 = llvm.trunc %arg1 : i64 to i32 + %3 = llvm.zext %2 : i32 to i64 + %4 = llvm.xor %1, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.sext %1 : i1 to i64 + %3 = llvm.ashr %arg0, %2 : i64 + %4 = llvm.srem %arg0, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i1 { + %0 = llvm.udiv %arg0, %arg0 : i64 + %1 = llvm.lshr %arg0, %0 : i64 + %2 = llvm.lshr %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + %4 = llvm.zext %3 : i32 to i64 + %5 = llvm.trunc %4 : i64 to i1 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i64 { + %0 = llvm.udiv %arg0, %arg1 : i64 + %1 = llvm.zext %arg2 : i1 to i64 + %2 = llvm.or %0, %1 : i64 + %3 = llvm.sdiv %2, %0 : i64 + %4 = llvm.trunc %3 : i64 to i32 + %5 = llvm.zext %4 : i32 to i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.icmp "ugt" %arg0, %arg0 : i64 + %1 = llvm.xor %arg1, %arg2 : i64 + %2 = llvm.lshr %1, %arg1 : i64 + %3 = llvm.select %0, %arg0, %2 : i1, i64 + %4 = llvm.trunc %3 : i64 to i1 + %5 = llvm.select %4, %arg1, %2 : i1, i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i32 { + %0 = llvm.lshr %arg0, %arg1 : i64 + %1 = llvm.select %arg3, %arg2, %arg1 : i1, i64 + %2 = llvm.udiv %arg2, %1 : i64 + %3 = llvm.urem %2, %arg1 : i64 + %4 = llvm.or %0, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1) -> i32 { + %0 = llvm.zext %arg0 : i1 to i64 + %1 = llvm.sdiv %0, %0 : i64 + %2 = llvm.and %1, %0 : i64 + %3 = llvm.xor %1, %2 : i64 + %4 = llvm.urem %0, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.ashr %arg0, %arg2 : i64 + %1 = llvm.srem %arg1, %0 : i64 + %2 = llvm.urem %arg1, %arg0 : i64 + %3 = llvm.icmp "ne" %1, %2 : i64 + %4 = llvm.zext %3 : i1 to i64 + %5 = llvm.icmp "ugt" %arg0, %4 : i64 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.and %arg1, %arg2 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.sext %1 : i1 to i64 + %3 = llvm.sdiv %arg0, %2 : i64 + %4 = llvm.lshr %3, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { + %0 = llvm.select %arg1, %arg0, %arg2 : i1, i64 + %1 = llvm.srem %arg0, %0 : i64 + %2 = llvm.or %1, %0 : i64 + %3 = llvm.trunc %2 : i64 to i1 + %4 = llvm.sext %3 : i1 to i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.select %0, %arg0, %arg1 : i1, i64 + %2 = llvm.lshr %arg0, %arg2 : i64 + %3 = llvm.xor %arg1, %2 : i64 + %4 = llvm.and %1, %3 : i64 + %5 = llvm.ashr %1, %4 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.or %arg0, %arg1 : i64 + %1 = llvm.sdiv %0, %arg1 : i64 + %2 = llvm.and %arg0, %1 : i64 + %3 = llvm.urem %0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i1 + %5 = llvm.select %4, %0, %arg1 : i1, i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.sdiv %arg0, %arg0 : i64 + %1 = llvm.srem %arg0, %0 : i64 + %2 = llvm.and %arg1, %arg2 : i64 + %3 = llvm.icmp "ugt" %1, %2 : i64 + %4 = llvm.zext %3 : i1 to i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.zext %0 : i32 to i64 + %2 = llvm.icmp "sge" %1, %arg1 : i64 + %3 = llvm.zext %2 : i1 to i64 + %4 = llvm.urem %3, %arg1 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { + %0 = llvm.select %arg1, %arg2, %arg2 : i1, i64 + %1 = llvm.lshr %arg0, %0 : i64 + %2 = llvm.sext %arg1 : i1 to i64 + %3 = llvm.and %1, %2 : i64 + %4 = llvm.and %1, %3 : i64 + %5 = llvm.trunc %4 : i64 to i1 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.zext %0 : i32 to i64 + %2 = llvm.sdiv %arg1, %arg0 : i64 + %3 = llvm.or %1, %2 : i64 + %4 = llvm.lshr %3, %arg1 : i64 + %5 = llvm.urem %3, %4 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.and %arg2, %1 : i64 + %3 = llvm.ashr %arg1, %2 : i64 + %4 = llvm.lshr %3, %1 : i64 + %5 = llvm.icmp "ne" %1, %4 : i64 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.urem %arg0, %arg0 : i64 + %1 = llvm.select %arg1, %arg2, %0 : i1, i64 + %2 = llvm.udiv %arg0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i1 + %4 = llvm.or %arg0, %arg2 : i64 + %5 = llvm.select %3, %4, %2 : i1, i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i32 { + %0 = llvm.urem %arg0, %arg1 : i64 + %1 = llvm.or %0, %arg1 : i64 + %2 = llvm.urem %1, %0 : i64 + %3 = llvm.zext %arg2 : i1 to i64 + %4 = llvm.xor %2, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1) -> i64 { + %0 = llvm.zext %arg1 : i1 to i64 + %1 = llvm.lshr %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.zext %2 : i32 to i64 + %4 = llvm.udiv %arg0, %3 : i64 + %5 = llvm.sdiv %3, %4 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.urem %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.sext %1 : i1 to i64 + %3 = llvm.udiv %2, %arg1 : i64 + %4 = llvm.ashr %arg0, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.zext %0 : i32 to i64 + %2 = llvm.trunc %arg0 : i64 to i1 + %3 = llvm.select %2, %1, %arg1 : i1, i64 + %4 = llvm.udiv %1, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.urem %arg0, %arg0 : i64 + %1 = llvm.xor %arg0, %0 : i64 + %2 = llvm.xor %1, %arg1 : i64 + %3 = llvm.ashr %2, %arg1 : i64 + %4 = llvm.udiv %0, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.srem %arg0, %arg1 : i64 + %1 = llvm.ashr %0, %arg2 : i64 + %2 = llvm.ashr %1, %0 : i64 + %3 = llvm.lshr %arg1, %arg0 : i64 + %4 = llvm.udiv %0, %3 : i64 + %5 = llvm.icmp "eq" %2, %4 : i64 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.ashr %arg1, %arg2 : i64 + %1 = llvm.sdiv %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + %4 = llvm.srem %3, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.select %arg1, %arg0, %arg0 : i1, i64 + %2 = llvm.select %0, %1, %1 : i1, i64 + %3 = llvm.urem %arg2, %arg0 : i64 + %4 = llvm.xor %2, %3 : i64 + %5 = llvm.srem %4, %arg0 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.srem %arg1, %arg0 : i64 + %1 = llvm.xor %0, %arg1 : i64 + %2 = llvm.ashr %arg0, %1 : i64 + %3 = llvm.urem %1, %0 : i64 + %4 = llvm.xor %2, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.sext %arg0 : i1 to i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.or %arg1, %arg2 : i64 + %3 = llvm.ashr %2, %0 : i64 + %4 = llvm.select %1, %3, %2 : i1, i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { + %0 = llvm.sdiv %arg0, %arg1 : i64 + %1 = llvm.select %arg2, %arg0, %0 : i1, i64 + %2 = llvm.udiv %0, %1 : i64 + %3 = llvm.srem %arg1, %2 : i64 + %4 = llvm.ashr %1, %3 : i64 + %5 = llvm.icmp "eq" %2, %4 : i64 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { + %0 = llvm.select %arg1, %arg2, %arg2 : i1, i64 + %1 = llvm.sdiv %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + %4 = llvm.srem %3, %0 : i64 + %5 = llvm.trunc %4 : i64 to i1 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.ashr %arg1, %arg2 : i64 + %1 = llvm.urem %arg0, %0 : i64 + %2 = llvm.udiv %arg2, %0 : i64 + %3 = llvm.sdiv %0, %2 : i64 + %4 = llvm.srem %1, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { + %0 = llvm.icmp "sgt" %arg0, %arg1 : i64 + %1 = llvm.sext %arg2 : i1 to i64 + %2 = llvm.select %0, %arg0, %1 : i1, i64 + %3 = llvm.udiv %2, %arg1 : i64 + %4 = llvm.lshr %1, %arg1 : i64 + %5 = llvm.icmp "ne" %3, %4 : i64 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.or %arg0, %arg0 : i64 + %1 = llvm.urem %arg2, %0 : i64 + %2 = llvm.ashr %arg2, %1 : i64 + %3 = llvm.srem %2, %2 : i64 + %4 = llvm.select %arg1, %3, %0 : i1, i64 + %5 = llvm.srem %0, %4 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.or %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.zext %1 : i1 to i64 + %3 = llvm.or %arg1, %0 : i64 + %4 = llvm.or %3, %2 : i64 + %5 = llvm.urem %2, %4 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.sext %0 : i32 to i64 + %2 = llvm.ashr %1, %1 : i64 + %3 = llvm.xor %arg0, %arg0 : i64 + %4 = llvm.and %1, %3 : i64 + %5 = llvm.lshr %2, %4 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.select %arg1, %arg0, %arg2 : i1, i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.zext %1 : i32 to i64 + %3 = llvm.urem %arg0, %2 : i64 + %4 = llvm.srem %arg2, %arg0 : i64 + %5 = llvm.ashr %3, %4 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.lshr %arg2, %arg0 : i64 + %1 = llvm.or %0, %arg0 : i64 + %2 = llvm.lshr %1, %arg0 : i64 + %3 = llvm.udiv %arg1, %2 : i64 + %4 = llvm.or %arg0, %3 : i64 + %5 = llvm.trunc %4 : i64 to i1 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.zext %arg0 : i1 to i64 + %1 = llvm.urem %0, %arg2 : i64 + %2 = llvm.and %arg1, %1 : i64 + %3 = llvm.select %arg0, %2, %0 : i1, i64 + %4 = llvm.xor %2, %3 : i64 + %5 = llvm.icmp "ule" %0, %4 : i64 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.srem %arg1, %arg0 : i64 + %1 = llvm.udiv %0, %arg2 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + %4 = llvm.or %arg0, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { + %0 = llvm.select %arg1, %arg0, %arg0 : i1, i64 + %1 = llvm.lshr %arg0, %0 : i64 + %2 = llvm.sdiv %arg2, %0 : i64 + %3 = llvm.udiv %1, %2 : i64 + %4 = llvm.sdiv %3, %arg2 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.or %arg0, %arg1 : i64 + %1 = llvm.udiv %0, %arg2 : i64 + %2 = llvm.sdiv %arg0, %arg1 : i64 + %3 = llvm.ashr %2, %arg1 : i64 + %4 = llvm.icmp "ult" %1, %3 : i64 + %5 = llvm.select %4, %arg1, %arg0 : i1, i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.lshr %arg2, %arg1 : i64 + %1 = llvm.select %arg0, %arg1, %0 : i1, i64 + %2 = llvm.udiv %arg2, %arg1 : i64 + %3 = llvm.or %1, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + %5 = llvm.zext %4 : i32 to i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.udiv %arg0, %arg2 : i64 + %1 = llvm.srem %arg1, %0 : i64 + %2 = llvm.udiv %arg0, %1 : i64 + %3 = llvm.xor %0, %arg1 : i64 + %4 = llvm.ashr %3, %arg0 : i64 + %5 = llvm.and %2, %4 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.xor %arg1, %arg1 : i64 + %1 = llvm.and %arg2, %0 : i64 + %2 = llvm.icmp "eq" %0, %1 : i64 + %3 = llvm.sext %2 : i1 to i64 + %4 = llvm.or %arg0, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i1) -> i1 { + %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 + %1 = llvm.select %arg2, %arg1, %arg1 : i1, i64 + %2 = llvm.udiv %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + %4 = llvm.zext %3 : i32 to i64 + %5 = llvm.trunc %4 : i64 to i1 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.and %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.sext %1 : i1 to i64 + %3 = llvm.udiv %arg2, %arg2 : i64 + %4 = llvm.udiv %2, %3 : i64 + %5 = llvm.sdiv %arg0, %4 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.zext %0 : i1 to i64 + %2 = llvm.zext %arg1 : i1 to i64 + %3 = llvm.icmp "ule" %1, %2 : i64 + %4 = llvm.select %3, %arg2, %arg0 : i1, i64 + %5 = llvm.trunc %4 : i64 to i1 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.sdiv %arg1, %arg2 : i64 + %1 = llvm.xor %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i1 + %3 = llvm.sext %2 : i1 to i64 + %4 = llvm.lshr %arg2, %1 : i64 + %5 = llvm.icmp "ule" %3, %4 : i64 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.udiv %arg0, %arg0 : i64 + %1 = llvm.xor %0, %0 : i64 + %2 = llvm.and %0, %1 : i64 + %3 = llvm.srem %arg1, %0 : i64 + %4 = llvm.srem %2, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.udiv %arg1, %arg1 : i64 + %1 = llvm.urem %arg0, %0 : i64 + %2 = llvm.icmp "sge" %1, %arg2 : i64 + %3 = llvm.zext %2 : i1 to i64 + %4 = llvm.or %arg0, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.and %arg2, %arg1 : i64 + %1 = llvm.xor %0, %arg2 : i64 + %2 = llvm.select %arg0, %arg1, %1 : i1, i64 + %3 = llvm.xor %arg2, %arg1 : i64 + %4 = llvm.urem %arg2, %3 : i64 + %5 = llvm.or %2, %4 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.ashr %arg1, %arg2 : i64 + %1 = llvm.and %arg0, %0 : i64 + %2 = llvm.lshr %1, %0 : i64 + %3 = llvm.xor %arg2, %arg0 : i64 + %4 = llvm.sdiv %2, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1) -> i1 { + %0 = llvm.zext %arg0 : i1 to i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.zext %1 : i1 to i64 + %3 = llvm.trunc %2 : i64 to i32 + %4 = llvm.sext %3 : i32 to i64 + %5 = llvm.trunc %4 : i64 to i1 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.srem %0, %arg1 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + %4 = llvm.udiv %3, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i1 { + %0 = llvm.zext %arg1 : i32 to i64 + %1 = llvm.sdiv %arg0, %arg2 : i64 + %2 = llvm.urem %0, %1 : i64 + %3 = llvm.urem %arg0, %2 : i64 + %4 = llvm.lshr %3, %0 : i64 + %5 = llvm.trunc %4 : i64 to i1 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1) -> i32 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.zext %arg1 : i1 to i64 + %2 = llvm.sdiv %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + %4 = llvm.sext %3 : i32 to i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i1 { + %0 = llvm.urem %arg2, %arg0 : i64 + %1 = llvm.sext %arg3 : i1 to i64 + %2 = llvm.or %0, %1 : i64 + %3 = llvm.urem %2, %arg2 : i64 + %4 = llvm.lshr %arg1, %3 : i64 + %5 = llvm.icmp "sle" %arg0, %4 : i64 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i32) -> i32 { + %0 = llvm.ashr %arg1, %arg2 : i64 + %1 = llvm.lshr %arg0, %0 : i64 + %2 = llvm.sext %arg3 : i32 to i64 + %3 = llvm.xor %2, %arg0 : i64 + %4 = llvm.or %1, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.sext %0 : i32 to i64 + %2 = llvm.sdiv %1, %1 : i64 + %3 = llvm.udiv %arg1, %arg1 : i64 + %4 = llvm.xor %3, %arg2 : i64 + %5 = llvm.icmp "ult" %2, %4 : i64 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.xor %arg0, %arg1 : i64 + %1 = llvm.or %0, %arg2 : i64 + %2 = llvm.udiv %arg2, %arg2 : i64 + %3 = llvm.urem %1, %2 : i64 + %4 = llvm.or %3, %0 : i64 + %5 = llvm.trunc %4 : i64 to i1 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.or %arg1, %arg2 : i64 + %1 = llvm.srem %arg0, %0 : i64 + %2 = llvm.urem %arg1, %arg2 : i64 + %3 = llvm.udiv %2, %0 : i64 + %4 = llvm.ashr %1, %3 : i64 + %5 = llvm.trunc %4 : i64 to i1 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.zext %arg0 : i1 to i64 + %1 = llvm.udiv %0, %arg1 : i64 + %2 = llvm.select %arg0, %arg2, %arg2 : i1, i64 + %3 = llvm.or %1, %2 : i64 + %4 = llvm.urem %0, %3 : i64 + %5 = llvm.icmp "uge" %3, %4 : i64 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.sdiv %arg0, %arg1 : i64 + %1 = llvm.and %arg2, %arg0 : i64 + %2 = llvm.udiv %1, %1 : i64 + %3 = llvm.trunc %2 : i64 to i1 + %4 = llvm.sext %3 : i1 to i64 + %5 = llvm.udiv %0, %4 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.udiv %arg0, %arg1 : i64 + %1 = llvm.srem %arg2, %arg0 : i64 + %2 = llvm.srem %0, %1 : i64 + %3 = llvm.urem %arg0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + %5 = llvm.sext %4 : i32 to i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.urem %arg1, %arg0 : i64 + %1 = llvm.xor %arg2, %0 : i64 + %2 = llvm.or %0, %1 : i64 + %3 = llvm.xor %arg0, %2 : i64 + %4 = llvm.or %3, %1 : i64 + %5 = llvm.lshr %3, %4 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i32 { + %0 = llvm.ashr %arg0, %arg1 : i64 + %1 = llvm.select %arg2, %arg0, %0 : i1, i64 + %2 = llvm.icmp "sge" %0, %1 : i64 + %3 = llvm.sext %2 : i1 to i64 + %4 = llvm.srem %3, %1 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.ashr %arg0, %arg0 : i64 + %1 = llvm.lshr %0, %arg1 : i64 + %2 = llvm.udiv %arg2, %0 : i64 + %3 = llvm.trunc %2 : i64 to i1 + %4 = llvm.sext %3 : i1 to i64 + %5 = llvm.lshr %1, %4 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.icmp "sge" %arg0, %arg0 : i64 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.udiv %1, %arg1 : i64 + %3 = llvm.icmp "sge" %1, %2 : i64 + %4 = llvm.sext %3 : i1 to i64 + %5 = llvm.icmp "uge" %4, %arg2 : i64 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.srem %arg0, %arg1 : i64 + %1 = llvm.xor %0, %arg1 : i64 + %2 = llvm.xor %1, %0 : i64 + %3 = llvm.and %2, %arg2 : i64 + %4 = llvm.ashr %1, %3 : i64 + %5 = llvm.and %4, %1 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.sdiv %arg0, %arg1 : i64 + %1 = llvm.trunc %arg1 : i64 to i32 + %2 = llvm.zext %1 : i32 to i64 + %3 = llvm.sdiv %arg1, %2 : i64 + %4 = llvm.or %0, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i64 { + %0 = llvm.udiv %arg0, %arg1 : i64 + %1 = llvm.lshr %arg2, %arg1 : i64 + %2 = llvm.lshr %arg1, %1 : i64 + %3 = llvm.select %arg3, %arg2, %arg0 : i1, i64 + %4 = llvm.or %2, %3 : i64 + %5 = llvm.or %0, %4 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.xor %arg0, %arg1 : i64 + %1 = llvm.icmp "sge" %arg0, %0 : i64 + %2 = llvm.zext %1 : i1 to i64 + %3 = llvm.urem %2, %0 : i64 + %4 = llvm.udiv %arg2, %3 : i64 + %5 = llvm.icmp "eq" %0, %4 : i64 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.udiv %arg0, %arg1 : i64 + %1 = llvm.sdiv %arg1, %arg2 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + %4 = llvm.xor %0, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i32) -> i1 { + %0 = llvm.udiv %arg0, %arg1 : i64 + %1 = llvm.zext %arg2 : i32 to i64 + %2 = llvm.lshr %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + %4 = llvm.sext %3 : i32 to i64 + %5 = llvm.trunc %4 : i64 to i1 + return %5 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.icmp "eq" %arg1, %arg2 : i64 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.icmp "sgt" %arg0, %1 : i64 + %3 = llvm.zext %2 : i1 to i64 + %4 = llvm.lshr %3, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.trunc %arg2 : i64 to i32 + %1 = llvm.zext %0 : i32 to i64 + %2 = llvm.udiv %arg1, %1 : i64 + %3 = llvm.sdiv %2, %arg2 : i64 + %4 = llvm.and %arg0, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + return %5 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64, %arg3: i32) -> i64 { + %0 = llvm.sext %arg3 : i32 to i64 + %1 = llvm.select %arg1, %arg2, %0 : i1, i64 + %2 = llvm.icmp "ugt" %arg0, %1 : i64 + %3 = llvm.zext %2 : i1 to i64 + %4 = llvm.xor %arg0, %3 : i64 + %5 = llvm.udiv %4, %0 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i32) -> i64 { + %0 = llvm.ashr %arg0, %arg1 : i64 + %1 = llvm.sext %arg2 : i32 to i64 + %2 = llvm.or %1, %1 : i64 + %3 = llvm.xor %1, %2 : i64 + %4 = llvm.srem %3, %3 : i64 + %5 = llvm.xor %0, %4 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.sext %0 : i32 to i64 + %2 = llvm.ashr %arg1, %arg0 : i64 + %3 = llvm.trunc %2 : i64 to i1 + %4 = llvm.select %3, %arg0, %arg2 : i1, i64 + %5 = llvm.lshr %1, %4 : i64 + return %5 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.ashr %arg0, %arg0 : i64 + %1 = llvm.or %0, %arg1 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + %4 = llvm.xor %3, %1 : i64 + %5 = llvm.icmp "ugt" %0, %4 : i64 + return %5 : i1 + } +} +// ----- diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_7.mlir b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_7.mlir new file mode 100644 index 0000000000..d671e6d157 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_7.mlir @@ -0,0 +1,1300 @@ +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.and %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.zext %1 : i1 to i64 + %3 = llvm.urem %2, %arg1 : i64 + %4 = llvm.icmp "sgt" %3, %arg1 : i64 + %5 = llvm.zext %4 : i1 to i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i32) -> i32 { + %0 = llvm.xor %arg0, %arg1 : i64 + %1 = llvm.icmp "uge" %arg1, %arg2 : i64 + %2 = llvm.sext %arg3 : i32 to i64 + %3 = llvm.select %1, %0, %2 : i1, i64 + %4 = llvm.and %0, %3 : i64 + %5 = llvm.xor %arg0, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.lshr %arg1, %arg1 : i64 + %1 = llvm.udiv %arg0, %0 : i64 + %2 = llvm.srem %0, %arg2 : i64 + %3 = llvm.sdiv %1, %2 : i64 + %4 = llvm.lshr %3, %arg1 : i64 + %5 = llvm.trunc %4 : i64 to i32 + %6 = llvm.zext %5 : i32 to i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1) -> i32 { + %0 = llvm.sext %arg1 : i1 to i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.zext %1 : i1 to i64 + %3 = llvm.urem %arg0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + %5 = llvm.sext %4 : i32 to i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.urem %0, %arg1 : i64 + %2 = llvm.srem %arg0, %1 : i64 + %3 = llvm.urem %2, %arg2 : i64 + %4 = llvm.icmp "sgt" %arg0, %3 : i64 + %5 = llvm.select %4, %0, %3 : i1, i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.srem %arg1, %arg2 : i64 + %1 = llvm.srem %arg0, %0 : i64 + %2 = llvm.icmp "ugt" %arg0, %1 : i64 + %3 = llvm.select %2, %0, %arg0 : i1, i64 + %4 = llvm.sdiv %arg2, %arg0 : i64 + %5 = llvm.select %2, %3, %4 : i1, i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.udiv %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.lshr %arg2, %0 : i64 + %3 = llvm.select %1, %arg2, %2 : i1, i64 + %4 = llvm.sdiv %arg0, %2 : i64 + %5 = llvm.select %arg1, %3, %4 : i1, i64 + %6 = llvm.sdiv %arg0, %5 : i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.urem %arg0, %arg0 : i64 + %2 = llvm.sdiv %arg0, %1 : i64 + %3 = llvm.select %0, %2, %2 : i1, i64 + %4 = llvm.trunc %3 : i64 to i1 + %5 = llvm.select %4, %arg1, %arg2 : i1, i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { + %0 = llvm.sext %arg0 : i1 to i64 + %1 = llvm.udiv %arg1, %arg2 : i64 + %2 = llvm.xor %0, %1 : i64 + %3 = llvm.and %2, %2 : i64 + %4 = llvm.sext %arg3 : i32 to i64 + %5 = llvm.udiv %3, %4 : i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.icmp "sle" %arg0, %arg1 : i64 + %1 = llvm.zext %0 : i1 to i64 + %2 = llvm.trunc %1 : i64 to i1 + %3 = llvm.udiv %arg1, %1 : i64 + %4 = llvm.select %2, %3, %arg2 : i1, i64 + %5 = llvm.udiv %arg0, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i1 { + %0 = llvm.sext %arg1 : i32 to i64 + %1 = llvm.icmp "uge" %0, %arg2 : i64 + %2 = llvm.select %1, %0, %0 : i1, i64 + %3 = llvm.urem %2, %2 : i64 + %4 = llvm.srem %arg0, %3 : i64 + %5 = llvm.ashr %arg0, %4 : i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.zext %0 : i1 to i64 + %2 = llvm.udiv %arg0, %1 : i64 + %3 = llvm.urem %1, %arg1 : i64 + %4 = llvm.urem %2, %3 : i64 + %5 = llvm.sdiv %1, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.urem %arg1, %arg1 : i64 + %2 = llvm.select %arg2, %1, %1 : i1, i64 + %3 = llvm.select %0, %arg1, %2 : i1, i64 + %4 = llvm.trunc %3 : i64 to i1 + %5 = llvm.zext %4 : i1 to i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.icmp "ugt" %arg1, %arg1 : i64 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.icmp "ne" %arg0, %1 : i64 + %3 = llvm.srem %arg1, %arg2 : i64 + %4 = llvm.select %2, %arg1, %3 : i1, i64 + %5 = llvm.urem %4, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.xor %arg0, %arg0 : i64 + %1 = llvm.lshr %arg0, %0 : i64 + %2 = llvm.xor %1, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + %4 = llvm.sext %3 : i32 to i64 + %5 = llvm.srem %4, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.ashr %arg1, %arg2 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.sext %1 : i32 to i64 + %3 = llvm.zext %1 : i32 to i64 + %4 = llvm.srem %3, %arg1 : i64 + %5 = llvm.ashr %2, %4 : i64 + %6 = llvm.urem %arg0, %5 : i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i32 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.sext %arg1 : i32 to i64 + %2 = llvm.or %1, %arg0 : i64 + %3 = llvm.urem %0, %2 : i64 + %4 = llvm.udiv %arg2, %0 : i64 + %5 = llvm.srem %3, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i32) -> i32 { + %0 = llvm.srem %arg0, %arg1 : i64 + %1 = llvm.zext %arg2 : i32 to i64 + %2 = llvm.ashr %0, %1 : i64 + %3 = llvm.trunc %arg0 : i64 to i32 + %4 = llvm.zext %3 : i32 to i64 + %5 = llvm.urem %2, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.sext %0 : i32 to i64 + %2 = llvm.sdiv %1, %1 : i64 + %3 = llvm.sdiv %2, %arg1 : i64 + %4 = llvm.and %arg0, %3 : i64 + %5 = llvm.lshr %arg0, %4 : i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64) -> i32 { + %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 + %1 = llvm.xor %0, %0 : i64 + %2 = llvm.urem %1, %1 : i64 + %3 = llvm.icmp "sgt" %1, %2 : i64 + %4 = llvm.sdiv %0, %0 : i64 + %5 = llvm.select %3, %4, %4 : i1, i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.udiv %arg0, %arg1 : i64 + %1 = llvm.icmp "ule" %arg1, %0 : i64 + %2 = llvm.select %1, %arg0, %arg2 : i1, i64 + %3 = llvm.trunc %2 : i64 to i1 + %4 = llvm.sext %3 : i1 to i64 + %5 = llvm.urem %4, %arg0 : i64 + %6 = llvm.icmp "ugt" %0, %5 : i64 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.xor %arg0, %arg1 : i64 + %1 = llvm.lshr %0, %arg1 : i64 + %2 = llvm.ashr %0, %1 : i64 + %3 = llvm.and %arg0, %arg2 : i64 + %4 = llvm.lshr %3, %arg2 : i64 + %5 = llvm.and %2, %4 : i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.and %arg2, %0 : i64 + %2 = llvm.icmp "ule" %arg1, %1 : i64 + %3 = llvm.zext %2 : i1 to i64 + %4 = llvm.xor %0, %3 : i64 + %5 = llvm.sdiv %arg0, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.zext %2 : i32 to i64 + %4 = llvm.xor %3, %arg1 : i64 + %5 = llvm.trunc %4 : i64 to i1 + %6 = llvm.zext %5 : i1 to i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.sext %arg1 : i1 to i64 + %1 = llvm.udiv %arg0, %0 : i64 + %2 = llvm.icmp "uge" %arg2, %1 : i64 + %3 = llvm.ashr %arg2, %1 : i64 + %4 = llvm.xor %arg2, %3 : i64 + %5 = llvm.select %2, %3, %4 : i1, i64 + %6 = llvm.ashr %1, %5 : i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.icmp "uge" %arg1, %arg0 : i64 + %1 = llvm.zext %0 : i1 to i64 + %2 = llvm.udiv %arg0, %1 : i64 + %3 = llvm.lshr %arg2, %arg0 : i64 + %4 = llvm.ashr %3, %arg2 : i64 + %5 = llvm.xor %2, %4 : i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { + %0 = llvm.select %arg2, %arg1, %arg1 : i1, i64 + %1 = llvm.lshr %arg1, %0 : i64 + %2 = llvm.and %0, %arg0 : i64 + %3 = llvm.srem %0, %2 : i64 + %4 = llvm.sdiv %1, %3 : i64 + %5 = llvm.ashr %arg0, %4 : i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.srem %arg0, %arg1 : i64 + %1 = llvm.icmp "sgt" %arg0, %0 : i64 + %2 = llvm.and %arg2, %arg1 : i64 + %3 = llvm.ashr %0, %0 : i64 + %4 = llvm.select %1, %2, %3 : i1, i64 + %5 = llvm.srem %arg0, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { + %0 = llvm.udiv %arg0, %arg0 : i64 + %1 = llvm.or %0, %arg0 : i64 + %2 = llvm.select %arg1, %arg2, %1 : i1, i64 + %3 = llvm.xor %1, %2 : i64 + %4 = llvm.sdiv %0, %3 : i64 + %5 = llvm.or %4, %3 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.urem %arg2, %arg0 : i64 + %1 = llvm.srem %arg2, %0 : i64 + %2 = llvm.trunc %1 : i64 to i1 + %3 = llvm.zext %2 : i1 to i64 + %4 = llvm.srem %arg2, %3 : i64 + %5 = llvm.lshr %arg1, %4 : i64 + %6 = llvm.icmp "ugt" %arg0, %5 : i64 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { + %0 = llvm.srem %arg0, %arg1 : i64 + %1 = llvm.icmp "ne" %arg2, %arg1 : i64 + %2 = llvm.zext %arg3 : i32 to i64 + %3 = llvm.srem %arg0, %arg0 : i64 + %4 = llvm.urem %3, %arg2 : i64 + %5 = llvm.select %1, %2, %4 : i1, i64 + %6 = llvm.icmp "ule" %0, %5 : i64 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.or %arg0, %arg1 : i64 + %1 = llvm.trunc %arg2 : i64 to i32 + %2 = llvm.sext %1 : i32 to i64 + %3 = llvm.xor %2, %0 : i64 + %4 = llvm.lshr %3, %arg2 : i64 + %5 = llvm.udiv %0, %4 : i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.srem %arg1, %arg0 : i64 + %1 = llvm.xor %0, %arg2 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + %4 = llvm.icmp "ne" %arg0, %3 : i64 + %5 = llvm.zext %4 : i1 to i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i32) -> i64 { + %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 + %1 = llvm.and %0, %arg1 : i64 + %2 = llvm.sext %arg2 : i32 to i64 + %3 = llvm.icmp "ne" %1, %2 : i64 + %4 = llvm.sext %3 : i1 to i64 + %5 = llvm.trunc %4 : i64 to i1 + %6 = llvm.zext %5 : i1 to i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.ashr %arg1, %arg2 : i64 + %1 = llvm.or %arg0, %0 : i64 + %2 = llvm.srem %1, %1 : i64 + %3 = llvm.trunc %2 : i64 to i1 + %4 = llvm.or %0, %0 : i64 + %5 = llvm.select %3, %4, %arg0 : i1, i64 + %6 = llvm.srem %5, %arg1 : i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.lshr %arg0, %arg1 : i64 + %1 = llvm.ashr %arg1, %0 : i64 + %2 = llvm.xor %1, %0 : i64 + %3 = llvm.icmp "ult" %arg0, %2 : i64 + %4 = llvm.zext %3 : i1 to i64 + %5 = llvm.and %arg0, %4 : i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.and %arg1, %arg1 : i64 + %1 = llvm.or %arg0, %0 : i64 + %2 = llvm.icmp "ult" %arg1, %1 : i64 + %3 = llvm.select %2, %arg2, %0 : i1, i64 + %4 = llvm.or %arg0, %3 : i64 + %5 = llvm.xor %4, %3 : i64 + %6 = llvm.icmp "slt" %1, %5 : i64 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i32 { + %0 = llvm.urem %arg1, %arg2 : i64 + %1 = llvm.and %arg0, %0 : i64 + %2 = llvm.zext %arg3 : i1 to i64 + %3 = llvm.srem %2, %0 : i64 + %4 = llvm.srem %arg0, %3 : i64 + %5 = llvm.or %1, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.or %arg0, %arg1 : i64 + %1 = llvm.lshr %0, %arg2 : i64 + %2 = llvm.urem %1, %1 : i64 + %3 = llvm.and %2, %2 : i64 + %4 = llvm.urem %arg1, %3 : i64 + %5 = llvm.or %arg0, %4 : i64 + %6 = llvm.icmp "ne" %1, %5 : i64 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.and %arg0, %arg0 : i64 + %1 = llvm.xor %arg1, %arg2 : i64 + %2 = llvm.and %0, %1 : i64 + %3 = llvm.ashr %1, %arg1 : i64 + %4 = llvm.lshr %2, %3 : i64 + %5 = llvm.icmp "sgt" %0, %4 : i64 + %6 = llvm.zext %5 : i1 to i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i32) -> i32 { + %0 = llvm.ashr %arg0, %arg1 : i64 + %1 = llvm.zext %arg2 : i32 to i64 + %2 = llvm.urem %arg1, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + %4 = llvm.sext %3 : i32 to i64 + %5 = llvm.urem %0, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.icmp "uge" %arg0, %arg1 : i64 + %1 = llvm.select %0, %arg2, %arg0 : i1, i64 + %2 = llvm.urem %arg1, %arg1 : i64 + %3 = llvm.icmp "ugt" %1, %2 : i64 + %4 = llvm.select %3, %arg2, %1 : i1, i64 + %5 = llvm.select %3, %2, %4 : i1, i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.and %arg0, %arg1 : i64 + %1 = llvm.srem %0, %arg2 : i64 + %2 = llvm.and %arg1, %0 : i64 + %3 = llvm.trunc %2 : i64 to i32 + %4 = llvm.zext %3 : i32 to i64 + %5 = llvm.srem %1, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64, %arg3: i32) -> i32 { + %0 = llvm.select %arg0, %arg1, %arg2 : i1, i64 + %1 = llvm.zext %arg3 : i32 to i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + %4 = llvm.lshr %0, %3 : i64 + %5 = llvm.lshr %4, %arg1 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i32 { + %0 = llvm.xor %arg0, %arg1 : i64 + %1 = llvm.select %arg2, %arg1, %arg1 : i1, i64 + %2 = llvm.xor %arg0, %1 : i64 + %3 = llvm.urem %0, %2 : i64 + %4 = llvm.ashr %3, %3 : i64 + %5 = llvm.xor %4, %2 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.udiv %arg1, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.sext %1 : i32 to i64 + %3 = llvm.urem %2, %arg1 : i64 + %4 = llvm.and %3, %arg2 : i64 + %5 = llvm.xor %arg0, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.and %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.sext %1 : i1 to i64 + %3 = llvm.select %1, %arg2, %0 : i1, i64 + %4 = llvm.xor %arg2, %3 : i64 + %5 = llvm.udiv %2, %4 : i64 + %6 = llvm.urem %0, %5 : i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.xor %arg0, %arg1 : i64 + %1 = llvm.udiv %0, %arg0 : i64 + %2 = llvm.udiv %1, %arg2 : i64 + %3 = llvm.lshr %0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i1 + %5 = llvm.zext %4 : i1 to i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { + %0 = llvm.sdiv %arg0, %arg0 : i64 + %1 = llvm.icmp "ule" %arg1, %arg2 : i64 + %2 = llvm.zext %arg3 : i32 to i64 + %3 = llvm.udiv %2, %arg1 : i64 + %4 = llvm.select %1, %arg1, %3 : i1, i64 + %5 = llvm.and %0, %4 : i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.sdiv %arg0, %arg0 : i64 + %1 = llvm.lshr %0, %arg1 : i64 + %2 = llvm.udiv %arg1, %arg2 : i64 + %3 = llvm.sdiv %1, %2 : i64 + %4 = llvm.ashr %0, %3 : i64 + %5 = llvm.udiv %0, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.srem %arg1, %arg2 : i64 + %2 = llvm.select %0, %1, %arg2 : i1, i64 + %3 = llvm.xor %arg0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + %5 = llvm.zext %4 : i32 to i64 + %6 = llvm.and %5, %arg1 : i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { + %0 = llvm.zext %arg1 : i1 to i64 + %1 = llvm.and %arg0, %arg2 : i64 + %2 = llvm.xor %0, %1 : i64 + %3 = llvm.ashr %arg0, %2 : i64 + %4 = llvm.urem %3, %1 : i64 + %5 = llvm.srem %arg0, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.or %arg0, %arg0 : i64 + %1 = llvm.urem %arg0, %0 : i64 + %2 = llvm.icmp "sge" %arg1, %arg1 : i64 + %3 = llvm.sext %2 : i1 to i64 + %4 = llvm.udiv %1, %3 : i64 + %5 = llvm.urem %arg0, %4 : i64 + %6 = llvm.and %5, %arg2 : i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.icmp "ult" %arg0, %0 : i64 + %2 = llvm.select %1, %arg1, %arg0 : i1, i64 + %3 = llvm.trunc %2 : i64 to i1 + %4 = llvm.sext %3 : i1 to i64 + %5 = llvm.srem %4, %arg0 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.ashr %arg1, %arg2 : i64 + %1 = llvm.select %arg0, %0, %0 : i1, i64 + %2 = llvm.srem %1, %1 : i64 + %3 = llvm.ashr %2, %1 : i64 + %4 = llvm.udiv %arg1, %3 : i64 + %5 = llvm.udiv %2, %4 : i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.zext %0 : i1 to i64 + %2 = llvm.zext %arg1 : i32 to i64 + %3 = llvm.srem %2, %2 : i64 + %4 = llvm.ashr %2, %3 : i64 + %5 = llvm.srem %1, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.sdiv %arg0, %arg0 : i64 + %1 = llvm.or %arg1, %arg2 : i64 + %2 = llvm.ashr %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i1 + %4 = llvm.select %3, %0, %2 : i1, i64 + %5 = llvm.xor %arg0, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.urem %arg0, %arg1 : i64 + %1 = llvm.sdiv %arg2, %0 : i64 + %2 = llvm.urem %arg1, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + %4 = llvm.sext %3 : i32 to i64 + %5 = llvm.or %arg0, %4 : i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.udiv %arg0, %arg1 : i64 + %1 = llvm.trunc %arg2 : i64 to i32 + %2 = llvm.zext %1 : i32 to i64 + %3 = llvm.ashr %arg2, %0 : i64 + %4 = llvm.icmp "ne" %2, %3 : i64 + %5 = llvm.select %4, %3, %arg0 : i1, i64 + %6 = llvm.lshr %0, %5 : i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.icmp "uge" %arg0, %arg0 : i64 + %1 = llvm.urem %arg0, %arg0 : i64 + %2 = llvm.select %0, %1, %arg1 : i1, i64 + %3 = llvm.sdiv %arg0, %2 : i64 + %4 = llvm.xor %arg2, %arg2 : i64 + %5 = llvm.icmp "sgt" %3, %4 : i64 + %6 = llvm.zext %5 : i1 to i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.icmp "sge" %arg0, %arg0 : i64 + %1 = llvm.udiv %arg1, %arg0 : i64 + %2 = llvm.srem %1, %arg2 : i64 + %3 = llvm.xor %arg0, %arg2 : i64 + %4 = llvm.select %0, %2, %3 : i1, i64 + %5 = llvm.sext %0 : i1 to i64 + %6 = llvm.icmp "sge" %4, %5 : i64 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.or %arg1, %arg2 : i64 + %1 = llvm.udiv %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + %4 = llvm.xor %1, %1 : i64 + %5 = llvm.and %3, %4 : i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i1) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.sext %0 : i32 to i64 + %2 = llvm.zext %arg2 : i1 to i64 + %3 = llvm.select %arg1, %2, %arg0 : i1, i64 + %4 = llvm.icmp "ule" %3, %3 : i64 + %5 = llvm.select %4, %3, %2 : i1, i64 + %6 = llvm.and %1, %5 : i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.or %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.lshr %arg2, %0 : i64 + %3 = llvm.select %1, %2, %2 : i1, i64 + %4 = llvm.srem %arg1, %arg0 : i64 + %5 = llvm.or %3, %4 : i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.icmp "slt" %arg0, %0 : i64 + %2 = llvm.trunc %arg1 : i64 to i1 + %3 = llvm.sext %2 : i1 to i64 + %4 = llvm.lshr %arg1, %arg2 : i64 + %5 = llvm.select %1, %3, %4 : i1, i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.select %0, %arg1, %arg1 : i1, i64 + %2 = llvm.sdiv %1, %arg1 : i64 + %3 = llvm.srem %arg2, %arg2 : i64 + %4 = llvm.or %1, %3 : i64 + %5 = llvm.or %2, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i32 { + %0 = llvm.urem %arg1, %arg0 : i64 + %1 = llvm.lshr %arg0, %0 : i64 + %2 = llvm.select %arg2, %arg0, %0 : i1, i64 + %3 = llvm.sdiv %2, %2 : i64 + %4 = llvm.sdiv %1, %3 : i64 + %5 = llvm.sdiv %arg0, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i32, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.zext %arg0 : i32 to i64 + %1 = llvm.and %0, %0 : i64 + %2 = llvm.xor %arg1, %arg2 : i64 + %3 = llvm.icmp "ugt" %1, %2 : i64 + %4 = llvm.sext %3 : i1 to i64 + %5 = llvm.ashr %4, %arg2 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.zext %arg1 : i1 to i64 + %1 = llvm.and %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.zext %2 : i32 to i64 + %4 = llvm.trunc %arg2 : i64 to i32 + %5 = llvm.zext %4 : i32 to i64 + %6 = llvm.or %3, %5 : i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { + %0 = llvm.icmp "ult" %arg1, %arg1 : i64 + %1 = llvm.select %0, %arg2, %arg2 : i1, i64 + %2 = llvm.icmp "ule" %arg0, %1 : i64 + %3 = llvm.sext %2 : i1 to i64 + %4 = llvm.sext %arg3 : i32 to i64 + %5 = llvm.urem %arg1, %4 : i64 + %6 = llvm.icmp "sgt" %3, %5 : i64 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.or %arg0, %arg1 : i64 + %1 = llvm.or %arg1, %arg2 : i64 + %2 = llvm.icmp "sge" %0, %1 : i64 + %3 = llvm.select %2, %1, %arg0 : i1, i64 + %4 = llvm.srem %arg2, %3 : i64 + %5 = llvm.select %2, %4, %arg2 : i1, i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.lshr %arg0, %arg1 : i64 + %1 = llvm.sdiv %arg1, %0 : i64 + %2 = llvm.urem %0, %1 : i64 + %3 = llvm.or %2, %1 : i64 + %4 = llvm.srem %1, %2 : i64 + %5 = llvm.urem %arg2, %4 : i64 + %6 = llvm.and %3, %5 : i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.xor %arg0, %arg0 : i64 + %1 = llvm.urem %0, %arg2 : i64 + %2 = llvm.lshr %arg1, %1 : i64 + %3 = llvm.ashr %arg0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i1 + %5 = llvm.sext %4 : i1 to i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { + %0 = llvm.ashr %arg0, %arg1 : i64 + %1 = llvm.select %arg2, %arg0, %arg1 : i1, i64 + %2 = llvm.sdiv %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i1 + %4 = llvm.ashr %0, %2 : i64 + %5 = llvm.select %3, %4, %0 : i1, i64 + %6 = llvm.icmp "ule" %2, %5 : i64 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.udiv %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.select %1, %arg2, %0 : i1, i64 + %3 = llvm.xor %2, %arg1 : i64 + %4 = llvm.srem %arg1, %3 : i64 + %5 = llvm.select %1, %arg1, %4 : i1, i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i1 { + %0 = llvm.sext %arg1 : i32 to i64 + %1 = llvm.or %0, %arg2 : i64 + %2 = llvm.srem %arg0, %1 : i64 + %3 = llvm.zext %arg1 : i32 to i64 + %4 = llvm.sdiv %1, %1 : i64 + %5 = llvm.and %3, %4 : i64 + %6 = llvm.icmp "sle" %2, %5 : i64 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.select %arg0, %arg1, %arg1 : i1, i64 + %1 = llvm.or %0, %arg1 : i64 + %2 = llvm.udiv %1, %1 : i64 + %3 = llvm.trunc %arg2 : i64 to i32 + %4 = llvm.sext %3 : i32 to i64 + %5 = llvm.srem %2, %4 : i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i1 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.and %0, %0 : i64 + %2 = llvm.sext %arg1 : i32 to i64 + %3 = llvm.udiv %1, %2 : i64 + %4 = llvm.urem %arg2, %3 : i64 + %5 = llvm.xor %3, %4 : i64 + %6 = llvm.icmp "uge" %arg0, %5 : i64 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.select %arg1, %arg0, %arg2 : i1, i64 + %1 = llvm.icmp "ugt" %arg0, %0 : i64 + %2 = llvm.sext %1 : i1 to i64 + %3 = llvm.lshr %0, %2 : i64 + %4 = llvm.sdiv %arg0, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + %6 = llvm.sext %5 : i32 to i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.srem %arg0, %arg1 : i64 + %1 = llvm.and %arg0, %arg1 : i64 + %2 = llvm.udiv %0, %1 : i64 + %3 = llvm.udiv %2, %0 : i64 + %4 = llvm.trunc %3 : i64 to i32 + %5 = llvm.sext %4 : i32 to i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { + %0 = llvm.select %arg2, %arg0, %arg1 : i1, i64 + %1 = llvm.lshr %arg0, %0 : i64 + %2 = llvm.icmp "ugt" %arg1, %1 : i64 + %3 = llvm.or %1, %arg0 : i64 + %4 = llvm.select %2, %3, %0 : i1, i64 + %5 = llvm.and %arg0, %4 : i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i1) -> i1 { + %0 = llvm.select %arg2, %arg0, %arg0 : i1, i64 + %1 = llvm.urem %arg0, %0 : i64 + %2 = llvm.urem %1, %arg0 : i64 + %3 = llvm.or %0, %2 : i64 + %4 = llvm.select %arg1, %3, %arg0 : i1, i64 + %5 = llvm.or %arg0, %4 : i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.select %0, %arg0, %arg0 : i1, i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + %4 = llvm.srem %3, %3 : i64 + %5 = llvm.lshr %4, %arg0 : i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.select %1, %arg1, %0 : i1, i64 + %3 = llvm.ashr %2, %arg2 : i64 + %4 = llvm.icmp "slt" %2, %0 : i64 + %5 = llvm.select %4, %arg0, %0 : i1, i64 + %6 = llvm.urem %3, %5 : i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.icmp "ugt" %arg0, %arg1 : i64 + %1 = llvm.zext %0 : i1 to i64 + %2 = llvm.ashr %1, %arg0 : i64 + %3 = llvm.sdiv %arg2, %arg0 : i64 + %4 = llvm.sdiv %3, %arg1 : i64 + %5 = llvm.lshr %2, %4 : i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.xor %arg0, %arg0 : i64 + %1 = llvm.urem %0, %arg1 : i64 + %2 = llvm.and %1, %arg2 : i64 + %3 = llvm.or %2, %arg2 : i64 + %4 = llvm.srem %3, %arg0 : i64 + %5 = llvm.sdiv %arg2, %4 : i64 + %6 = llvm.icmp "eq" %1, %5 : i64 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i32) -> i32 { + %0 = llvm.ashr %arg0, %arg0 : i64 + %1 = llvm.lshr %0, %arg1 : i64 + %2 = llvm.sdiv %arg2, %arg0 : i64 + %3 = llvm.sext %arg3 : i32 to i64 + %4 = llvm.lshr %2, %3 : i64 + %5 = llvm.lshr %1, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i32, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.sext %arg0 : i32 to i64 + %1 = llvm.trunc %arg1 : i64 to i1 + %2 = llvm.sext %1 : i1 to i64 + %3 = llvm.icmp "uge" %0, %2 : i64 + %4 = llvm.zext %3 : i1 to i64 + %5 = llvm.ashr %4, %arg2 : i64 + %6 = llvm.xor %5, %arg1 : i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.icmp "ugt" %arg0, %arg0 : i64 + %1 = llvm.srem %arg0, %arg0 : i64 + %2 = llvm.xor %1, %1 : i64 + %3 = llvm.trunc %arg1 : i64 to i1 + %4 = llvm.sext %3 : i1 to i64 + %5 = llvm.select %0, %2, %4 : i1, i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i1 { + %0 = llvm.ashr %arg0, %arg1 : i64 + %1 = llvm.zext %arg3 : i1 to i64 + %2 = llvm.lshr %arg1, %1 : i64 + %3 = llvm.trunc %2 : i64 to i1 + %4 = llvm.select %3, %1, %arg0 : i1, i64 + %5 = llvm.and %arg2, %4 : i64 + %6 = llvm.icmp "slt" %0, %5 : i64 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i32, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.sext %arg0 : i32 to i64 + %1 = llvm.sext %arg1 : i1 to i64 + %2 = llvm.sdiv %1, %arg2 : i64 + %3 = llvm.ashr %0, %2 : i64 + %4 = llvm.lshr %3, %arg2 : i64 + %5 = llvm.and %3, %4 : i64 + %6 = llvm.and %3, %5 : i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i64 { + %0 = llvm.urem %arg1, %arg1 : i64 + %1 = llvm.ashr %arg0, %0 : i64 + %2 = llvm.srem %arg2, %1 : i64 + %3 = llvm.and %1, %2 : i64 + %4 = llvm.sext %arg3 : i1 to i64 + %5 = llvm.lshr %1, %4 : i64 + %6 = llvm.xor %3, %5 : i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.urem %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.sext %1 : i32 to i64 + %3 = llvm.zext %1 : i32 to i64 + %4 = llvm.udiv %2, %3 : i64 + %5 = llvm.srem %4, %3 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64) -> i32 { + %0 = llvm.sext %arg0 : i1 to i64 + %1 = llvm.udiv %0, %0 : i64 + %2 = llvm.xor %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + %4 = llvm.zext %3 : i32 to i64 + %5 = llvm.lshr %4, %arg1 : i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i1 { + %0 = llvm.or %arg0, %arg0 : i64 + %1 = llvm.srem %0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + %4 = llvm.trunc %3 : i64 to i32 + %5 = llvm.zext %4 : i32 to i64 + %6 = llvm.icmp "ule" %0, %5 : i64 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.udiv %arg0, %1 : i64 + %3 = llvm.icmp "ugt" %arg1, %arg2 : i64 + %4 = llvm.select %3, %arg2, %2 : i1, i64 + %5 = llvm.and %2, %4 : i64 + %6 = llvm.trunc %5 : i64 to i1 + return %6 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.zext %0 : i1 to i64 + %2 = llvm.and %1, %1 : i64 + %3 = llvm.udiv %2, %2 : i64 + %4 = llvm.trunc %3 : i64 to i1 + %5 = llvm.zext %4 : i1 to i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i64 { + %0 = llvm.or %arg0, %arg1 : i64 + %1 = llvm.sext %arg2 : i1 to i64 + %2 = llvm.and %0, %1 : i64 + %3 = llvm.icmp "eq" %1, %2 : i64 + %4 = llvm.xor %arg0, %1 : i64 + %5 = llvm.select %3, %2, %4 : i1, i64 + %6 = llvm.ashr %0, %5 : i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.and %arg0, %arg0 : i64 + %1 = llvm.or %0, %arg1 : i64 + %2 = llvm.ashr %arg0, %arg2 : i64 + %3 = llvm.sdiv %2, %arg1 : i64 + %4 = llvm.urem %1, %0 : i64 + %5 = llvm.sdiv %3, %4 : i64 + %6 = llvm.urem %1, %5 : i64 + return %6 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.xor %arg0, %arg2 : i64 + %1 = llvm.lshr %arg1, %0 : i64 + %2 = llvm.xor %1, %arg0 : i64 + %3 = llvm.urem %arg0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + %5 = llvm.sext %4 : i32 to i64 + %6 = llvm.trunc %5 : i64 to i32 + return %6 : i32 + } +} +// ----- diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_8.mlir b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_8.mlir new file mode 100644 index 0000000000..0fdbac9802 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/output_8.mlir @@ -0,0 +1,1400 @@ +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i1 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.lshr %0, %arg1 : i64 + %2 = llvm.and %1, %arg2 : i64 + %3 = llvm.urem %arg0, %0 : i64 + %4 = llvm.select %arg3, %3, %2 : i1, i64 + %5 = llvm.and %2, %4 : i64 + %6 = llvm.or %2, %5 : i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.sdiv %arg0, %arg1 : i64 + %1 = llvm.udiv %0, %arg2 : i64 + %2 = llvm.and %arg0, %1 : i64 + %3 = llvm.udiv %0, %2 : i64 + %4 = llvm.ashr %arg1, %arg0 : i64 + %5 = llvm.xor %3, %4 : i64 + %6 = llvm.udiv %5, %arg0 : i64 + %7 = llvm.icmp "ule" %2, %6 : i64 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64) -> i32 { + %0 = llvm.sext %arg0 : i1 to i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.sext %1 : i32 to i64 + %3 = llvm.srem %0, %arg1 : i64 + %4 = llvm.trunc %3 : i64 to i32 + %5 = llvm.sext %4 : i32 to i64 + %6 = llvm.or %2, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { + %0 = llvm.select %arg1, %arg2, %arg2 : i1, i64 + %1 = llvm.udiv %arg0, %0 : i64 + %2 = llvm.srem %1, %0 : i64 + %3 = llvm.urem %arg0, %2 : i64 + %4 = llvm.and %arg2, %3 : i64 + %5 = llvm.or %4, %3 : i64 + %6 = llvm.or %3, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { + %0 = llvm.select %arg0, %arg1, %arg2 : i1, i64 + %1 = llvm.sext %arg3 : i32 to i64 + %2 = llvm.select %arg0, %arg1, %1 : i1, i64 + %3 = llvm.lshr %1, %2 : i64 + %4 = llvm.lshr %0, %3 : i64 + %5 = llvm.select %arg0, %arg1, %4 : i1, i64 + %6 = llvm.urem %4, %5 : i64 + %7 = llvm.icmp "sgt" %4, %6 : i64 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i32 { + %0 = llvm.sdiv %arg0, %arg0 : i64 + %1 = llvm.or %arg1, %arg0 : i64 + %2 = llvm.select %arg3, %arg2, %0 : i1, i64 + %3 = llvm.ashr %arg2, %2 : i64 + %4 = llvm.sdiv %1, %3 : i64 + %5 = llvm.and %0, %4 : i64 + %6 = llvm.ashr %5, %0 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i32, %arg2: i64) -> i1 { + %0 = llvm.sext %arg0 : i1 to i64 + %1 = llvm.sext %arg1 : i32 to i64 + %2 = llvm.or %arg2, %0 : i64 + %3 = llvm.sdiv %2, %0 : i64 + %4 = llvm.srem %3, %2 : i64 + %5 = llvm.and %1, %4 : i64 + %6 = llvm.sdiv %0, %5 : i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64, %arg3: i32) -> i32 { + %0 = llvm.sext %arg3 : i32 to i64 + %1 = llvm.lshr %arg2, %0 : i64 + %2 = llvm.icmp "sge" %1, %arg0 : i64 + %3 = llvm.sext %2 : i1 to i64 + %4 = llvm.select %arg1, %1, %3 : i1, i64 + %5 = llvm.and %4, %4 : i64 + %6 = llvm.udiv %arg0, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { + %0 = llvm.sext %arg1 : i1 to i64 + %1 = llvm.and %0, %arg0 : i64 + %2 = llvm.ashr %1, %arg2 : i64 + %3 = llvm.sdiv %2, %arg2 : i64 + %4 = llvm.udiv %arg0, %3 : i64 + %5 = llvm.trunc %4 : i64 to i1 + %6 = llvm.sext %5 : i1 to i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.xor %arg0, %arg1 : i64 + %1 = llvm.xor %0, %0 : i64 + %2 = llvm.ashr %arg0, %arg1 : i64 + %3 = llvm.udiv %arg2, %1 : i64 + %4 = llvm.sdiv %2, %3 : i64 + %5 = llvm.or %1, %4 : i64 + %6 = llvm.srem %5, %4 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.xor %arg1, %arg2 : i64 + %2 = llvm.xor %0, %1 : i64 + %3 = llvm.lshr %arg1, %2 : i64 + %4 = llvm.srem %3, %2 : i64 + %5 = llvm.and %0, %4 : i64 + %6 = llvm.or %5, %0 : i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i1, %arg2: i64) -> i1 { + %0 = llvm.zext %arg0 : i1 to i64 + %1 = llvm.select %arg1, %0, %0 : i1, i64 + %2 = llvm.lshr %1, %arg2 : i64 + %3 = llvm.icmp "sge" %0, %2 : i64 + %4 = llvm.sext %3 : i1 to i64 + %5 = llvm.trunc %2 : i64 to i1 + %6 = llvm.sext %5 : i1 to i64 + %7 = llvm.icmp "sgt" %4, %6 : i64 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.ashr %arg2, %arg0 : i64 + %1 = llvm.or %arg1, %0 : i64 + %2 = llvm.trunc %1 : i64 to i1 + %3 = llvm.select %2, %1, %1 : i1, i64 + %4 = llvm.sdiv %3, %1 : i64 + %5 = llvm.select %2, %1, %0 : i1, i64 + %6 = llvm.select %2, %4, %5 : i1, i64 + %7 = llvm.icmp "uge" %arg0, %6 : i64 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i32 { + %0 = llvm.zext %arg2 : i1 to i64 + %1 = llvm.or %arg1, %0 : i64 + %2 = llvm.urem %arg1, %1 : i64 + %3 = llvm.urem %2, %arg1 : i64 + %4 = llvm.srem %arg1, %3 : i64 + %5 = llvm.sdiv %arg0, %4 : i64 + %6 = llvm.ashr %5, %0 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.sext %0 : i32 to i64 + %2 = llvm.udiv %arg2, %1 : i64 + %3 = llvm.xor %arg2, %2 : i64 + %4 = llvm.sdiv %3, %arg2 : i64 + %5 = llvm.select %arg1, %2, %4 : i1, i64 + %6 = llvm.lshr %arg0, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { + %0 = llvm.and %arg0, %arg0 : i64 + %1 = llvm.udiv %arg2, %arg2 : i64 + %2 = llvm.srem %arg2, %1 : i64 + %3 = llvm.lshr %arg1, %2 : i64 + %4 = llvm.zext %arg3 : i32 to i64 + %5 = llvm.sdiv %3, %4 : i64 + %6 = llvm.udiv %0, %5 : i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.sext %0 : i1 to i64 + %2 = llvm.srem %1, %arg1 : i64 + %3 = llvm.urem %1, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + %5 = llvm.zext %4 : i32 to i64 + %6 = llvm.udiv %5, %1 : i64 + %7 = llvm.urem %6, %arg2 : i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.trunc %arg1 : i64 to i1 + %1 = llvm.zext %0 : i1 to i64 + %2 = llvm.sdiv %1, %arg2 : i64 + %3 = llvm.urem %arg0, %2 : i64 + %4 = llvm.udiv %arg1, %arg1 : i64 + %5 = llvm.icmp "slt" %3, %4 : i64 + %6 = llvm.lshr %arg2, %4 : i64 + %7 = llvm.select %5, %6, %1 : i1, i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i64 { + %0 = llvm.udiv %arg2, %arg2 : i64 + %1 = llvm.or %0, %0 : i64 + %2 = llvm.xor %1, %arg0 : i64 + %3 = llvm.xor %arg1, %2 : i64 + %4 = llvm.sdiv %arg0, %3 : i64 + %5 = llvm.zext %arg3 : i1 to i64 + %6 = llvm.or %4, %5 : i64 + %7 = llvm.ashr %arg0, %6 : i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.urem %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.select %1, %arg0, %0 : i1, i64 + %3 = llvm.udiv %0, %arg0 : i64 + %4 = llvm.or %2, %3 : i64 + %5 = llvm.or %arg1, %arg2 : i64 + %6 = llvm.and %4, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.zext %0 : i32 to i64 + %2 = llvm.ashr %1, %1 : i64 + %3 = llvm.srem %2, %arg1 : i64 + %4 = llvm.ashr %1, %3 : i64 + %5 = llvm.urem %4, %2 : i64 + %6 = llvm.sdiv %1, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.srem %arg0, %arg1 : i64 + %1 = llvm.ashr %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.zext %2 : i32 to i64 + %4 = llvm.trunc %3 : i64 to i32 + %5 = llvm.sext %4 : i32 to i64 + %6 = llvm.and %5, %arg2 : i64 + %7 = llvm.icmp "ne" %3, %6 : i64 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64, %arg3: i32) -> i64 { + %0 = llvm.urem %arg0, %arg0 : i64 + %1 = llvm.select %arg1, %0, %arg2 : i1, i64 + %2 = llvm.icmp "ugt" %0, %1 : i64 + %3 = llvm.trunc %arg2 : i64 to i1 + %4 = llvm.sext %arg3 : i32 to i64 + %5 = llvm.lshr %arg2, %0 : i64 + %6 = llvm.select %3, %4, %5 : i1, i64 + %7 = llvm.select %2, %arg0, %6 : i1, i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.icmp "sle" %arg0, %arg0 : i64 + %1 = llvm.zext %0 : i1 to i64 + %2 = llvm.urem %arg1, %arg2 : i64 + %3 = llvm.icmp "ne" %1, %2 : i64 + %4 = llvm.srem %arg2, %arg0 : i64 + %5 = llvm.sdiv %4, %arg0 : i64 + %6 = llvm.select %3, %arg1, %5 : i1, i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.sdiv %arg0, %arg1 : i64 + %1 = llvm.and %arg2, %arg0 : i64 + %2 = llvm.udiv %arg2, %1 : i64 + %3 = llvm.udiv %0, %2 : i64 + %4 = llvm.srem %3, %arg0 : i64 + %5 = llvm.srem %4, %arg0 : i64 + %6 = llvm.sdiv %3, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64) -> i1 { + %0 = llvm.zext %arg0 : i1 to i64 + %1 = llvm.icmp "ule" %0, %0 : i64 + %2 = llvm.zext %1 : i1 to i64 + %3 = llvm.sdiv %0, %arg1 : i64 + %4 = llvm.lshr %0, %3 : i64 + %5 = llvm.sdiv %arg1, %4 : i64 + %6 = llvm.lshr %2, %5 : i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.and %arg0, %arg0 : i64 + %1 = llvm.select %arg1, %arg2, %arg0 : i1, i64 + %2 = llvm.urem %0, %1 : i64 + %3 = llvm.or %1, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + %5 = llvm.zext %4 : i32 to i64 + %6 = llvm.and %2, %5 : i64 + %7 = llvm.ashr %6, %5 : i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.icmp "slt" %arg0, %arg1 : i64 + %1 = llvm.zext %0 : i1 to i64 + %2 = llvm.and %arg1, %1 : i64 + %3 = llvm.xor %arg0, %2 : i64 + %4 = llvm.icmp "sge" %arg2, %3 : i64 + %5 = llvm.srem %1, %arg0 : i64 + %6 = llvm.select %4, %arg1, %5 : i1, i64 + %7 = llvm.lshr %3, %6 : i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.xor %arg0, %arg1 : i64 + %1 = llvm.udiv %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.sext %2 : i32 to i64 + %4 = llvm.srem %arg2, %arg2 : i64 + %5 = llvm.or %3, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + %7 = llvm.sext %6 : i32 to i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.and %0, %0 : i64 + %2 = llvm.srem %arg2, %arg2 : i64 + %3 = llvm.select %arg1, %arg2, %2 : i1, i64 + %4 = llvm.urem %1, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + %6 = llvm.sext %5 : i32 to i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i32, %arg2: i64) -> i1 { + %0 = llvm.sext %arg1 : i32 to i64 + %1 = llvm.select %arg0, %0, %arg2 : i1, i64 + %2 = llvm.ashr %1, %1 : i64 + %3 = llvm.sext %arg0 : i1 to i64 + %4 = llvm.sdiv %3, %3 : i64 + %5 = llvm.or %4, %1 : i64 + %6 = llvm.ashr %2, %5 : i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i32 { + %0 = llvm.sext %arg1 : i32 to i64 + %1 = llvm.xor %0, %arg0 : i64 + %2 = llvm.or %arg0, %1 : i64 + %3 = llvm.sdiv %2, %1 : i64 + %4 = llvm.trunc %3 : i64 to i32 + %5 = llvm.zext %4 : i32 to i64 + %6 = llvm.sdiv %5, %arg2 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.urem %arg0, %arg0 : i64 + %1 = llvm.select %arg1, %arg2, %0 : i1, i64 + %2 = llvm.sdiv %1, %0 : i64 + %3 = llvm.and %2, %arg0 : i64 + %4 = llvm.trunc %3 : i64 to i32 + %5 = llvm.zext %4 : i32 to i64 + %6 = llvm.sdiv %5, %5 : i64 + %7 = llvm.udiv %0, %6 : i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.select %arg0, %arg1, %arg2 : i1, i64 + %1 = llvm.sext %arg0 : i1 to i64 + %2 = llvm.udiv %0, %1 : i64 + %3 = llvm.lshr %2, %1 : i64 + %4 = llvm.trunc %arg1 : i64 to i1 + %5 = llvm.sext %4 : i1 to i64 + %6 = llvm.ashr %3, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.sext %arg0 : i1 to i64 + %1 = llvm.udiv %arg1, %arg2 : i64 + %2 = llvm.icmp "ne" %0, %1 : i64 + %3 = llvm.sext %2 : i1 to i64 + %4 = llvm.ashr %0, %3 : i64 + %5 = llvm.udiv %arg2, %4 : i64 + %6 = llvm.udiv %4, %5 : i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i1 { + %0 = llvm.srem %arg0, %arg1 : i64 + %1 = llvm.or %arg2, %arg1 : i64 + %2 = llvm.zext %arg3 : i1 to i64 + %3 = llvm.lshr %1, %2 : i64 + %4 = llvm.icmp "ult" %0, %3 : i64 + %5 = llvm.zext %4 : i1 to i64 + %6 = llvm.urem %arg0, %2 : i64 + %7 = llvm.icmp "ult" %5, %6 : i64 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.icmp "ule" %arg0, %arg0 : i64 + %1 = llvm.zext %0 : i1 to i64 + %2 = llvm.xor %arg1, %1 : i64 + %3 = llvm.srem %arg2, %arg0 : i64 + %4 = llvm.urem %2, %3 : i64 + %5 = llvm.lshr %4, %1 : i64 + %6 = llvm.udiv %1, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { + %0 = llvm.and %arg0, %arg1 : i64 + %1 = llvm.zext %arg2 : i1 to i64 + %2 = llvm.srem %0, %1 : i64 + %3 = llvm.sdiv %arg0, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + %5 = llvm.zext %4 : i32 to i64 + %6 = llvm.and %arg0, %5 : i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i1 + %1 = llvm.select %0, %arg0, %arg0 : i1, i64 + %2 = llvm.icmp "sgt" %1, %1 : i64 + %3 = llvm.or %arg1, %arg0 : i64 + %4 = llvm.ashr %3, %1 : i64 + %5 = llvm.srem %1, %4 : i64 + %6 = llvm.select %2, %3, %5 : i1, i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i1 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.zext %0 : i32 to i64 + %2 = llvm.or %1, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + %4 = llvm.zext %3 : i32 to i64 + %5 = llvm.ashr %1, %4 : i64 + %6 = llvm.and %2, %5 : i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64) -> i1 { + %0 = llvm.sdiv %arg0, %arg0 : i64 + %1 = llvm.xor %0, %0 : i64 + %2 = llvm.srem %0, %1 : i64 + %3 = llvm.udiv %arg0, %2 : i64 + %4 = llvm.or %3, %arg0 : i64 + %5 = llvm.trunc %4 : i64 to i1 + %6 = llvm.sext %5 : i1 to i64 + %7 = llvm.icmp "ult" %6, %0 : i64 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i32 { + %0 = llvm.ashr %arg0, %arg1 : i64 + %1 = llvm.lshr %arg0, %0 : i64 + %2 = llvm.select %arg2, %arg1, %arg0 : i1, i64 + %3 = llvm.icmp "eq" %1, %2 : i64 + %4 = llvm.sext %3 : i1 to i64 + %5 = llvm.icmp "sle" %arg0, %4 : i64 + %6 = llvm.sext %5 : i1 to i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.select %arg0, %arg1, %arg2 : i1, i64 + %1 = llvm.and %0, %arg1 : i64 + %2 = llvm.ashr %1, %0 : i64 + %3 = llvm.trunc %2 : i64 to i1 + %4 = llvm.trunc %arg1 : i64 to i32 + %5 = llvm.zext %4 : i32 to i64 + %6 = llvm.select %3, %5, %5 : i1, i64 + %7 = llvm.srem %1, %6 : i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.ashr %arg1, %arg2 : i64 + %1 = llvm.sdiv %0, %0 : i64 + %2 = llvm.sdiv %1, %0 : i64 + %3 = llvm.and %1, %1 : i64 + %4 = llvm.or %0, %3 : i64 + %5 = llvm.sdiv %2, %4 : i64 + %6 = llvm.select %arg0, %0, %5 : i1, i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) -> i32 { + %0 = llvm.udiv %arg0, %arg2 : i64 + %1 = llvm.select %arg3, %arg0, %arg1 : i1, i64 + %2 = llvm.udiv %0, %1 : i64 + %3 = llvm.udiv %0, %2 : i64 + %4 = llvm.xor %3, %2 : i64 + %5 = llvm.xor %arg1, %4 : i64 + %6 = llvm.lshr %arg0, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i1 { + %0 = llvm.and %arg0, %arg0 : i64 + %1 = llvm.srem %0, %arg0 : i64 + %2 = llvm.trunc %1 : i64 to i1 + %3 = llvm.or %arg1, %arg0 : i64 + %4 = llvm.select %arg2, %arg0, %3 : i1, i64 + %5 = llvm.select %2, %3, %4 : i1, i64 + %6 = llvm.and %1, %3 : i64 + %7 = llvm.icmp "ne" %5, %6 : i64 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { + %0 = llvm.urem %arg1, %arg2 : i64 + %1 = llvm.ashr %arg0, %0 : i64 + %2 = llvm.sext %arg3 : i32 to i64 + %3 = llvm.ashr %arg1, %0 : i64 + %4 = llvm.xor %2, %3 : i64 + %5 = llvm.xor %1, %4 : i64 + %6 = llvm.and %arg0, %5 : i64 + %7 = llvm.icmp "slt" %6, %1 : i64 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i1 { + %0 = llvm.sext %arg1 : i32 to i64 + %1 = llvm.and %arg0, %0 : i64 + %2 = llvm.sdiv %1, %1 : i64 + %3 = llvm.and %arg0, %2 : i64 + %4 = llvm.srem %arg2, %2 : i64 + %5 = llvm.ashr %1, %4 : i64 + %6 = llvm.srem %3, %5 : i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.udiv %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.sext %1 : i32 to i64 + %3 = llvm.icmp "sgt" %arg0, %0 : i64 + %4 = llvm.sext %3 : i1 to i64 + %5 = llvm.xor %2, %2 : i64 + %6 = llvm.urem %4, %5 : i64 + %7 = llvm.ashr %2, %6 : i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.xor %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.sext %1 : i32 to i64 + %3 = llvm.ashr %arg0, %arg1 : i64 + %4 = llvm.icmp "uge" %2, %3 : i64 + %5 = llvm.and %arg2, %3 : i64 + %6 = llvm.select %4, %5, %arg2 : i1, i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.lshr %arg1, %arg2 : i64 + %1 = llvm.urem %0, %arg0 : i64 + %2 = llvm.ashr %arg1, %1 : i64 + %3 = llvm.udiv %1, %2 : i64 + %4 = llvm.trunc %3 : i64 to i1 + %5 = llvm.select %4, %3, %2 : i1, i64 + %6 = llvm.ashr %arg0, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.srem %arg2, %arg1 : i64 + %1 = llvm.srem %arg1, %0 : i64 + %2 = llvm.lshr %0, %arg0 : i64 + %3 = llvm.or %1, %2 : i64 + %4 = llvm.xor %2, %2 : i64 + %5 = llvm.urem %3, %4 : i64 + %6 = llvm.udiv %arg0, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.udiv %arg0, %arg0 : i64 + %1 = llvm.and %arg0, %0 : i64 + %2 = llvm.sdiv %arg1, %arg2 : i64 + %3 = llvm.lshr %1, %2 : i64 + %4 = llvm.srem %3, %arg2 : i64 + %5 = llvm.trunc %4 : i64 to i32 + %6 = llvm.zext %5 : i32 to i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i32 { + %0 = llvm.xor %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.zext %1 : i32 to i64 + %3 = llvm.sext %arg2 : i1 to i64 + %4 = llvm.or %2, %3 : i64 + %5 = llvm.srem %2, %4 : i64 + %6 = llvm.udiv %2, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.urem %arg0, %arg0 : i64 + %1 = llvm.xor %arg0, %0 : i64 + %2 = llvm.icmp "uge" %1, %1 : i64 + %3 = llvm.trunc %arg1 : i64 to i1 + %4 = llvm.sdiv %arg2, %arg1 : i64 + %5 = llvm.select %3, %4, %arg2 : i1, i64 + %6 = llvm.select %2, %0, %5 : i1, i64 + %7 = llvm.icmp "ule" %6, %arg2 : i64 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.ashr %arg0, %arg1 : i64 + %1 = llvm.lshr %arg0, %0 : i64 + %2 = llvm.and %arg2, %1 : i64 + %3 = llvm.urem %1, %2 : i64 + %4 = llvm.trunc %arg1 : i64 to i1 + %5 = llvm.zext %4 : i1 to i64 + %6 = llvm.sdiv %3, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.select %arg1, %arg0, %arg2 : i1, i64 + %1 = llvm.urem %0, %0 : i64 + %2 = llvm.sdiv %arg0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i1 + %4 = llvm.and %0, %1 : i64 + %5 = llvm.xor %1, %1 : i64 + %6 = llvm.srem %5, %4 : i64 + %7 = llvm.select %3, %4, %6 : i1, i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i32, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.sext %arg0 : i32 to i64 + %1 = llvm.urem %arg1, %arg1 : i64 + %2 = llvm.or %arg1, %1 : i64 + %3 = llvm.icmp "ugt" %2, %0 : i64 + %4 = llvm.sext %3 : i1 to i64 + %5 = llvm.sdiv %0, %4 : i64 + %6 = llvm.srem %arg2, %1 : i64 + %7 = llvm.and %5, %6 : i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64, %arg3: i32) -> i1 { + %0 = llvm.sext %arg3 : i32 to i64 + %1 = llvm.select %arg1, %arg2, %0 : i1, i64 + %2 = llvm.udiv %arg0, %1 : i64 + %3 = llvm.ashr %2, %arg2 : i64 + %4 = llvm.and %1, %3 : i64 + %5 = llvm.icmp "slt" %4, %arg0 : i64 + %6 = llvm.sext %5 : i1 to i64 + %7 = llvm.icmp "sgt" %arg0, %6 : i64 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i1 { + %0 = llvm.sext %arg1 : i32 to i64 + %1 = llvm.xor %arg0, %0 : i64 + %2 = llvm.or %1, %arg2 : i64 + %3 = llvm.or %2, %arg0 : i64 + %4 = llvm.trunc %3 : i64 to i1 + %5 = llvm.sext %4 : i1 to i64 + %6 = llvm.ashr %arg2, %5 : i64 + %7 = llvm.icmp "uge" %1, %6 : i64 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i1 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.sext %arg1 : i32 to i64 + %2 = llvm.xor %1, %arg0 : i64 + %3 = llvm.icmp "ne" %1, %2 : i64 + %4 = llvm.xor %arg0, %arg2 : i64 + %5 = llvm.select %3, %2, %4 : i1, i64 + %6 = llvm.or %0, %5 : i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.sext %arg0 : i1 to i64 + %1 = llvm.select %arg0, %arg1, %arg1 : i1, i64 + %2 = llvm.icmp "ne" %arg2, %1 : i64 + %3 = llvm.sext %2 : i1 to i64 + %4 = llvm.trunc %3 : i64 to i32 + %5 = llvm.sext %4 : i32 to i64 + %6 = llvm.lshr %arg1, %5 : i64 + %7 = llvm.urem %0, %6 : i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i32 { + %0 = llvm.zext %arg1 : i32 to i64 + %1 = llvm.urem %arg2, %0 : i64 + %2 = llvm.or %0, %1 : i64 + %3 = llvm.or %1, %1 : i64 + %4 = llvm.urem %1, %3 : i64 + %5 = llvm.xor %2, %4 : i64 + %6 = llvm.lshr %arg0, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.icmp "ule" %arg2, %arg2 : i64 + %1 = llvm.zext %0 : i1 to i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.zext %2 : i32 to i64 + %4 = llvm.and %arg1, %3 : i64 + %5 = llvm.sdiv %arg0, %4 : i64 + %6 = llvm.xor %arg2, %1 : i64 + %7 = llvm.sdiv %5, %6 : i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.xor %arg0, %arg0 : i64 + %1 = llvm.and %arg2, %arg0 : i64 + %2 = llvm.lshr %arg1, %1 : i64 + %3 = llvm.trunc %2 : i64 to i32 + %4 = llvm.sext %3 : i32 to i64 + %5 = llvm.sdiv %0, %4 : i64 + %6 = llvm.urem %5, %5 : i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64) -> i1 { + %0 = llvm.zext %arg0 : i1 to i64 + %1 = llvm.sext %arg0 : i1 to i64 + %2 = llvm.srem %1, %1 : i64 + %3 = llvm.srem %0, %2 : i64 + %4 = llvm.urem %arg1, %3 : i64 + %5 = llvm.udiv %0, %4 : i64 + %6 = llvm.xor %0, %5 : i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.and %0, %arg0 : i64 + %2 = llvm.urem %1, %arg2 : i64 + %3 = llvm.or %arg1, %2 : i64 + %4 = llvm.icmp "ule" %0, %3 : i64 + %5 = llvm.zext %4 : i1 to i64 + %6 = llvm.srem %1, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.ashr %arg1, %arg2 : i64 + %1 = llvm.or %arg0, %0 : i64 + %2 = llvm.trunc %arg1 : i64 to i1 + %3 = llvm.zext %2 : i1 to i64 + %4 = llvm.icmp "slt" %1, %3 : i64 + %5 = llvm.select %4, %0, %arg2 : i1, i64 + %6 = llvm.trunc %5 : i64 to i32 + %7 = llvm.sext %6 : i32 to i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { + %0 = llvm.zext %arg1 : i1 to i64 + %1 = llvm.trunc %arg2 : i64 to i1 + %2 = llvm.sext %1 : i1 to i64 + %3 = llvm.and %0, %2 : i64 + %4 = llvm.udiv %arg0, %3 : i64 + %5 = llvm.udiv %4, %0 : i64 + %6 = llvm.and %5, %4 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { + %0 = llvm.select %arg1, %arg0, %arg2 : i1, i64 + %1 = llvm.srem %arg0, %0 : i64 + %2 = llvm.xor %arg0, %1 : i64 + %3 = llvm.xor %0, %0 : i64 + %4 = llvm.or %2, %3 : i64 + %5 = llvm.trunc %4 : i64 to i1 + %6 = llvm.zext %5 : i1 to i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.udiv %0, %arg1 : i64 + %2 = llvm.lshr %0, %1 : i64 + %3 = llvm.icmp "ult" %0, %arg0 : i64 + %4 = llvm.sext %3 : i1 to i64 + %5 = llvm.udiv %2, %4 : i64 + %6 = llvm.or %arg0, %5 : i64 + %7 = llvm.icmp "sgt" %6, %0 : i64 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.or %arg1, %arg1 : i64 + %1 = llvm.sdiv %arg1, %arg2 : i64 + %2 = llvm.icmp "ne" %arg2, %1 : i64 + %3 = llvm.zext %2 : i1 to i64 + %4 = llvm.and %arg2, %1 : i64 + %5 = llvm.urem %3, %4 : i64 + %6 = llvm.sdiv %0, %5 : i64 + %7 = llvm.icmp "ugt" %arg0, %6 : i64 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.udiv %arg0, %arg1 : i64 + %1 = llvm.lshr %arg1, %arg0 : i64 + %2 = llvm.sdiv %0, %1 : i64 + %3 = llvm.sdiv %arg2, %arg0 : i64 + %4 = llvm.ashr %arg2, %3 : i64 + %5 = llvm.and %arg1, %4 : i64 + %6 = llvm.udiv %2, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.select %arg0, %arg1, %arg2 : i1, i64 + %1 = llvm.icmp "ugt" %0, %arg1 : i64 + %2 = llvm.sext %1 : i1 to i64 + %3 = llvm.urem %0, %2 : i64 + %4 = llvm.and %3, %arg2 : i64 + %5 = llvm.udiv %2, %4 : i64 + %6 = llvm.udiv %3, %5 : i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.trunc %arg0 : i64 to i32 + %1 = llvm.sext %0 : i32 to i64 + %2 = llvm.lshr %arg1, %1 : i64 + %3 = llvm.ashr %2, %arg1 : i64 + %4 = llvm.or %1, %3 : i64 + %5 = llvm.trunc %1 : i64 to i32 + %6 = llvm.sext %5 : i32 to i64 + %7 = llvm.xor %4, %6 : i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.lshr %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i1 + %2 = llvm.select %1, %arg2, %arg2 : i1, i64 + %3 = llvm.srem %0, %arg1 : i64 + %4 = llvm.xor %2, %3 : i64 + %5 = llvm.and %4, %arg1 : i64 + %6 = llvm.ashr %arg2, %arg0 : i64 + %7 = llvm.icmp "sge" %5, %6 : i64 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i1) -> i64 { + %0 = llvm.or %arg0, %arg1 : i64 + %1 = llvm.sdiv %arg1, %arg0 : i64 + %2 = llvm.zext %arg2 : i1 to i64 + %3 = llvm.urem %arg1, %2 : i64 + %4 = llvm.and %2, %3 : i64 + %5 = llvm.srem %1, %4 : i64 + %6 = llvm.udiv %0, %5 : i64 + %7 = llvm.sdiv %arg0, %6 : i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.icmp "ne" %arg0, %arg1 : i64 + %1 = llvm.select %0, %arg2, %arg2 : i1, i64 + %2 = llvm.srem %arg1, %arg0 : i64 + %3 = llvm.ashr %arg1, %2 : i64 + %4 = llvm.sdiv %3, %1 : i64 + %5 = llvm.xor %1, %4 : i64 + %6 = llvm.or %5, %4 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.ashr %arg1, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.sext %1 : i32 to i64 + %3 = llvm.trunc %2 : i64 to i1 + %4 = llvm.sext %3 : i1 to i64 + %5 = llvm.trunc %4 : i64 to i32 + %6 = llvm.sext %5 : i32 to i64 + %7 = llvm.ashr %arg0, %6 : i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.or %arg0, %arg1 : i64 + %1 = llvm.and %0, %arg2 : i64 + %2 = llvm.sdiv %1, %1 : i64 + %3 = llvm.lshr %2, %arg2 : i64 + %4 = llvm.srem %arg1, %3 : i64 + %5 = llvm.urem %2, %4 : i64 + %6 = llvm.or %5, %arg1 : i64 + %7 = llvm.srem %6, %6 : i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i64 { + %0 = llvm.select %arg1, %arg2, %arg0 : i1, i64 + %1 = llvm.sdiv %arg0, %0 : i64 + %2 = llvm.sdiv %1, %1 : i64 + %3 = llvm.and %2, %2 : i64 + %4 = llvm.trunc %3 : i64 to i1 + %5 = llvm.or %0, %0 : i64 + %6 = llvm.xor %3, %5 : i64 + %7 = llvm.select %4, %1, %6 : i1, i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32) -> i32 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.zext %arg1 : i32 to i64 + %2 = llvm.trunc %1 : i64 to i1 + %3 = llvm.zext %2 : i1 to i64 + %4 = llvm.zext %2 : i1 to i64 + %5 = llvm.urem %3, %4 : i64 + %6 = llvm.urem %0, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.sdiv %arg0, %arg0 : i64 + %1 = llvm.xor %arg0, %0 : i64 + %2 = llvm.urem %arg0, %1 : i64 + %3 = llvm.ashr %arg1, %arg0 : i64 + %4 = llvm.or %2, %3 : i64 + %5 = llvm.trunc %4 : i64 to i1 + %6 = llvm.zext %5 : i1 to i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.urem %arg1, %arg2 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.sext %1 : i32 to i64 + %3 = llvm.udiv %arg0, %arg2 : i64 + %4 = llvm.urem %2, %3 : i64 + %5 = llvm.lshr %arg0, %4 : i64 + %6 = llvm.sdiv %5, %arg2 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.zext %arg0 : i1 to i64 + %1 = llvm.xor %0, %0 : i64 + %2 = llvm.xor %0, %1 : i64 + %3 = llvm.and %2, %1 : i64 + %4 = llvm.xor %arg1, %0 : i64 + %5 = llvm.icmp "sge" %3, %4 : i64 + %6 = llvm.sext %5 : i1 to i64 + %7 = llvm.sdiv %6, %arg2 : i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.udiv %arg0, %arg1 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.zext %1 : i32 to i64 + %3 = llvm.lshr %arg2, %arg0 : i64 + %4 = llvm.lshr %2, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + %6 = llvm.zext %5 : i32 to i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i1 { + %0 = llvm.and %arg0, %arg0 : i64 + %1 = llvm.lshr %0, %0 : i64 + %2 = llvm.select %arg1, %arg2, %arg0 : i1, i64 + %3 = llvm.icmp "eq" %arg0, %2 : i64 + %4 = llvm.sext %3 : i1 to i64 + %5 = llvm.sdiv %4, %arg0 : i64 + %6 = llvm.ashr %2, %5 : i64 + %7 = llvm.icmp "ne" %1, %6 : i64 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.urem %arg0, %arg1 : i64 + %1 = llvm.srem %arg1, %arg2 : i64 + %2 = llvm.ashr %1, %1 : i64 + %3 = llvm.udiv %0, %2 : i64 + %4 = llvm.or %0, %3 : i64 + %5 = llvm.urem %arg2, %1 : i64 + %6 = llvm.udiv %5, %5 : i64 + %7 = llvm.lshr %4, %6 : i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.icmp "ult" %arg0, %arg0 : i64 + %1 = llvm.zext %0 : i1 to i64 + %2 = llvm.or %arg0, %1 : i64 + %3 = llvm.ashr %2, %arg1 : i64 + %4 = llvm.udiv %3, %arg1 : i64 + %5 = llvm.sdiv %4, %arg2 : i64 + %6 = llvm.sdiv %5, %arg0 : i64 + %7 = llvm.icmp "slt" %4, %6 : i64 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.ashr %arg0, %arg1 : i64 + %1 = llvm.udiv %arg2, %arg1 : i64 + %2 = llvm.or %arg0, %1 : i64 + %3 = llvm.lshr %0, %2 : i64 + %4 = llvm.ashr %3, %arg1 : i64 + %5 = llvm.or %3, %4 : i64 + %6 = llvm.trunc %5 : i64 to i32 + %7 = llvm.zext %6 : i32 to i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.lshr %arg0, %arg0 : i64 + %1 = llvm.xor %arg0, %0 : i64 + %2 = llvm.trunc %1 : i64 to i32 + %3 = llvm.zext %2 : i32 to i64 + %4 = llvm.xor %3, %3 : i64 + %5 = llvm.and %3, %arg1 : i64 + %6 = llvm.lshr %4, %5 : i64 + %7 = llvm.srem %6, %5 : i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i32, %arg2: i64) -> i32 { + %0 = llvm.sext %arg1 : i32 to i64 + %1 = llvm.icmp "ult" %arg0, %0 : i64 + %2 = llvm.select %1, %0, %arg2 : i1, i64 + %3 = llvm.trunc %2 : i64 to i32 + %4 = llvm.zext %3 : i32 to i64 + %5 = llvm.lshr %2, %arg0 : i64 + %6 = llvm.ashr %4, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.urem %arg1, %arg2 : i64 + %1 = llvm.udiv %arg1, %0 : i64 + %2 = llvm.sdiv %0, %1 : i64 + %3 = llvm.udiv %arg0, %2 : i64 + %4 = llvm.icmp "ugt" %3, %1 : i64 + %5 = llvm.sext %4 : i1 to i64 + %6 = llvm.srem %5, %1 : i64 + %7 = llvm.lshr %5, %6 : i64 + return %7 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.udiv %arg1, %arg2 : i64 + %1 = llvm.icmp "sle" %0, %arg0 : i64 + %2 = llvm.sext %1 : i1 to i64 + %3 = llvm.sdiv %2, %2 : i64 + %4 = llvm.trunc %3 : i64 to i32 + %5 = llvm.sext %4 : i32 to i64 + %6 = llvm.ashr %arg0, %5 : i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i1 { + %0 = llvm.ashr %arg0, %arg1 : i64 + %1 = llvm.or %arg0, %0 : i64 + %2 = llvm.and %arg2, %arg2 : i64 + %3 = llvm.sdiv %arg1, %2 : i64 + %4 = llvm.sdiv %3, %2 : i64 + %5 = llvm.xor %4, %1 : i64 + %6 = llvm.xor %arg2, %5 : i64 + %7 = llvm.icmp "uge" %1, %6 : i64 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { + %0 = llvm.zext %arg3 : i32 to i64 + %1 = llvm.srem %arg2, %0 : i64 + %2 = llvm.or %arg1, %1 : i64 + %3 = llvm.sdiv %arg0, %0 : i64 + %4 = llvm.sdiv %2, %3 : i64 + %5 = llvm.urem %4, %arg1 : i64 + %6 = llvm.lshr %arg0, %5 : i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i1, %arg1: i64, %arg2: i64, %arg3: i32) -> i1 { + %0 = llvm.lshr %arg1, %arg1 : i64 + %1 = llvm.udiv %arg1, %arg2 : i64 + %2 = llvm.and %0, %1 : i64 + %3 = llvm.trunc %2 : i64 to i1 + %4 = llvm.sext %arg3 : i32 to i64 + %5 = llvm.select %3, %2, %4 : i1, i64 + %6 = llvm.select %arg0, %arg1, %5 : i1, i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.srem %arg0, %arg0 : i64 + %1 = llvm.trunc %0 : i64 to i32 + %2 = llvm.sext %1 : i32 to i64 + %3 = llvm.sdiv %2, %arg1 : i64 + %4 = llvm.sdiv %2, %3 : i64 + %5 = llvm.trunc %4 : i64 to i32 + %6 = llvm.zext %5 : i32 to i64 + %7 = llvm.trunc %6 : i64 to i1 + return %7 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i1, %arg2: i64) -> i32 { + %0 = llvm.sext %arg1 : i1 to i64 + %1 = llvm.srem %0, %0 : i64 + %2 = llvm.and %arg0, %1 : i64 + %3 = llvm.udiv %arg0, %arg2 : i64 + %4 = llvm.udiv %3, %3 : i64 + %5 = llvm.udiv %4, %3 : i64 + %6 = llvm.ashr %2, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64, %arg2: i64) -> i32 { + %0 = llvm.icmp "sge" %arg0, %arg1 : i64 + %1 = llvm.select %0, %arg0, %arg2 : i1, i64 + %2 = llvm.or %1, %arg2 : i64 + %3 = llvm.srem %arg2, %arg1 : i64 + %4 = llvm.trunc %3 : i64 to i1 + %5 = llvm.sext %4 : i1 to i64 + %6 = llvm.ashr %2, %5 : i64 + %7 = llvm.trunc %6 : i64 to i32 + return %7 : i32 + } +} +// ----- diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/version_log.txt b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/version_log.txt new file mode 100644 index 0000000000..9431f434b7 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/version_log.txt @@ -0,0 +1 @@ +MLIR-fuzz commit hash: 2210c14 diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/README.md b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/README.md new file mode 100644 index 0000000000..d797779c2f --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/README.md @@ -0,0 +1,60 @@ +# Benchmarks Generation + +### Dependencies + +This evaluation requires LLVM's static compiler (`llc`), either install it through your favourite +package manager, or, if you've built LLVM from source, add the `bin` directory +to your path. + +For example, if you've built LLVM at `~/llvm-project/build`, and you run bash as +your shell, you should run the following before you run the script: + +```bash +export PATH=$PATH:~/llvm-project/build/bin/ +``` + +Our evaluation also depends on [mlir-fuzz](https://github.com/opencompl/mlir-fuzz) to produce the initial synthetic programs, and it needs to be installed to run `generate_multi.py` + + +### How to run + +To generate the initial fuzzed programs, run: +``` +python3 generate_multi.py --num --max_size --min_size +``` + +For each `size` in the interval `[min_size, max_size]`, the script saves to `benchmarks/MLIR_multi` +a single file `out_size.mlir` containing `num` programs. +This will be the starting point of the conversion. + +To generate the remaining benchmarks, run: +``` +uv run generate.py --num --jobs --llvm_opt +``` + +The script `generate.py` populates the folders in `benchmarks` by running the following: +- For each file in `MLIR_multi`, extract `num` single MLIR modules and save them in `benchmarks/MLIR_single/`. Each file containing a single module will have two numbers that remain consistent throughout the lowering (e.g. `size_function_num`, where `size` is the initial program size specified in `generate_multi.py`). +- using `mlir-opt`, convert each of these files containing a single module to the LLVM dialect, save the result in `benchmarks/LLVM/*.ll` + +Then, the scripts lowers all the files using both LLVM and Lean-MLIR, to enable the comparison of the lowered RISCV assembly output. + +*LLVM toolchain* +- using `mlir-translate`, convert the `*.ll` files in LLVMIR, and save the result in `benchmarks/LLVMIR/*.mlir` +- using `llc` with `selectionDAG`, compile the LLVMIR files to the `riscv` backend and save the result in `benchmarks/LLC_ASM_selectiondag/*.s` +- using `llc`, compile the LLVMIR files to the `riscv` backend and save the result in `benchmarks/LLC_ASM_globalisel/*.s` + +*Lean-MLIR toolchain* +- extract the first block `bb0` from the `*.ll` files and save the result in `benchmarks/MLIR_bb0/*.mlir` +- run the Lean-MLIR lowering to RiscV and save the result in `benchmarks/LEANMLIR_ASM/*.mlir`, potentially in parallel by setting the `jobs` input argument (the default number is 1). +- run the Lean-MLIR optimized lowering to RiscV and save the result in `benchmarks/LEANMLIR_ASM_opt/*.mlir`, potentially in parallel by setting the `jobs` input argument (the default number is 1). +- remove `unrealized_cast` operations from the assembly file using XDSL, save the result in `benchmarks/XDSL_no_casts/*.mlir` +- remove `unrealized_cast` operations from the optimized assembly file using XDSL, save the result in `benchmarks/XDSL_no_casts_opt/*.mlir` +- perform register allocation using XDSL, save the result in `benchmarks/XDSL_reg_alloc/*.mlir` +- perform register allocation using XDSL on optimized assembly, save the result in `benchmarks/XDSL_reg_alloc_opt/*.mlir` +- lower to RISCV assembly using XDSL, save the result in `benchmarks/XDSL_ASM/*.mlir` +- lower optimized assembly to RISCV using XDSL, save the result in `benchmarks/XDSL_ASM_opt/*.mlir` + +Each step in `generate.py` produces a log file, which one can retrieve in `logs/`. The names in the log file contain the function and the pass that outputted that file. + +### How to reuse and customize +- to add new MLIR tests, add a file to `benchmarks/MLIR_multi`. Files in this folder at the moment are named according to the followign convention: `out_` + number of MLIR modules in the file + `.mlir`. \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/create_func.py b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/create_func.py new file mode 100644 index 0000000000..2a7c41cfa3 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/create_func.py @@ -0,0 +1,58 @@ +import sys + +from xdsl.rewriter import Rewriter +from xdsl.xdsl_opt_main import xDSLOptMain +from xdsl.rewriter import InsertPoint +from xdsl.ir import Block + +from xdsl.dialects.builtin import ModuleOp, FunctionType +from xdsl.dialects import llvm +from xdsl.dialects import func + + +class MyOptMain(xDSLOptMain): + def process_module(self, module: ModuleOp): + module_args_types = module.body.block.arg_types + return_op = module.body.block.ops.last + return_op_types = [op.type for op in return_op.operands] + assert isinstance(return_op, llvm.ReturnOp) + + new_region = Rewriter().move_region_contents_to_new_regions(module.body) + func_type = FunctionType.from_lists(module_args_types, return_op_types) + new_func = func.FuncOp("main", func_type) + module.body.add_block(Block()) + Rewriter().insert_op(new_func, InsertPoint.at_end(module.body.block)) + new_func.regions = [new_region] + + Rewriter().replace_op(return_op, func.ReturnOp(*return_op.operands)) + + def run(self): + chunks, file_extension = self.prepare_input() + output_stream = self.prepare_output() + + try: + for i, (chunk, offset) in enumerate(chunks): + try: + if i > 0: + output_stream.write("// -----\n") + module = self.parse_chunk(chunk, file_extension, offset) + + if module is not None: + self.process_module(module) + output_stream.write(self.output_resulting_program(module)) + output_stream.flush() + finally: + chunk.close() + finally: + if output_stream is not sys.stdout: + output_stream.close() + + exit(0) + + +def main(): + MyOptMain().run() + + +if "__main__" == __name__: + main() diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/generate.py b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/generate.py new file mode 100755 index 0000000000..f36a89a510 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/generate.py @@ -0,0 +1,635 @@ +#!/usr/bin/env -S uv run --script +# +# /// script +# requires-python = ">=3.12" +# dependencies = ["xdsl"] +# +# [tool.uv.sources] +# xdsl = { git = "https://github.com/luisacicolini/xdsl.git", rev = "5e00c8487235fb56db9183bc3434b44baa4151cf" } +# /// + + +import sys +import os +import shutil +import subprocess +import re +import argparse +import concurrent.futures + + +ROOT_DIR_PATH = ( + subprocess.check_output(["git", "rev-parse", "--show-toplevel"]) + .decode("utf-8") + .strip() +) + +TIMEOUT_SEC = 1800 + +LLC_GLOBALISEL_ASM_DIR_PATH = ( + f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LLC_GlobalISel_ASM/" +) + +LLVM_DIR_PATH = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LLVM/" +LLVMIR_DIR_PATH = ( + f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LLVMIR/" +) +MLIR_bb0_DIR_PATH = ( + f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_bb0/" +) +MLIR_bb0_veIR_DIR_PATH = ( + f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_bb0_veIR/" +) +MLIR_single_DIR_PATH = ( + f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_single/" +) +MLIR_multi_DIR_PATH = ( + f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/" +) +isolated_instructions_DIR_PATH = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/" +LLC_ASM_selectiondag_DIR_PATH = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LLC_ASM_selectiondag/" +LLC_ASM_globalisel_DIR_PATH = ( + f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LLC_ASM_globalisel/" +) +LEANMLIR_ASM_DIR_PATH = ( + f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LEANMLIR_ASM/" +) +LEANMLIR_ASM_opt_DIR_PATH = ( + f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LEANMLIR_ASM_opt/" +) +XDSL_ASM_DIR_PATH = ( + f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/XDSL_ASM/" +) +XDSL_opt_ASM_DIR_PATH = ( + f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/XDSL_opt_ASM/" +) +XDSL_FUNC_ASM_DIR_PATH = ( + f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/XDSL_FUNC/" +) +XDSL_FUNC_opt_ASM_DIR_PATH = ( + f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/XDSL_FUNC_opt/" +) +LOGS_DIR_PATH = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/logs/" + + +AUTOGEN_DIR_PATHS = [ + LLVM_DIR_PATH, + LLVMIR_DIR_PATH, + MLIR_bb0_DIR_PATH, + MLIR_bb0_veIR_DIR_PATH, + MLIR_single_DIR_PATH, + LLC_ASM_selectiondag_DIR_PATH, + LLC_ASM_globalisel_DIR_PATH, + # XDSL_FUNC_ASM_DIR_PATH, + XDSL_FUNC_opt_ASM_DIR_PATH, + # LEANMLIR_ASM_DIR_PATH, + # XDSL_ASM_DIR_PATH, + LOGS_DIR_PATH, + LEANMLIR_ASM_opt_DIR_PATH, + XDSL_opt_ASM_DIR_PATH, +] + + +def setup_benchmarking_directories(): + """ + Create clean directories to store the benchmarks. + """ + for directory in AUTOGEN_DIR_PATHS: + if not os.path.exists(directory): + os.makedirs(directory) + else: + shutil.rmtree(directory) + os.makedirs(directory) + + +def replace_hyphens_in_variables(file_path): + """ + Reads a file, replaces hyphens (-) with underscores (_) within + MLIR variable names (starting with %), and overwrites the file. + """ + + if not os.path.exists(file_path): + print(f"Error: File not found at {file_path}") + return + + pattern = r"(%[a-zA-Z0-9_-]+)" + + def variable_replacer(match): + """Replace all hyphens with underscores in the matched variable name.""" + variable_name = match.group(0) + if "-" in variable_name: + return variable_name.replace("-", "_") + return variable_name + + try: + with open(file_path, "r") as f: + original_content = f.read() + + modified_content = re.sub(pattern, variable_replacer, original_content) + with open(file_path, "w") as f: + f.write(modified_content) + + except IOError as e: + print(f"Error processing file {file_path}: {e}") + except Exception as e: + print(f"An unexpected error occurred: {e}") + + +def run_command(cmd, log_file, timeout=TIMEOUT_SEC): + try: + ret_code = subprocess.Popen( + cmd, cwd=ROOT_DIR_PATH, stdout=log_file, stderr=log_file, shell=True + ).wait(timeout=timeout) + return ret_code + except subprocess.TimeoutExpired: + log_file.truncate(0) + log_file.write(f"timeout of {timeout} seconds reached\n") + print(f"{log_file} - timeout of {timeout} seconds reached") + + +def extract_helper(input_file, output_base, max_functions, base_name): + f = open(input_file, "r") + all_lines = f.readlines() + function_count = 0 + curr_program = [] + brackets_count = 0 + for line in all_lines: + if "{" in line: + brackets_count += 1 + if brackets_count == 2: + # remove indentation + curr_program.append(line[2:]) + if "}" in line: + brackets_count -= 1 + if brackets_count == 1 and len(curr_program) > 0: + # write file + out_f = open(output_base + f"{base_name}{function_count}.mlir", "w") + out_f.writelines(curr_program) + out_f.write("\n") + out_f.close() + curr_program = [] + function_count += 1 + curr_program = [] + if function_count >= max_functions: + print(f"Reached maximum of {max_functions} functions. Stopping extraction.") + break + + +def extract(input_dir, output_base, max_functions, type): + if type: + for filename in os.listdir(input_dir): + input_file = os.path.join(input_dir, filename) + instruction_name = "".join(filename.split(".")[0]) + extract_helper( + input_file, output_base, max_functions, f"{instruction_name}_" + ) + else: + size = input_dir.split("_")[-1].split(".")[0] + base_name = f"{size}_function_" + extract_helper(input_dir, output_base, max_functions, base_name) + + +def MLIR_opt_arith_llvm(input_file, output_file, log_file, pass_dict): + """ + Run mlir-opt and convert a file into LLVM dialect. + """ + cmd_base = ( + "mlir-opt -convert-arith-to-llvm -convert-func-to-llvm --mlir-print-op-generic " + ) + cmd = cmd_base + input_file + " -o " + output_file + ret_code = run_command(cmd, log_file) + pass_dict[output_file] = ret_code + + +def MLIR_translate_llvmir(input_file, output_file, log_file, pass_dict): + """ + Run mlir-translate and translate a file from LLVM dialect to LLVMIR. + """ + cmd_base = "mlir-translate --mlir-to-llvmir " + cmd = cmd_base + input_file + " -o " + output_file + ret_code = run_command(cmd, log_file) + pass_dict[output_file] = ret_code + + +def LLC_compile_riscv_selectiondag(input_file, output_file, log_file, pass_dict, opt): + """ + Compile LLVMIR to RISCV assembly with llc. + """ + cmd_base = ( + "llc -march=riscv64 -mcpu=generic-rv64 -mattr=+m,+b -filetype=asm " + opt + " " + ) + cmd = cmd_base + input_file + " -o " + output_file + ret_code = run_command(cmd, log_file) + pass_dict[output_file] = ret_code + + +def LLC_compile_riscv_globalisel(input_file, output_file, log_file, pass_dict, opt): + """ + Compile LLVMIR to RISCV assembly with llc using the GlobalISel framework. + """ + cmd_base = ( + "llc -march=riscv64 -mcpu=generic-rv64 --global-isel -mattr=+m,+b -filetype=asm " + + opt + + " " + ) + cmd = cmd_base + input_file + " -o " + output_file + ret_code = run_command(cmd, log_file) + pass_dict[output_file] = ret_code + + +def extract_bb0(input_file, output_file, log_file): + """ + Extract the first basic block from the MLIR file. + """ + o_f = open(output_file, "w") + in_block = False + try: + with open(input_file, "r") as f: + for line in f: + line = line.strip() + if "^bb0(" in line: + in_block = True + o_f.write("{\n") + o_f.write(line + "\n") + continue + if in_block: + o_f.write(line + "\n") + if '"llvm.return"' in line: + o_f.write("}" + "\n") + o_f.close() + return + + except FileNotFoundError: + print(f"Error: The file '{input_file}' was not found.", file=log_file) + sys.exit(1) + +def extract_bb0_veIR(input_file, output_file, log_file): + """ + Extract the first basic block from the MLIR file, print it in a `buildin.module`. + """ + o_f = open(output_file, "w") + o_f.write("\"builtin.module\"() ({\n") + in_block = False + try: + with open(input_file, "r") as f: + for line in f: + line = line.strip() + if "^bb0(" in line: + in_block = True + o_f.write("\t" + line + "\n") + continue + if in_block: + o_f.write("\t" + line + "\n") + if '"llvm.return"' in line: + o_f.write("}) : () -> ()\n") + o_f.close() + return + + except FileNotFoundError: + print(f"Error: The file '{input_file}' was not found.", file=log_file) + sys.exit(1) + + +def LAKE_compile_riscv64(jobs, pass_dict): + """ + Lower the input file to RISCV with Lean-MLIR, using multiple threads. + """ + with concurrent.futures.ThreadPoolExecutor(max_workers=jobs) as executor: + futures = {} + + for filename in os.listdir(MLIR_bb0_DIR_PATH): + input_file = os.path.join(MLIR_bb0_DIR_PATH, filename) + basename, _ = os.path.splitext(filename) + output_file = os.path.join(LEANMLIR_ASM_DIR_PATH, basename + ".mlir") + log_file = open(LOGS_DIR_PATH + basename + "_lake.mlir", "w") + cmd_base = f"cd {ROOT_DIR_PATH}; lake exe opt --passriscv64 " + cmd = cmd_base + input_file + " > " + output_file + future = executor.submit(run_command, cmd, log_file) + futures[future] = output_file + + total = len(futures) + for idx, future in enumerate(concurrent.futures.as_completed(futures)): + file_path = futures[future] + ret_code = future.result() + pass_dict[file_path] = ret_code + percentage = (float(idx) / float(total)) * 100 + print(f"compiling with lean-mlir {percentage:.2f}%") + + +def LAKE_compile_riscv64_opt(jobs, pass_dict): + """ + Lower the input file to RISCV with Lean-MLIR, using multiple threads. + """ + with concurrent.futures.ThreadPoolExecutor(max_workers=jobs) as executor: + futures = {} + + for filename in os.listdir(MLIR_bb0_DIR_PATH): + input_file = os.path.join(MLIR_bb0_DIR_PATH, filename) + basename, _ = os.path.splitext(filename) + output_file = os.path.join(LEANMLIR_ASM_opt_DIR_PATH, basename + ".mlir") + log_file = open(LOGS_DIR_PATH + basename + "_lake.mlir", "w") + cmd_base = f"cd {ROOT_DIR_PATH}; lake exe opt --passriscv64_optimized " + cmd = cmd_base + input_file + " > " + output_file + future = executor.submit(run_command, cmd, log_file) + futures[future] = output_file + + total = len(futures) + for idx, future in enumerate(concurrent.futures.as_completed(futures)): + file_path = futures[future] + ret_code = future.result() + pass_dict[file_path] = ret_code + percentage = (float(idx) / float(total)) * 100 + print(f"compiling with lean-mlir (optimized pass): {percentage:.2f}%") + + +def XDSL_create_func(input_file, output_file, log_file, pass_dict): + """ + Remove unrealized casts from the RISCV64 dialect MLIR files with xdsl. + """ + cmd_base = f"python3 {ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/create_func.py " + cmd = cmd_base + input_file + " > " + output_file + ret_code = run_command(cmd, log_file) + pass_dict[output_file] = ret_code + + +def XDSL_reg_alloc(input_file, output_file, log_file, pass_dict): + """ + Remove unrealized casts from the RISCV64 dialect MLIR files with xdsl. + """ + try: + from xdsl.xdsl_opt_main import xDSLOptMain + + xdsl_opt_main = xDSLOptMain( + args=f"{input_file} -p convert-func-to-riscv-func,reconcile-unrealized-casts,riscv-allocate-registers{{force-infinite=true}},riscv-allocate-infinite-registers,canonicalize-register-allocation -t riscv-asm -o {output_file}".split() + ) + xdsl_opt_main.run() + # cmd = cmd_base + input_file + " > " + output_file + # ret_code = run_command(cmd, log_file) + pass_dict[output_file] = 1 + except Exception as e: + print(f"XDSL_reg_alloc failed for {input_file} with error: {e}", file=log_file) + pass_dict[output_file] = 0 + + +def generate_benchmarks(num, jobs, llvm_opt, compare_lowering_patterns=False): + setup_benchmarking_directories() + + if compare_lowering_patterns: + print( + f"Using instruction-specific files from: {isolated_instructions_DIR_PATH}" + ) + extract( + isolated_instructions_DIR_PATH, + MLIR_single_DIR_PATH, + num, + compare_lowering_patterns, + ) + else: + # extract mlir blocks and put them all in separate files + # for each file with programs of a certain size + for file in os.listdir(MLIR_multi_DIR_PATH): + input_file = os.path.join(MLIR_multi_DIR_PATH, file) + replace_hyphens_in_variables(input_file) + extract(input_file, MLIR_single_DIR_PATH, num, compare_lowering_patterns) + + MLIR_opt_file2ret = dict() + idx = 0 + # Run mlir-opt and convert into LLVM dialect + for filename in os.listdir(MLIR_single_DIR_PATH): + input_file = os.path.join(MLIR_single_DIR_PATH, filename) + basename, _ = os.path.splitext(filename) + output_file = os.path.join(LLVM_DIR_PATH, basename + ".ll") + log_file = open(os.path.join(LOGS_DIR_PATH, basename + "_mlir_opt.log"), "w") + MLIR_opt_arith_llvm(input_file, output_file, log_file, MLIR_opt_file2ret) + idx += 1 + percentage = (float(idx) / float(len(os.listdir(MLIR_single_DIR_PATH)))) * 100 + print(f"translating to LLVM with mlir-opt: {percentage:.2f}%") + + MLIR_translate_file2ret = dict() + idx = 0 + # Run mlir-translate and convert LLVM into LLVMIR + for filename in os.listdir(LLVM_DIR_PATH): + input_file = os.path.join(LLVM_DIR_PATH, filename) + # only run the lowering if the previous pass was successful: + if MLIR_opt_file2ret[input_file] == 0: + basename, _ = os.path.splitext(filename) + output_file = os.path.join(LLVMIR_DIR_PATH, basename + ".mlir") + log_file = open( + os.path.join(LOGS_DIR_PATH, basename + "_mlir_translate.log"), "w" + ) + MLIR_translate_llvmir( + input_file, output_file, log_file, MLIR_translate_file2ret + ) + idx += 1 + percentage = (float(idx) / float(len(MLIR_opt_file2ret))) * 100 + print(f"translating to LLVMIR with mlir-translate: {percentage:.2f}%") + + LLC_file2ret = dict() + idx = 0 + # Use llc with `selectionDAG` to compile LLVMIR into RISCV + for filename in os.listdir(LLVMIR_DIR_PATH): + input_file = os.path.join(LLVMIR_DIR_PATH, filename) + # only run the lowering if the previous pass was successful: + if MLIR_translate_file2ret[input_file] == 0: + basename, _ = os.path.splitext(filename) + + if llvm_opt == "default": + output_file = os.path.join( + LLC_ASM_selectiondag_DIR_PATH, basename + ".s" + ) + log_file = open( + os.path.join(LOGS_DIR_PATH, basename + "_selectiondag_llc.log"), + "w", + ) + LLC_compile_riscv_selectiondag( + input_file, output_file, log_file, LLC_file2ret, "" + ) + else: + output_file = os.path.join( + LLC_ASM_selectiondag_DIR_PATH, basename + "_" + llvm_opt + ".s" + ) + log_file = open( + os.path.join( + LOGS_DIR_PATH, + basename + "_selectiondag_llc" + "_" + llvm_opt + ".log", + ), + "w", + ) + LLC_compile_riscv_selectiondag( + input_file, output_file, log_file, LLC_file2ret, "-" + llvm_opt + ) + idx += 1 + percentage = (float(idx) / float(len(MLIR_translate_file2ret))) * 100 + print(f"compiling with llc (selectionDAG {llvm_opt}): {percentage:.2f}%") + + LLC_GLOBALISEL_file2ret = dict() + idx = 0 + # Use llc with `GlobalISel` to compile LLVMIR into RISCV + for filename in os.listdir(LLVMIR_DIR_PATH): + input_file = os.path.join(LLVMIR_DIR_PATH, filename) + # only run the lowering if the previous pass was successful: + if MLIR_translate_file2ret[input_file] == 0: # previous pass succeded + if llvm_opt == "default": + basename, _ = os.path.splitext(filename) + output_file = os.path.join(LLC_ASM_globalisel_DIR_PATH, basename + ".s") + log_file = open( + os.path.join(LOGS_DIR_PATH, basename + "_globalisel_llc.log"), + "w", + ) + LLC_compile_riscv_globalisel( + input_file, output_file, log_file, LLC_GLOBALISEL_file2ret, "" + ) + else: + basename, _ = os.path.splitext(filename) + output_file = os.path.join( + LLC_ASM_globalisel_DIR_PATH, basename + "_" + llvm_opt + ".s" + ) + log_file = open( + os.path.join( + LOGS_DIR_PATH, + basename + "_globalisel_llc" + "_" + llvm_opt + ".log", + ), + "w", + ) + LLC_compile_riscv_globalisel( + input_file, + output_file, + log_file, + LLC_GLOBALISEL_file2ret, + "-" + llvm_opt, + ) + idx += 1 + percentage = (float(idx) / float(len(MLIR_translate_file2ret))) * 100 + print(f"compiling with llc (globalISel {llvm_opt}): {percentage:.2f}%") + + # Extract bb0 + idx = 0 + for filename in os.listdir(LLVM_DIR_PATH): + input_file = os.path.join(LLVM_DIR_PATH, filename) + basename, _ = os.path.splitext(filename) + output_file = os.path.join(MLIR_bb0_DIR_PATH, basename + ".mlir") + output_file_veIR = os.path.join(MLIR_bb0_veIR_DIR_PATH, basename + ".mlir") + log_file = open(os.path.join(LOGS_DIR_PATH, basename + "_bb0_extract.log"), "w") + log_file_veIR = open(os.path.join(LOGS_DIR_PATH, basename + "_bb0_extract_veIR.log"), "w") + extract_bb0(input_file, output_file, log_file) + extract_bb0_veIR(input_file, output_file_veIR, log_file_veIR) + idx += 1 + percentage = (float(idx) / float(len(os.listdir(LLVM_DIR_PATH)))) * 100 + print(f"extracting the first basic block: {percentage:.2f}%") + + # LAKE_file2ret = dict() + # # Run the lean pass in parallel + # LAKE_compile_riscv64(jobs, LAKE_file2ret) + + LAKE_file2ret_opt = dict() + # Run the optimized lean pass in parallel + LAKE_compile_riscv64_opt(jobs, LAKE_file2ret_opt) + + # XDSL_create_func_file2ret = dict() + # idx = 0 + # # Create `func.func` + # for filename in os.listdir(LEANMLIR_ASM_DIR_PATH): + # input_file = os.path.join(LEANMLIR_ASM_DIR_PATH, filename) + # if LAKE_file2ret[input_file] == 0: + # basename, _ = os.path.splitext(filename) + # output_file = os.path.join(XDSL_FUNC_ASM_DIR_PATH, basename + ".mlir") + # log_file = open( + # os.path.join(LOGS_DIR_PATH, basename + "_xdsl_create_func.log"), "w" + # ) + # XDSL_create_func( + # input_file, output_file, log_file, XDSL_create_func_file2ret + # ) + # idx += 1 + # percentage = (float(idx) / float(len(LAKE_file2ret))) * 100 + # print(f"creating func.func module: {percentage:.2f}%") + + XDSL_create_func_file2ret_opt = dict() + idx = 0 + # Create `func.func` + for filename in os.listdir(LEANMLIR_ASM_opt_DIR_PATH): + input_file = os.path.join(LEANMLIR_ASM_opt_DIR_PATH, filename) + if LAKE_file2ret_opt[input_file] == 0: + basename, _ = os.path.splitext(filename) + output_file = os.path.join(XDSL_FUNC_opt_ASM_DIR_PATH, basename + ".mlir") + log_file = open( + os.path.join(LOGS_DIR_PATH, basename + "_xdsl_create_func_opt.log"), "w" + ) + XDSL_create_func( + input_file, output_file, log_file, XDSL_create_func_file2ret_opt + ) + idx += 1 + percentage = (float(idx) / float(len(LAKE_file2ret_opt))) * 100 + print(f"creating func.func module (opt): {percentage:.2f}%") + + # XDSL_reg_alloc_file2ret = dict() + # idx = 0 + # # Register allocation with XDSL + # for filename in os.listdir(XDSL_FUNC_ASM_DIR_PATH): + # input_file = os.path.join(XDSL_FUNC_ASM_DIR_PATH, filename) + # if XDSL_create_func_file2ret[input_file] == 0: + # basename, _ = os.path.splitext(filename) + # output_file = os.path.join(XDSL_ASM_DIR_PATH, basename + ".mlir") + # log_file = open( + # os.path.join(LOGS_DIR_PATH, basename + "_xdsl_reg_alloc.log"), "w" + # ) + # XDSL_reg_alloc(input_file, output_file, log_file, XDSL_reg_alloc_file2ret) + # idx += 1 + # percentage = (float(idx) / float(len(XDSL_create_func_file2ret))) * 100 + # print(f"allocating registers and outputting assembly: {percentage:.2f}%") + + XDSL_reg_alloc_file2ret_opt = dict() + idx = 0 + # Register allocation with XDSL + for filename in os.listdir(XDSL_FUNC_opt_ASM_DIR_PATH): + input_file = os.path.join(XDSL_FUNC_opt_ASM_DIR_PATH, filename) + if XDSL_create_func_file2ret_opt[input_file] == 0: + basename, _ = os.path.splitext(filename) + output_file = os.path.join(XDSL_opt_ASM_DIR_PATH, basename + ".mlir") + log_file = open( + os.path.join(LOGS_DIR_PATH, basename + "_xdsl_reg_alloc.log"), "w" + ) + XDSL_reg_alloc( + input_file, output_file, log_file, XDSL_reg_alloc_file2ret_opt + ) + idx += 1 + percentage = (float(idx) / float(len(XDSL_create_func_file2ret_opt))) * 100 + print(f"allocating registers and outputting assembly (opt): {percentage:.2f}%") + + +def main(): + parser = argparse.ArgumentParser( + prog="generate", + description="Generate a new set of benchmarks in all the representations, from MLIR to RISCV assembly.", + ) + + parser.add_argument( + "-n", "--num", type=int, default=100, help="Number of benchmarks to generate. " + ) + + parser.add_argument( + "-j", "--jobs", type=int, default=1, help="Parallel jobs for all benchmarks" + ) + + parser.add_argument( + "-llvm", + "--llvm_opt", + help="Optimization level for LLVM.", + choices=["O3", "O2", "O1", "O0", "default", "all"], + default="default", + ) + + parser.add_argument( + "-l", + "--instruction_lowering", + help="Create files for instruction lowering patterns comparison.", + action="store_true", + default=False, + ) + + args = parser.parse_args() + + generate_benchmarks(args.num, args.jobs, args.llvm_opt, args.instruction_lowering) + + +if __name__ == "__main__": + main() diff --git a/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/generate_multi.py b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/generate_multi.py new file mode 100644 index 0000000000..aff162dc17 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/generate_multi.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 + +import subprocess +import os +import shutil +import argparse + +MLIR_fuzz_DIR_PATH = "~/mlir-fuzz" + +ROOT_DIR_PATH = ( + subprocess.check_output(["git", "rev-parse", "--show-toplevel"]) + .decode("utf-8") + .strip() +) + +MLIR_multi_DIR_PATH = ( + f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/MLIR_multi/" +) + + +def create_version_log(): + """ + Checks the git hash of `mlir-fuzz` and saves it to `MLIR_multi/version_log.txt`. + """ + + git_command = ["git", "rev-parse", "--short", "HEAD"] + external_repo = os.path.expanduser(MLIR_fuzz_DIR_PATH) + result = subprocess.run( + git_command, cwd=external_repo, capture_output=True, text=True, check=True + ) + + commit_hash = result.stdout.strip() + + log_file_path = os.path.join(MLIR_multi_DIR_PATH, "version_log.txt") + log_file = open(log_file_path, "w") + log_file.write(f"MLIR-fuzz commit hash: {commit_hash}\n") + log_file.close() + + +def generate_benchmarks(num_programs, min_size, max_size): + if not os.path.exists(MLIR_multi_DIR_PATH): + os.makedirs(MLIR_multi_DIR_PATH) + else: + shutil.rmtree(MLIR_multi_DIR_PATH) + os.makedirs(MLIR_multi_DIR_PATH) + + create_version_log() + + for size in range(min_size, max_size + 1): + output_file = f"{MLIR_multi_DIR_PATH}/output_{size}.mlir" + command = ( + f"{MLIR_fuzz_DIR_PATH}/build/bin/mlir-enumerate {MLIR_fuzz_DIR_PATH}/dialects/llvm.mlir " + + f"--exact-size=1 --max-num-ops={size} --min-constant-value=-50 --max-constant-value=50 --min-num-args=1 --strategy=random --max-programs={num_programs} --constant-kind=none" + + f"> {output_file}" + ) + + print(f"Generating benchmarks of size {size} into {output_file}") + print(command) + os.system(command) + + +def main(): + parser = argparse.ArgumentParser( + prog="generate", + description="Generate a new set of benchmarks in all the representations, from MLIR to RISCV assembly.", + ) + + parser.add_argument( + "--min_size", + type=int, + help="Min #ops of the synthesized programs. ", + ) + + parser.add_argument( + "--max_size", + type=int, + help="Max #ops of the synthesized programs. ", + ) + + parser.add_argument( + "--num", + type=int, + help="#programs for each size in the [min_size, max_size] interval. ", + ) + + args = parser.parse_args() + generate_benchmarks(args.num, args.min_size, args.max_size) + + +if __name__ == "__main__": + main() diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/README.md b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/README.md new file mode 100644 index 0000000000..5bd7d82bbe --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/README.md @@ -0,0 +1,33 @@ +# Benchmarks Generation + +### Dependencies + +This evaluation relies on dependencies from both `Evaluation/benchmarks` and `Evaluation/mca-analysis`. Therefore `llc` and `evallib` must be in the path. Evallib is added to the path in the given `run_comparison.sh` script. + +### How to run + +Use the `run_comparison.sh` script to run the comparisons. First make the script executable by: + +```bash +chmod +x ./run_comparison.sh +``` + +Then run the script by: +```bash +./run_comparison.sh +``` + +The results are logged in the `comparison.log` file. + +### Results +The comparison script performs a comprehensive analysis of instruction lowering patterns across multiple compilers and optimization levels, organized into three distinct phases. + +Phase 1: LLVM Compiler Consistency Check + The script begins by comparing SelectionDAG and GlobalISel. For each instruction variant, it examines all optimization levels (O0, O1, O2, O3) to verify consistency within each compiler. This internal consistency check ensures that the instruction lowering pattern remains stable across different optimization levels within the same compiler backend. +Phase 2: Cross-Compiler Comparison (LLVM) + After that, the script performs a cross-compiler comparison between SelectionDAG and GlobalISel outputs. For each optimization level, it compares the generated instruction sequences from both frameworks. This comparison reveals whether the two instruction selection approaches produce identical or different lowering patterns for the same input. +Phase 3: LEAN-MLIR vs LLVM Comparison + Finally, the script compares the LEAN-MLIR compiler outputs against LLVM's results at specific optimization levels. This comparison is performed in two stages: + +Unoptimized comparison: LEAN-MLIR output is compared against O0 outputs from both GlobalISel and SelectionDAG. +Optimized comparison: LEAN-MLIR-opt output is compared against O2 outputs from both GlobalISel and SelectionDAG. diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/compare_lowerings.py b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/compare_lowerings.py new file mode 100644 index 0000000000..f72d4cf0de --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/compare_lowerings.py @@ -0,0 +1,440 @@ +#!/usr/bin/env python3 + +import os +import re +import sys +import argparse +from pathlib import Path +from collections import defaultdict, Counter +import json +import subprocess +from datetime import datetime + +ROOT_DIR = ( + subprocess.check_output(["git", "rev-parse", "--show-toplevel"]) + .decode("utf-8") + .strip() +) + +MCA_LEANMLIR_DIR = ( + f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LEANMLIR/" +) +MCA_LEANMLIR_opt_DIR = ( + f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LEANMLIR_opt/" +) +MCA_LLVM_globalisel_DIR = ( + f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LLVM_globalisel/" +) +MCA_LLVM_selectiondag_DIR = ( + f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LLVM_selectiondag/" +) + +LOGS_DIR = f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns" + + +class Logger: + """Logger class to write to both console and file.""" + + def __init__(self, log_file): + self.log_file = log_file + self.file_handle = None + + def __enter__(self): + # Create logs directory if it doesn't exist + os.makedirs(os.path.dirname(self.log_file), exist_ok=True) + self.file_handle = open(self.log_file, 'w') + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + if self.file_handle: + self.file_handle.close() + + def log(self, message): + """Write message to both console and file.""" + print(message) + if self.file_handle: + self.file_handle.write(message + '\n') + self.file_handle.flush() + + +def parse_instructions(filename): + """ + Parse instructions from a compiler output file. + + Args: + filename: Path to the .out file + + Returns: + List of instruction names + """ + instructions = [] + in_instruction_section = False + + try: + with open(filename, 'r') as f: + for line in f: + if '[0] [1] [2] [3] [4] [5] [6] [7] Instructions:' in line: + in_instruction_section = True + continue + if in_instruction_section and line.strip(): + parts = line.split() + if len(parts) > 8: + instruction = parts[8] # inst name is in 9th column + instructions.append(instruction) + except FileNotFoundError: + print(f"Warning: File not found: {filename}") + return [] + except Exception as e: + print(f"Error parsing {filename}: {e}") + return [] + + return instructions + + +def collect_results_lean(base_dir): + results = {} + + if not os.path.exists(base_dir): + print(f"Warning: Directory not found: {base_dir}") + return results + + for filename in os.listdir(base_dir): + filepath = os.path.join(base_dir, filename) + basename = os.path.basename(filename) + pattern = r'llvm_(\w+)_(\d+)\.out' + match = re.match(pattern, basename) + + if match: + instruction_name = match.group(1) + variant = int(match.group(2)) + + instructions = parse_instructions(filepath) + + if instruction_name not in results: + results[instruction_name] = {} + + results[instruction_name][variant] = instructions + + return results + + + +def collect_results_llvm(base_dir): + results = {} + + if not os.path.exists(base_dir): + print(f"Warning: Directory not found: {base_dir}") + return results + + for filename in os.listdir(base_dir): + filepath = os.path.join(base_dir, filename) + basename = os.path.basename(filename) + pattern = r'llvm_(\w+)_(\d+)_(O[0-3]|default)\.out' + match = re.match(pattern, basename) + + if match: + instruction_name = match.group(1) + variant = int(match.group(2)) + opt_level = match.group(3) + + instructions = parse_instructions(filepath) + + if instruction_name not in results: + results[instruction_name] = {} + if variant not in results[instruction_name]: + results[instruction_name][variant] = {} + + results[instruction_name][variant][opt_level] = instructions + + return results + + +def log_instruction_diff(logger, instructions_list, labels): + """ + Log detailed differences between instruction lists. + + Args: + logger: Logger instance + instructions_list: List of instruction lists to compare + labels: Labels for each instruction list + """ + max_len = max(len(insts) for insts in instructions_list) + + logger.log("\n Instruction-by-instruction comparison:") + logger.log(" " + "-" * 80) + + # Print header + header = f" {'Index':<8}" + for label in labels: + header += f"{label:<25}" + logger.log(header) + logger.log(" " + "-" * 80) + + # Compare instruction by instruction + for i in range(max_len): + row = f" {i:<8}" + instructions_at_i = [] + + for insts in instructions_list: + if i < len(insts): + inst = insts[i] + instructions_at_i.append(inst) + row += f"{inst:<25}" + else: + instructions_at_i.append(None) + row += f"{'':<25}" + + # Highlight if instructions differ at this position + if len(set(inst for inst in instructions_at_i if inst is not None)) > 1: + logger.log(row + " DIFFERS") + else: + logger.log(row) + + logger.log(" " + "-" * 80) + + # Print summary + logger.log("\n Summary:") + for label, insts in zip(labels, instructions_list): + logger.log(f" {label}: {len(insts)} instructions") + logger.log("") + + +def compare_in_compiler(logger, results, op, var, compiler_name): + """ + Compare instruction sets across optimization levels within a single compiler. + + Args: + logger: Logger instance + results: List of instruction lists for different optimization levels + op: Operation name + var: Variant number + compiler_name: Name of the compiler + """ + all_equal = all(lst == results[0] for lst in results) + + if all_equal: + logger.log(f" ✓ All optimization levels produce the same instructions for " + f"{compiler_name} llvm.{op} variant {var}") + else: + logger.log(f"\n ✗ DIFFERENT instruction sets found across optimization levels for " + f"{compiler_name} llvm.{op} variant {var}") + + # Create labels for each optimization level + opt_levels = ['O0', 'O1', 'O2', 'O3', 'default'][:len(results)] + log_instruction_diff(logger, results, opt_levels) + + +def compare_llvm_compilers(logger, globalisel_results, selectiondag_results): + """ + Compare instruction sets between GlobalISel and SelectionDAG compilers. + """ + logger.log("\n" + "=" * 100) + logger.log("COMPARISON 1: GlobalISel vs SelectionDAG") + logger.log("=" * 100 + "\n") + + for operation in sorted(globalisel_results.keys()): + for variant in sorted(globalisel_results[operation].keys()): + logger.log(f"\n{'─' * 100}") + logger.log(f"Operation: llvm.{operation}, Variant: {variant}") + logger.log(f"{'─' * 100}") + + opt_results_globalisel = [] + opt_results_selectiondag = [] + opt_levels = sorted(globalisel_results[operation][variant].keys()) + + # Compare across optimization levels + for opt_level in opt_levels: + globalisel_insts = globalisel_results[operation][variant][opt_level] + selectiondag_insts = selectiondag_results[operation][variant][opt_level] + + opt_results_globalisel.append(globalisel_insts) + opt_results_selectiondag.append(selectiondag_insts) + + if globalisel_insts == selectiondag_insts: + logger.log(f" ✓ Same instructions at {opt_level}") + else: + logger.log(f"\n ✗ DIFFERENT instructions at {opt_level}") + log_instruction_diff( + logger, + [globalisel_insts, selectiondag_insts], + [f"GlobalISel-{opt_level}", f"SelectionDAG-{opt_level}"] + ) + + # Compare within each compiler across optimization levels + logger.log("") + compare_in_compiler(logger, opt_results_globalisel, operation, variant, "GlobalISel") + compare_in_compiler(logger, opt_results_selectiondag, operation, variant, "SelectionDAG") + + +def compare_lean_vs_llvm(logger, leanmlir_results, leanmlir_opt_results, + globalisel_results, selectiondag_results): + """ + Compare LEAN compilers with LLVM compilers. + - LEANMLIR vs O0 of GlobalISel and SelectionDAG + - LEANMLIR_opt vs O2 of GlobalISel and SelectionDAG + """ + logger.log("\n" + "=" * 100) + logger.log("COMPARISON 2: LEANMLIR vs LLVM at O0") + logger.log("=" * 100 + "\n") + + # Get all operations that exist in LEANMLIR + for operation in sorted(leanmlir_results.keys()): + for variant in sorted(leanmlir_results[operation].keys()): + logger.log(f"\n{'─' * 100}") + logger.log(f"Operation: llvm.{operation}, Variant: {variant}") + logger.log(f"{'─' * 100}") + + lean_insts = leanmlir_results[operation][variant] + + # Check if this operation/variant exists in LLVM results + if operation not in globalisel_results or variant not in globalisel_results[operation]: + logger.log(f" ✗ Operation/variant not found in GlobalISel results") + continue + + if operation not in selectiondag_results or variant not in selectiondag_results[operation]: + logger.log(f" ✗ Operation/variant not found in SelectionDAG results") + continue + + # Get O0 instructions from LLVM compilers + globalisel_o0 = globalisel_results[operation][variant].get('O0', []) + selectiondag_o0 = selectiondag_results[operation][variant].get('O0', []) + + if not globalisel_o0: + logger.log(f" ✗ O0 results not found for GlobalISel") + if not selectiondag_o0: + logger.log(f" ✗ O0 results not found for SelectionDAG") + + # Compare LEAN vs GlobalISel O0 + if globalisel_o0: + if lean_insts == globalisel_o0: + logger.log(f" ✓ LEANMLIR matches GlobalISel-O0") + else: + logger.log(f"\n ✗ LEANMLIR DIFFERS from GlobalISel-O0") + log_instruction_diff( + logger, + [lean_insts, globalisel_o0], + ["LEANMLIR", "GlobalISel-O0"] + ) + + # Compare LEAN vs SelectionDAG O0 + if selectiondag_o0: + if lean_insts == selectiondag_o0: + logger.log(f" ✓ LEANMLIR matches SelectionDAG-O0") + else: + logger.log(f"\n ✗ LEANMLIR DIFFERS from SelectionDAG-O0") + log_instruction_diff( + logger, + [lean_insts, selectiondag_o0], + ["LEANMLIR", "SelectionDAG-O0"] + ) + + # Compare all three at once for a comprehensive view + if globalisel_o0 and selectiondag_o0: + all_same = lean_insts == globalisel_o0 == selectiondag_o0 + if all_same: + logger.log(f"\n ✓ All three produce IDENTICAL instructions (LEANMLIR, GlobalISel-O0, SelectionDAG-O0)") + else: + logger.log(f"\n Comprehensive comparison of all three:") + log_instruction_diff( + logger, + [lean_insts, globalisel_o0, selectiondag_o0], + ["LEANMLIR", "GlobalISel-O0", "SelectionDAG-O0"] + ) + + logger.log("\n" + "=" * 100) + logger.log("COMPARISON 3: LEANMLIR_opt vs LLVM at O2") + logger.log("=" * 100 + "\n") + + # Get all operations that exist in LEANMLIR_opt + for operation in sorted(leanmlir_opt_results.keys()): + for variant in sorted(leanmlir_opt_results[operation].keys()): + logger.log(f"\n{'─' * 100}") + logger.log(f"Operation: llvm.{operation}, Variant: {variant}") + logger.log(f"{'─' * 100}") + + lean_opt_insts = leanmlir_opt_results[operation][variant] + + # Check if this operation/variant exists in LLVM results + if operation not in globalisel_results or variant not in globalisel_results[operation]: + logger.log(f" ✗ Operation/variant not found in GlobalISel results") + continue + + if operation not in selectiondag_results or variant not in selectiondag_results[operation]: + logger.log(f" ✗ Operation/variant not found in SelectionDAG results") + continue + + # Get O2 instructions from LLVM compilers + globalisel_o2 = globalisel_results[operation][variant].get('O2', []) + selectiondag_o2 = selectiondag_results[operation][variant].get('O2', []) + + if not globalisel_o2: + logger.log(f" ✗ O2 results not found for GlobalISel") + if not selectiondag_o2: + logger.log(f" ✗ O2 results not found for SelectionDAG") + + # Compare LEAN_opt vs GlobalISel O2 + if globalisel_o2: + if lean_opt_insts == globalisel_o2: + logger.log(f" ✓ LEANMLIR_opt matches GlobalISel-O2") + else: + logger.log(f"\n ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2") + log_instruction_diff( + logger, + [lean_opt_insts, globalisel_o2], + ["LEANMLIR_opt", "GlobalISel-O2"] + ) + + # Compare LEAN_opt vs SelectionDAG O2 + if selectiondag_o2: + if lean_opt_insts == selectiondag_o2: + logger.log(f" ✓ LEANMLIR_opt matches SelectionDAG-O2") + else: + logger.log(f"\n ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2") + log_instruction_diff( + logger, + [lean_opt_insts, selectiondag_o2], + ["LEANMLIR_opt", "SelectionDAG-O2"] + ) + + # Compare all three at once for a comprehensive view + if globalisel_o2 and selectiondag_o2: + all_same = lean_opt_insts == globalisel_o2 == selectiondag_o2 + if all_same: + logger.log(f"\n ✓ All three produce IDENTICAL instructions (LEANMLIR_opt, GlobalISel-O2, SelectionDAG-O2)") + else: + logger.log(f"\n Comprehensive comparison of all three:") + log_instruction_diff( + logger, + [lean_opt_insts, globalisel_o2, selectiondag_o2], + ["LEANMLIR_opt", "GlobalISel-O2", "SelectionDAG-O2"] + ) + + +def main(): + log_file = os.path.join(LOGS_DIR, f"comparison.log") + + # Collect results from all compilers + print(f"Collecting results... (log will be saved to {log_file})") + + globalisel_results = collect_results_llvm(MCA_LLVM_globalisel_DIR) + selectiondag_results = collect_results_llvm(MCA_LLVM_selectiondag_DIR) + leanmlir_results = collect_results_lean(MCA_LEANMLIR_DIR) + leanmlir_opt_results = collect_results_lean(MCA_LEANMLIR_opt_DIR) + + # Use logger context manager + with Logger(log_file) as logger: + # Compare LLVM compilers + compare_llvm_compilers(logger, globalisel_results, selectiondag_results) + + # Compare LEAN vs LLVM + compare_lean_vs_llvm(logger, leanmlir_results, leanmlir_opt_results, + globalisel_results, selectiondag_results) + + logger.log("\n" + "=" * 100) + logger.log("END OF ALL COMPARISONS") + logger.log("=" * 100 + "\n") + + print(f"\nLog file saved to: {log_file}") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/comparison.log b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/comparison.log new file mode 100644 index 0000000000..326c9e36d4 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/comparison.log @@ -0,0 +1,5370 @@ + +==================================================================================================== +COMPARISON 1: GlobalISel vs SelectionDAG +==================================================================================================== + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.add, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.add variant 0 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.add variant 0 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.add, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.add variant 1 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.add variant 1 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.add, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.add variant 2 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.add variant 2 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.and, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.and variant 0 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.and variant 0 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.ashr, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.ashr variant 0 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.ashr variant 0 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.icmp variant 0 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.icmp variant 0 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.icmp variant 1 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.icmp variant 1 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.icmp variant 2 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.icmp variant 2 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 3 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.icmp variant 3 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.icmp variant 3 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 4 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.icmp variant 4 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.icmp variant 4 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 5 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.icmp variant 5 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.icmp variant 5 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 6 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.icmp variant 6 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.icmp variant 6 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 7 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.icmp variant 7 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.icmp variant 7 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 8 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.icmp variant 8 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.icmp variant 8 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.mul, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.mul variant 0 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.mul variant 0 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.mul, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.mul variant 1 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.mul variant 1 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.mul, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.mul variant 2 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.mul variant 2 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.or, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.or variant 0 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.or variant 0 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.rem, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.rem variant 0 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.rem variant 0 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sdiv, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.sdiv variant 0 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.sdiv variant 0 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.select, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ DIFFERENT instructions at O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 addi addi + 1 sd sd + 2 andi mv ⚠️ DIFFERS + 3 sd andi ⚠️ DIFFERS + 4 bnez sd ⚠️ DIFFERS + 5 ld bnez ⚠️ DIFFERS + 6 sd ld ⚠️ DIFFERS + 7 ld sd ⚠️ DIFFERS + 8 addi ld ⚠️ DIFFERS + 9 ret addi ⚠️ DIFFERS + 10 ret + -------------------------------------------------------------------------------- + + Summary: + GlobalISel-O0: 10 instructions + SelectionDAG-O0: 11 instructions + + + ✗ DIFFERENT instructions at O1 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index GlobalISel-O1 SelectionDAG-O1 + -------------------------------------------------------------------------------- + 0 mv andi ⚠️ DIFFERS + 1 mv mv + 2 andi bnez ⚠️ DIFFERS + 3 bnez mv ⚠️ DIFFERS + 4 mv ret ⚠️ DIFFERS + 5 ret + -------------------------------------------------------------------------------- + + Summary: + GlobalISel-O1: 6 instructions + SelectionDAG-O1: 5 instructions + + + ✗ DIFFERENT instructions at O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv andi ⚠️ DIFFERS + 1 mv mv + 2 andi bnez ⚠️ DIFFERS + 3 bnez mv ⚠️ DIFFERS + 4 mv ret ⚠️ DIFFERS + 5 ret + -------------------------------------------------------------------------------- + + Summary: + GlobalISel-O2: 6 instructions + SelectionDAG-O2: 5 instructions + + + ✗ DIFFERENT instructions at O3 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index GlobalISel-O3 SelectionDAG-O3 + -------------------------------------------------------------------------------- + 0 mv andi ⚠️ DIFFERS + 1 mv mv + 2 andi bnez ⚠️ DIFFERS + 3 bnez mv ⚠️ DIFFERS + 4 mv ret ⚠️ DIFFERS + 5 ret + -------------------------------------------------------------------------------- + + Summary: + GlobalISel-O3: 6 instructions + SelectionDAG-O3: 5 instructions + + + + ✗ DIFFERENT instruction sets found across optimization levels for GlobalISel llvm.select variant 0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index O0 O1 O2 O3 + -------------------------------------------------------------------------------- + 0 addi mv mv mv ⚠️ DIFFERS + 1 sd mv mv mv ⚠️ DIFFERS + 2 andi andi andi andi + 3 sd bnez bnez bnez ⚠️ DIFFERS + 4 bnez mv mv mv ⚠️ DIFFERS + 5 ld ret ret ret ⚠️ DIFFERS + 6 sd + 7 ld + 8 addi + 9 ret + -------------------------------------------------------------------------------- + + Summary: + O0: 10 instructions + O1: 6 instructions + O2: 6 instructions + O3: 6 instructions + + + ✗ DIFFERENT instruction sets found across optimization levels for SelectionDAG llvm.select variant 0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index O0 O1 O2 O3 + -------------------------------------------------------------------------------- + 0 addi andi andi andi ⚠️ DIFFERS + 1 sd mv mv mv ⚠️ DIFFERS + 2 mv bnez bnez bnez ⚠️ DIFFERS + 3 andi mv mv mv ⚠️ DIFFERS + 4 sd ret ret ret ⚠️ DIFFERS + 5 bnez + 6 ld + 7 sd + 8 ld + 9 addi + 10 ret + -------------------------------------------------------------------------------- + + Summary: + O0: 11 instructions + O1: 5 instructions + O2: 5 instructions + O3: 5 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sext, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.sext variant 0 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.sext variant 0 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sext, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.sext variant 1 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.sext variant 1 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sext, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.sext variant 2 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.sext variant 2 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sext, Variant: 3 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.sext variant 3 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.sext variant 3 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.shl, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.shl variant 0 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.shl variant 0 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.shl, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.shl variant 1 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.shl variant 1 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.shl, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.shl variant 2 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.shl variant 2 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.shl, Variant: 3 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.shl variant 3 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.shl variant 3 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.srl, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.srl variant 0 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.srl variant 0 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sub, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.sub variant 0 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.sub variant 0 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sub, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.sub variant 1 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.sub variant 1 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sub, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.sub variant 2 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.sub variant 2 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.trunc, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.trunc variant 0 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.trunc variant 0 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.udiv, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.udiv variant 0 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.udiv variant 0 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.urem, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.urem variant 0 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.urem variant 0 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.xor, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.xor variant 0 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.xor variant 0 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.zext, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.zext variant 0 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.zext variant 0 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.zext, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.zext variant 1 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.zext variant 1 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.zext, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.zext variant 2 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.zext variant 2 + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.zext, Variant: 3 +──────────────────────────────────────────────────────────────────────────────────────────────────── + ✓ Same instructions at O0 + ✓ Same instructions at O1 + ✓ Same instructions at O2 + ✓ Same instructions at O3 + + ✓ All optimization levels produce the same instructions for GlobalISel llvm.zext variant 3 + ✓ All optimization levels produce the same instructions for SelectionDAG llvm.zext variant 3 + +==================================================================================================== +COMPARISON 2: LEANMLIR vs LLVM at O0 +==================================================================================================== + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.add, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv add ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 add + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv add ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 add + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv add add ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 add + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.add, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv add ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 add + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv add ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 add + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv add add ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 add + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.add, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv add ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 add + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv add ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 add + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv add add ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 add + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.and, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv and ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 and + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv and ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 and + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv and and ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 and + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.ashr, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv sra ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sra + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sra ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sra + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sra sra ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sra + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv sltu ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sltu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sltu ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sltu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sltu sltu ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sltu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv sltu ⚠️ DIFFERS + 1 mv xori ⚠️ DIFFERS + 2 sltu ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 6 instructions + GlobalISel-O0: 3 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sltu ⚠️ DIFFERS + 1 mv xori ⚠️ DIFFERS + 2 sltu ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 6 instructions + SelectionDAG-O0: 3 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sltu sltu ⚠️ DIFFERS + 1 mv xori xori ⚠️ DIFFERS + 2 sltu ret ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 6 instructions + GlobalISel-O0: 3 instructions + SelectionDAG-O0: 3 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv sltu ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sltu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sltu ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sltu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sltu sltu ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sltu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 3 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv sltu ⚠️ DIFFERS + 1 mv xori ⚠️ DIFFERS + 2 sltu ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 6 instructions + GlobalISel-O0: 3 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sltu ⚠️ DIFFERS + 1 mv xori ⚠️ DIFFERS + 2 sltu ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 6 instructions + SelectionDAG-O0: 3 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sltu sltu ⚠️ DIFFERS + 1 mv xori xori ⚠️ DIFFERS + 2 sltu ret ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 6 instructions + GlobalISel-O0: 3 instructions + SelectionDAG-O0: 3 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 4 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv slt ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 slt + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv slt ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 slt + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv slt slt ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 slt + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 5 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv slt ⚠️ DIFFERS + 1 mv xori ⚠️ DIFFERS + 2 slt ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 6 instructions + GlobalISel-O0: 3 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv slt ⚠️ DIFFERS + 1 mv xori ⚠️ DIFFERS + 2 slt ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 6 instructions + SelectionDAG-O0: 3 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv slt slt ⚠️ DIFFERS + 1 mv xori xori ⚠️ DIFFERS + 2 slt ret ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 6 instructions + GlobalISel-O0: 3 instructions + SelectionDAG-O0: 3 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 6 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv slt ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 slt + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv slt ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 slt + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv slt slt ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 slt + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 7 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv slt ⚠️ DIFFERS + 1 mv xori ⚠️ DIFFERS + 2 slt ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 6 instructions + GlobalISel-O0: 3 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv slt ⚠️ DIFFERS + 1 mv xori ⚠️ DIFFERS + 2 slt ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 6 instructions + SelectionDAG-O0: 3 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv slt slt ⚠️ DIFFERS + 1 mv xori xori ⚠️ DIFFERS + 2 slt ret ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 6 instructions + GlobalISel-O0: 3 instructions + SelectionDAG-O0: 3 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 8 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv xor ⚠️ DIFFERS + 1 mv seqz ⚠️ DIFFERS + 2 xor ret ⚠️ DIFFERS + 3 seqz + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 6 instructions + GlobalISel-O0: 3 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv xor ⚠️ DIFFERS + 1 mv seqz ⚠️ DIFFERS + 2 xor ret ⚠️ DIFFERS + 3 seqz + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 6 instructions + SelectionDAG-O0: 3 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv xor xor ⚠️ DIFFERS + 1 mv seqz seqz ⚠️ DIFFERS + 2 xor ret ret ⚠️ DIFFERS + 3 seqz + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 6 instructions + GlobalISel-O0: 3 instructions + SelectionDAG-O0: 3 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.mul, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv mul ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 mul + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv mul ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 mul + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv mul mul ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 mul + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.mul, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv mul ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 mul + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv mul ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 mul + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv mul mul ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 mul + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.mul, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv mul ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 mul + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv mul ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 mul + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv mul mul ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 mul + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.or, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv or ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 or + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv or ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 or + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv or or ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 or + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.rem, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv rem ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 rem + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv rem ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 rem + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv rem rem ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 rem + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sdiv, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv div ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 div + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv div ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 div + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv div div ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 div + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.select, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 addi + 1 sd + 2 andi + 3 sd + 4 bnez + 5 ld + 6 sd + 7 ld + 8 addi + 9 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 0 instructions + GlobalISel-O0: 10 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 addi + 1 sd + 2 mv + 3 andi + 4 sd + 5 bnez + 6 ld + 7 sd + 8 ld + 9 addi + 10 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 0 instructions + SelectionDAG-O0: 11 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 addi addi + 1 sd sd + 2 andi mv ⚠️ DIFFERS + 3 sd andi ⚠️ DIFFERS + 4 bnez sd ⚠️ DIFFERS + 5 ld bnez ⚠️ DIFFERS + 6 sd ld ⚠️ DIFFERS + 7 ld sd ⚠️ DIFFERS + 8 addi ld ⚠️ DIFFERS + 9 ret addi ⚠️ DIFFERS + 10 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 0 instructions + GlobalISel-O0: 10 instructions + SelectionDAG-O0: 11 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sext, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 slli + 1 srai + 2 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 0 instructions + GlobalISel-O0: 3 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 slli + 1 srai + 2 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 0 instructions + SelectionDAG-O0: 3 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 slli slli + 1 srai srai + 2 ret ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 0 instructions + GlobalISel-O0: 3 instructions + SelectionDAG-O0: 3 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sext, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 sext.b + 1 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 0 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 sext.b + 1 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 0 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 sext.b sext.b + 1 ret ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 0 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sext, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 sext.h + 1 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 0 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 sext.h + 1 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 0 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 sext.h sext.h + 1 ret ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 0 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sext, Variant: 3 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 sext.w + 1 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 0 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 sext.w + 1 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 0 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 sext.w sext.w + 1 ret ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 0 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.shl, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv sll ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sll ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sll sll ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.shl, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv sll ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sll ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sll sll ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.shl, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv sll ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sll ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sll sll ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.shl, Variant: 3 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv sll ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sll ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sll sll ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.srl, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv srl ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 srl + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv srl ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 srl + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv srl srl ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 srl + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sub, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv sub ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sub + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sub ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sub + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sub sub ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sub + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sub, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv sub ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sub + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sub ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sub + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sub sub ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sub + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sub, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv sub ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sub + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sub ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sub + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv sub sub ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sub + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.trunc, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv ret ⚠️ DIFFERS + 1 mv + 2 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 3 instructions + GlobalISel-O0: 1 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv ret ⚠️ DIFFERS + 1 mv + 2 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 3 instructions + SelectionDAG-O0: 1 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv ret ret ⚠️ DIFFERS + 1 mv + 2 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 3 instructions + GlobalISel-O0: 1 instructions + SelectionDAG-O0: 1 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.udiv, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv divu ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 divu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv divu ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 divu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv divu divu ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 divu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.urem, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv divu ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 divu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv divu ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 divu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv divu divu ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 divu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.xor, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv xor ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 xor + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv xor ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 xor + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv xor xor ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 xor + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 5 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.zext, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv andi ⚠️ DIFFERS + 1 andi ret ⚠️ DIFFERS + 2 mv + 3 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 4 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv andi ⚠️ DIFFERS + 1 andi ret ⚠️ DIFFERS + 2 mv + 3 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 4 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv andi andi ⚠️ DIFFERS + 1 andi ret ret ⚠️ DIFFERS + 2 mv + 3 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 4 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.zext, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv andi ⚠️ DIFFERS + 1 andi ret ⚠️ DIFFERS + 2 mv + 3 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 4 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv andi ⚠️ DIFFERS + 1 andi ret ⚠️ DIFFERS + 2 mv + 3 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 4 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv andi andi ⚠️ DIFFERS + 1 andi ret ret ⚠️ DIFFERS + 2 mv + 3 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 4 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.zext, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 mv zext.h ⚠️ DIFFERS + 1 zext.h ret ⚠️ DIFFERS + 2 mv + 3 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 4 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv zext.h ⚠️ DIFFERS + 1 zext.h ret ⚠️ DIFFERS + 2 mv + 3 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 4 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 mv zext.h zext.h ⚠️ DIFFERS + 1 zext.h ret ret ⚠️ DIFFERS + 2 mv + 3 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 4 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.zext, Variant: 3 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR DIFFERS from GlobalISel-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 + -------------------------------------------------------------------------------- + 0 zext.w + 1 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 0 instructions + GlobalISel-O0: 2 instructions + + + ✗ LEANMLIR DIFFERS from SelectionDAG-O0 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 zext.w + 1 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 0 instructions + SelectionDAG-O0: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR GlobalISel-O0 SelectionDAG-O0 + -------------------------------------------------------------------------------- + 0 zext.w zext.w + 1 ret ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR: 0 instructions + GlobalISel-O0: 2 instructions + SelectionDAG-O0: 2 instructions + + +==================================================================================================== +COMPARISON 3: LEANMLIR_opt vs LLVM at O2 +==================================================================================================== + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.add, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv add ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 add + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv add ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 add + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv add add ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 add + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.add, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv add ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 add + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv add ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 add + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv add add ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 add + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.add, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv add ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 add + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv add ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 add + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv add add ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 add + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.and, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv and ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 and + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv and ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 and + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv and and ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 and + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.ashr, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv sra ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sra + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sra ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sra + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sra sra ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sra + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv sltu ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sltu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sltu ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sltu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sltu sltu ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sltu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv sltu ⚠️ DIFFERS + 1 mv xori ⚠️ DIFFERS + 2 sltu ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 6 instructions + GlobalISel-O2: 3 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sltu ⚠️ DIFFERS + 1 mv xori ⚠️ DIFFERS + 2 sltu ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 6 instructions + SelectionDAG-O2: 3 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sltu sltu ⚠️ DIFFERS + 1 mv xori xori ⚠️ DIFFERS + 2 sltu ret ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 6 instructions + GlobalISel-O2: 3 instructions + SelectionDAG-O2: 3 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv sltu ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sltu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sltu ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sltu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sltu sltu ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sltu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 3 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv sltu ⚠️ DIFFERS + 1 mv xori ⚠️ DIFFERS + 2 sltu ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 6 instructions + GlobalISel-O2: 3 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sltu ⚠️ DIFFERS + 1 mv xori ⚠️ DIFFERS + 2 sltu ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 6 instructions + SelectionDAG-O2: 3 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sltu sltu ⚠️ DIFFERS + 1 mv xori xori ⚠️ DIFFERS + 2 sltu ret ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 6 instructions + GlobalISel-O2: 3 instructions + SelectionDAG-O2: 3 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 4 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv slt ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 slt + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv slt ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 slt + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv slt slt ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 slt + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 5 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv slt ⚠️ DIFFERS + 1 mv xori ⚠️ DIFFERS + 2 slt ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 6 instructions + GlobalISel-O2: 3 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv slt ⚠️ DIFFERS + 1 mv xori ⚠️ DIFFERS + 2 slt ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 6 instructions + SelectionDAG-O2: 3 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv slt slt ⚠️ DIFFERS + 1 mv xori xori ⚠️ DIFFERS + 2 slt ret ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 6 instructions + GlobalISel-O2: 3 instructions + SelectionDAG-O2: 3 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 6 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv slt ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 slt + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv slt ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 slt + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv slt slt ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 slt + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 7 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv slt ⚠️ DIFFERS + 1 mv xori ⚠️ DIFFERS + 2 slt ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 6 instructions + GlobalISel-O2: 3 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv slt ⚠️ DIFFERS + 1 mv xori ⚠️ DIFFERS + 2 slt ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 6 instructions + SelectionDAG-O2: 3 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv slt slt ⚠️ DIFFERS + 1 mv xori xori ⚠️ DIFFERS + 2 slt ret ret ⚠️ DIFFERS + 3 xori + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 6 instructions + GlobalISel-O2: 3 instructions + SelectionDAG-O2: 3 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.icmp, Variant: 8 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv xor ⚠️ DIFFERS + 1 mv seqz ⚠️ DIFFERS + 2 xor ret ⚠️ DIFFERS + 3 seqz + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 6 instructions + GlobalISel-O2: 3 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv xor ⚠️ DIFFERS + 1 mv seqz ⚠️ DIFFERS + 2 xor ret ⚠️ DIFFERS + 3 seqz + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 6 instructions + SelectionDAG-O2: 3 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv xor xor ⚠️ DIFFERS + 1 mv seqz seqz ⚠️ DIFFERS + 2 xor ret ret ⚠️ DIFFERS + 3 seqz + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 6 instructions + GlobalISel-O2: 3 instructions + SelectionDAG-O2: 3 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.mul, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv mul ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 mul + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv mul ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 mul + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv mul mul ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 mul + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.mul, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv mul ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 mul + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv mul ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 mul + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv mul mul ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 mul + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.mul, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv mul ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 mul + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv mul ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 mul + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv mul mul ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 mul + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.or, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv or ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 or + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv or ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 or + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv or or ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 or + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.rem, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv rem ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 rem + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv rem ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 rem + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv rem rem ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 rem + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sdiv, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv div ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 div + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv div ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 div + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv div div ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 div + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.select, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv + 1 mv + 2 andi + 3 bnez + 4 mv + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 0 instructions + GlobalISel-O2: 6 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 andi + 1 mv + 2 bnez + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 0 instructions + SelectionDAG-O2: 5 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv andi ⚠️ DIFFERS + 1 mv mv + 2 andi bnez ⚠️ DIFFERS + 3 bnez mv ⚠️ DIFFERS + 4 mv ret ⚠️ DIFFERS + 5 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 0 instructions + GlobalISel-O2: 6 instructions + SelectionDAG-O2: 5 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sext, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 slli + 1 srai + 2 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 0 instructions + GlobalISel-O2: 3 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 slli + 1 srai + 2 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 0 instructions + SelectionDAG-O2: 3 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 slli slli + 1 srai srai + 2 ret ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 0 instructions + GlobalISel-O2: 3 instructions + SelectionDAG-O2: 3 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sext, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 sext.b + 1 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 0 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 sext.b + 1 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 0 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 sext.b sext.b + 1 ret ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 0 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sext, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 sext.h + 1 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 0 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 sext.h + 1 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 0 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 sext.h sext.h + 1 ret ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 0 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sext, Variant: 3 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 sext.w + 1 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 0 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 sext.w + 1 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 0 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 sext.w sext.w + 1 ret ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 0 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.shl, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv sll ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sll ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sll sll ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.shl, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv sll ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sll ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sll sll ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.shl, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv sll ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sll ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sll sll ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.shl, Variant: 3 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv sll ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sll ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sll sll ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sll + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.srl, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv srl ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 srl + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv srl ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 srl + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv srl srl ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 srl + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sub, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv sub ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sub + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sub ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sub + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sub sub ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sub + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sub, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv sub ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sub + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sub ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sub + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sub sub ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sub + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.sub, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv sub ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sub + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sub ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 sub + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv sub sub ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 sub + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.trunc, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv ret ⚠️ DIFFERS + 1 mv + 2 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 3 instructions + GlobalISel-O2: 1 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv ret ⚠️ DIFFERS + 1 mv + 2 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 3 instructions + SelectionDAG-O2: 1 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv ret ret ⚠️ DIFFERS + 1 mv + 2 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 3 instructions + GlobalISel-O2: 1 instructions + SelectionDAG-O2: 1 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.udiv, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv divu ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 divu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv divu ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 divu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv divu divu ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 divu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.urem, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv divu ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 divu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv divu ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 divu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv divu divu ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 divu + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.xor, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv xor ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 xor + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv xor ⚠️ DIFFERS + 1 mv ret ⚠️ DIFFERS + 2 xor + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv xor xor ⚠️ DIFFERS + 1 mv ret ret ⚠️ DIFFERS + 2 xor + 3 mv + 4 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 5 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.zext, Variant: 0 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv andi ⚠️ DIFFERS + 1 andi ret ⚠️ DIFFERS + 2 mv + 3 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 4 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv andi ⚠️ DIFFERS + 1 andi ret ⚠️ DIFFERS + 2 mv + 3 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 4 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv andi andi ⚠️ DIFFERS + 1 andi ret ret ⚠️ DIFFERS + 2 mv + 3 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 4 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.zext, Variant: 1 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv andi ⚠️ DIFFERS + 1 andi ret ⚠️ DIFFERS + 2 mv + 3 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 4 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv andi ⚠️ DIFFERS + 1 andi ret ⚠️ DIFFERS + 2 mv + 3 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 4 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv andi andi ⚠️ DIFFERS + 1 andi ret ret ⚠️ DIFFERS + 2 mv + 3 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 4 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.zext, Variant: 2 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 mv zext.h ⚠️ DIFFERS + 1 zext.h ret ⚠️ DIFFERS + 2 mv + 3 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 4 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv zext.h ⚠️ DIFFERS + 1 zext.h ret ⚠️ DIFFERS + 2 mv + 3 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 4 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 mv zext.h zext.h ⚠️ DIFFERS + 1 zext.h ret ret ⚠️ DIFFERS + 2 mv + 3 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 4 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +──────────────────────────────────────────────────────────────────────────────────────────────────── +Operation: llvm.zext, Variant: 3 +──────────────────────────────────────────────────────────────────────────────────────────────────── + + ✗ LEANMLIR_opt DIFFERS from GlobalISel-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 + -------------------------------------------------------------------------------- + 0 zext.w + 1 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 0 instructions + GlobalISel-O2: 2 instructions + + + ✗ LEANMLIR_opt DIFFERS from SelectionDAG-O2 + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 zext.w + 1 ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 0 instructions + SelectionDAG-O2: 2 instructions + + + Comprehensive comparison of all three: + + Instruction-by-instruction comparison: + -------------------------------------------------------------------------------- + Index LEANMLIR_opt GlobalISel-O2 SelectionDAG-O2 + -------------------------------------------------------------------------------- + 0 zext.w zext.w + 1 ret ret + -------------------------------------------------------------------------------- + + Summary: + LEANMLIR_opt: 0 instructions + GlobalISel-O2: 2 instructions + SelectionDAG-O2: 2 instructions + + +==================================================================================================== +END OF ALL COMPARISONS +==================================================================================================== + diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_add.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_add.mlir new file mode 100644 index 0000000000..167eda5101 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_add.mlir @@ -0,0 +1,21 @@ +// llvm.add +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.add %arg0, %arg1 overflow : i64 + return %0 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.add %arg0, %arg1 overflow : i64 + return %0 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.add %arg0, %arg1 overflow : i64 + return %0 : i64 + } +} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_and.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_and.mlir new file mode 100644 index 0000000000..3b9428b43d --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_and.mlir @@ -0,0 +1,7 @@ +// llvm.and +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.and %arg0, %arg1 : i64 + return %0 : i64 + } +} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_ashr.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_ashr.mlir new file mode 100644 index 0000000000..e8441f4a41 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_ashr.mlir @@ -0,0 +1,7 @@ +// llvm.ashr +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.ashr %arg0, %arg1 : i64 + return %0 : i64 + } +} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_icmp.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_icmp.mlir new file mode 100644 index 0000000000..5482fce1b1 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_icmp.mlir @@ -0,0 +1,70 @@ +// llvm.icmp +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.icmp "ugt" %arg0, %arg1 : i64 + return %0 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.icmp "uge" %arg0, %arg1 : i64 + return %0 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.icmp "ult" %arg0, %arg1 : i64 + return %0 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.icmp "ule" %arg0, %arg1 : i64 + return %0 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.icmp "sgt" %arg0, %arg1 : i64 + return %0 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.icmp "sge" %arg0, %arg1 : i64 + return %0 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.icmp "slt" %arg0, %arg1 : i64 + return %0 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.icmp "sle" %arg0, %arg1 : i64 + return %0 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.icmp "eq" %arg0, %arg1 : i64 + return %0 : i1 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i1 { + %0 = llvm.icmp "neq" %arg0, %arg1 : i64 + return %0 : i1 + } +} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_mul.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_mul.mlir new file mode 100644 index 0000000000..1efd7b2fcd --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_mul.mlir @@ -0,0 +1,21 @@ +// llvm.mul +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.mul %arg0, %arg1 overflow : i64 + return %0 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.mul %arg0, %arg1 overflow : i64 + return %0 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.mul %arg0, %arg1 overflow : i64 + return %0 : i64 + } +} diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_or.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_or.mlir new file mode 100644 index 0000000000..13162159f4 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_or.mlir @@ -0,0 +1,7 @@ +// llvm.or +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.or %arg0, %arg1 : i64 + return %0 : i64 + } +} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_rem.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_rem.mlir new file mode 100644 index 0000000000..1f070de0ef --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_rem.mlir @@ -0,0 +1,7 @@ +// llvm.rem +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.srem %arg0, %arg1 : i64 + return %0 : i64 + } +} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sdiv.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sdiv.mlir new file mode 100644 index 0000000000..af5f06d6da --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sdiv.mlir @@ -0,0 +1,7 @@ +// llvm.sdiv +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.sdiv %arg0, %arg1 : i64 + return %0 : i64 + } +} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_select.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_select.mlir new file mode 100644 index 0000000000..1e15a4102e --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_select.mlir @@ -0,0 +1,7 @@ +// llvm.select +module { + func.func @main(%cond : i1, %arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.select %cond, %arg0, %arg1 : i1, i64 + return %0 : i64 + } +} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sext.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sext.mlir new file mode 100644 index 0000000000..b6f36b0426 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sext.mlir @@ -0,0 +1,28 @@ +// llvm.sext +module { + func.func @main(%arg0: i1) -> i64 { + %0 = llvm.sext %arg0 : i1 to i64 + return %0 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i8) -> i64 { + %0 = llvm.sext %arg0 : i8 to i64 + return %0 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i16) -> i64 { + %0 = llvm.sext %arg0 : i16 to i64 + return %0 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i32) -> i64 { + %0 = llvm.sext %arg0 : i32 to i64 + return %0 : i64 + } +} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_shl.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_shl.mlir new file mode 100644 index 0000000000..ec86a8d33f --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_shl.mlir @@ -0,0 +1,28 @@ +// llvm.shl +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.shl %arg0, %arg1 : i64 + return %0 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.shl %arg0, %arg1 overflow : i64 + return %0 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.shl %arg0, %arg1 overflow : i64 + return %0 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.shl %arg0, %arg1 overflow : i64 + return %0 : i64 + } +} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_srl.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_srl.mlir new file mode 100644 index 0000000000..3187cfa691 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_srl.mlir @@ -0,0 +1,7 @@ +// llvm.srl +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.lshr %arg0, %arg1 : i64 + return %0 : i64 + } +} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sub.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sub.mlir new file mode 100644 index 0000000000..6f600d13ad --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_sub.mlir @@ -0,0 +1,21 @@ +// llvm.sub +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.sub %arg0, %arg1 overflow : i64 + return %0 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.sub %arg0, %arg1 overflow : i64 + return %0 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.sub %arg0, %arg1 overflow : i64 + return %0 : i64 + } +} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_trunc.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_trunc.mlir new file mode 100644 index 0000000000..dc6700695a --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_trunc.mlir @@ -0,0 +1,7 @@ +// llvm.trunc +module { + func.func @main(%arg0: i64) -> i32 { + %0 = llvm.trunc %arg0 : i64 to i32 + return %0 : i32 + } +} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_udiv.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_udiv.mlir new file mode 100644 index 0000000000..445b47437a --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_udiv.mlir @@ -0,0 +1,7 @@ +// llvm.udiv +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.udiv %arg0, %arg1 : i64 + return %0 : i64 + } +} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_urem.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_urem.mlir new file mode 100644 index 0000000000..7f61c56d54 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_urem.mlir @@ -0,0 +1,7 @@ +// llvm.urem +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.udiv %arg0, %arg1 : i64 + return %0 : i64 + } +} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_xor.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_xor.mlir new file mode 100644 index 0000000000..c3586dfd71 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_xor.mlir @@ -0,0 +1,7 @@ +// llvm.xor +module { + func.func @main(%arg0: i64, %arg1: i64) -> i64 { + %0 = llvm.xor %arg0, %arg1 : i64 + return %0 : i64 + } +} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_zext.mlir b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_zext.mlir new file mode 100644 index 0000000000..e8127afbce --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/isolated_instructions/llvm_zext.mlir @@ -0,0 +1,28 @@ +// llvm.zext +module { + func.func @main(%arg0: i1) -> i64 { + %0 = llvm.zext %arg0 : i1 to i64 + return %0 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i8) -> i64 { + %0 = llvm.zext %arg0 : i8 to i64 + return %0 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i16) -> i64 { + %0 = llvm.zext %arg0 : i16 to i64 + return %0 : i64 + } +} +// ----- +module { + func.func @main(%arg0: i32) -> i64 { + %0 = llvm.zext %arg0 : i32 to i64 + return %0 : i64 + } +} \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/run_comparison.sh b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/run_comparison.sh new file mode 100755 index 0000000000..8373001af5 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/compare-lowering-patterns/run_comparison.sh @@ -0,0 +1,5 @@ +#! /bin/bash +export PYTHONPATH=$PYTHONPATH:~/lean-mlir +python3 ../benchmarks/generate.py --num 10 --jobs 30 --llvm_opt all -l +python3 ../mca-analysis/run_mca.py +python3 compare_lowerings.py \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/.python-version b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/.python-version new file mode 100644 index 0000000000..24ee5b1be9 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/README.md b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/README.md new file mode 100644 index 0000000000..b2b13cd670 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/README.md @@ -0,0 +1,42 @@ + +# MCA Analysis + +## Dependencies + +This evaluation requires `llvm-mca`, either install it through your favourite +package manager, or, if you've built LLVM from source, add the `bin` directory +to your path. + +For example, if you've built LLVM at `~/llvm-project/build`, and you run bash as +your shell, you should run the following before you run the script: + +```bash +export PATH=$PATH:~/llvm-project/build/bin/ +``` + +To make sure that `evallib` is correctly imported, run: + +```bash +export PYTHONPATH=$PYTHONPATH:~/lean-mlir +``` + +## How to run + +To reproduce the mca analysis results, run: +``` +python3 run_mca.py +``` + + +This file will run LLVM's `llvm-mca` tool on the RISCV assembly files produced by LLVM with `globalISel`, LLVM with `selectionDAG`, Lean-MLIR + XDSL and Lean-MLIR with optimizations + XDSL using the following command: + +``` +llvm-mca -mtriple=riscv64 -mcpu=sifive-u74 -mattr=+m,+zba,+zbb,+zbs $input_file +``` + +The results of the analysis and the log of the tool are available in `results/`. + +To reproduce the plots, run +``` +python3 plot.py +``` \ No newline at end of file diff --git a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/plot.py b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/plot.py new file mode 100755 index 0000000000..bb3e0007c9 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/plot.py @@ -0,0 +1,1043 @@ +#!/usr/bin/env python3 + +import subprocess +import os +import argparse +import shutil +import pandas as pd +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +import math +from num2words import num2words + +matplotlib.rcParams["pdf.fonttype"] = 42 +matplotlib.rcParams["font.size"] = 20 + + +matplotlib.rcParams["figure.autolayout"] = True +matplotlib.rcParams["legend.frameon"] = False +matplotlib.rcParams["axes.spines.right"] = False +matplotlib.rcParams["axes.spines.top"] = False + +# matplotlib.rcParams['figure.figsize'] = 5, 2 + +light_gray = "#cacaca" +dark_gray = "#827b7b" +light_blue = "#a6cee3" +dark_blue = "#1f78b4" +light_green = "#b2df8a" +dark_green = "#33a02c" +light_red = "#fb9a99" +dark_red = "#e31a1c" +black = "#000000" +white = "#ffffff" + +colors_list = [ + light_gray, + dark_gray, + light_blue, + dark_blue, + light_green, + dark_green, + light_red, + dark_red, + black, + white, +] + +ROOT_DIR_PATH = ( + subprocess.check_output(["git", "rev-parse", "--show-toplevel"]) + .decode("utf-8") + .strip() +) + +LLVMIR_DIR_PATH = ( + f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LLVMIR/" +) + +LLVM_globalisel_results_DIR_PATH = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LLVM_globalisel/" +LLVM_selectiondag_results_DIR_PATH = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LLVM_selectiondag/" +LEANMLIR_results_DIR_PATH = ( + f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LEANMLIR/" +) +LEANMLIR_opt_results_DIR_PATH = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LEANMLIR_opt/" + +tables_dir = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/tables/" +data_dir = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/data/" +plots_dir = f"{ROOT_DIR_PATH}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/plots/" + + +def setup_benchmarking_directories(): + """ + Create clean directories to store the benchmarks. + """ + if not os.path.exists(data_dir): + os.makedirs(data_dir) + else: + shutil.rmtree(data_dir) + os.makedirs(data_dir) + + if not os.path.exists(plots_dir): + os.makedirs(plots_dir) + else: + shutil.rmtree(plots_dir) + os.makedirs(plots_dir) + + +parameters_match = { + "tot_instructions": "Instructions: ", + "tot_cycles": "Total Cycles: ", + "tot_uops": "Total uOps: ", + "similarity": "Instructions List: ", +} + +parameters_labels = { + "tot_instructions": "#Instructions", + "tot_cycles": "#Cycles", + "tot_uops": "#uOps", + "similarity": "Instructions List:", +} + +selector_labels = { + "LEANMLIR_opt": "Lean-MLIRISel", + "LLVM_globalisel_O1": "GlobalISel (O1)", + "LLVM_globalisel_O2": "GlobalISel (O2)", + "LLVM_globalisel_O3": "GlobalISel (O3)", + "LLVM_globalisel": "GlobalISel", + "LLVM_selectiondag_O1": "SelectionDAG (O1)", + "LLVM_selectiondag_O2": "SelectionDAG (O2)", + "LLVM_selectiondag_O3": "SelectionDAG (O3)", + "LLVM_selectiondag": "SelectionDAG", +} + + +def parse_instructions(filename): + instructions = [] + in_instruction_section = False + + with open(filename, "r") as f: + for line in f: + if ( + "[0] [1] [2] [3] [4] [5] [6] [7] Instructions:" + in line + ): + in_instruction_section = True + continue + + if in_instruction_section and line.strip(): + parts = line.split() + instruction = parts[8:] # inst name is in 9th column + instructions.append(instruction) + if len(instructions) == 0: + return None + return instructions + + +def extract_data(results_directory, benchmark_name, parameter): + """ + Parses the results of mca and saves the result in a DataFrame, then printed to `.csv` + """ + function_names = [] + parameter_numbers = [] + for filename in os.listdir(results_directory): + file_path = os.path.join(results_directory, filename) + try: + if parameter == "similarity": + with open(file_path, "r") as f: + file_lines = f.readlines() + instructions = parse_instructions(file_path) + if instructions is not None: + parameter_numbers.append(instructions) + function_names.append(filename.split(".")[0]) + else: + with open(file_path, "r") as f: + file_lines = f.readlines() + for line in file_lines: + if parameters_match[parameter] in line: + function_names.append(filename.split(".")[0]) + num = int(line.split(" ")[-1]) + if parameter == "tot_cycles": + parameter_numbers.append(int(num)) + else: + parameter_numbers.append(int(num / 100)) + except FileNotFoundError: + print(f"Warning: file not found at {file_path}. Skipping.") + df = pd.DataFrame( + { + "function_name": function_names, + benchmark_name + "_" + parameter: parameter_numbers, + } + ) + df.to_csv(data_dir + benchmark_name + "_" + parameter + ".csv") + + +def join_dataframes(dataframe_names, parameter): + """ + Joins multiple DataFrames on a common 'function_name' column. + """ + for idx, name in enumerate(dataframe_names): + df = pd.read_csv( + data_dir + name + "_" + parameter + ".csv", index_col=0, header=0 + ) + if idx == 0: + complete_df = df + else: + complete_df = pd.merge(complete_df, df, on="function_name", how="inner") + complete_df["instructions_number"] = complete_df["function_name"].apply( + lambda x: int(x.split("_")[0]) + ) + if parameter == "similarity": + complete_df["is_eqv_LLVM_globalisel"] = complete_df["LLVM_globalisel_" + parameter] == complete_df["LEANMLIR_opt_" + parameter] + complete_df["is_eqv_LLVM_selectiondag"] = complete_df["LLVM_selectiondag_" + parameter] == complete_df["LEANMLIR_opt_" + parameter] + # drop LLVM_globalisel_similarity and LLVM_selectiondag_similarity columns + complete_df = complete_df.drop( + ["LLVM_globalisel_" + parameter, "LLVM_selectiondag_" + parameter, "LEANMLIR_opt_" + parameter], axis=1 + ) + complete_df.to_csv(data_dir + parameter + ".csv") + + +def sorted_line_plot_all(parameter): + df = pd.read_csv(data_dir + parameter + ".csv") + + sorted_df = df.sort_values( + by=[ + "LEANMLIR_opt_" + parameter, + "LLVM_globalisel_" + parameter, + "LLVM_selectiondag_" + parameter, + ] + ) + + plt.plot( + range(len(sorted_df)), + sorted_df["LEANMLIR_opt_" + parameter], + label=selector_labels["LEANMLIR_opt"], + color=dark_green, + ) + plt.plot( + range(len(sorted_df)), + sorted_df["LLVM_globalisel_" + parameter], + label=selector_labels["LLVM_globalisel"], + color=light_blue, + ) + plt.plot( + range(len(sorted_df)), + sorted_df["LLVM_selectiondag_" + parameter], + label=selector_labels["LLVM_selectiondag"], + color=light_red, + ) + plot_max = ( + np.max( + [ + sorted_df["LEANMLIR_opt_" + parameter].min(), + sorted_df["LLVM_globalisel_" + parameter].min(), + sorted_df["LLVM_selectiondag_" + parameter].min(), + ] + ) + + 1 + ) + + plt.ylim(1, int(plot_max * 1.5) + 1) + plt.yticks(range(1, int(plot_max * 1.5) + 1, int((int(plot_max * 1.5) + 5) / 5))) + + plt.xlabel("Program Index") + plt.ylabel(parameter) + plt.figure(figsize=(10, 5)) + + # plt.title(f'{parameter} Per Program') + + plt.legend(ncols=2) + plt.tight_layout() + + pdf_filename = plots_dir + parameter + "_line.pdf" + plt.savefig(pdf_filename) + # print(f"\nPlot saved to '{pdf_filename}' in the current working directory.") + plt.close() + + +def scatter_plot(parameter, selector1, selector2): + df = pd.read_csv(data_dir + parameter + ".csv") + + if selector1 + "_" + parameter not in df.columns: + print(f"Error: the column {selector1} does not exist in the dataframe.") + return + if selector2 + "_" + parameter not in df.columns: + print(f"Error: the column {selector2} does not exist in the dataframe.") + + df_plot_comparison = df[ + [selector1 + "_" + parameter, selector2 + "_" + parameter] + ].dropna() + + frequencies = ( + df_plot_comparison.groupby( + [selector1 + "_" + parameter, selector2 + "_" + parameter] + ) + .size() + .reset_index(name="Frequency") + ) + df_plot_scaled = pd.merge( + df_plot_comparison, + frequencies, + on=[selector1 + "_" + parameter, selector2 + "_" + parameter], + how="left", + ) + + df_plot_scaled["Scaled_Size"] = np.sqrt((df_plot_scaled["Frequency"])) * 50 + 20 + + + plt.scatter( + df_plot_scaled[selector1 + "_" + parameter], + df_plot_scaled[selector2 + "_" + parameter], + s=df_plot_scaled["Scaled_Size"], + color=light_blue, + alpha=0.7, + edgecolors="w", + label="Function data points (Size by frequency)", + ) + + min_val = min( + df_plot_comparison[selector1 + "_" + parameter].min(), + df_plot_comparison[selector2 + "_" + parameter].min(), + ) + max_val = max( + df_plot_comparison[selector1 + "_" + parameter].max(), + df_plot_comparison[selector2 + "_" + parameter].max(), + ) + # Add a small buffer to the min/max values for better visualization + plot_min = max(0, min_val - 1) + plot_max = max_val + 1 + + plt.plot( + [plot_min, plot_max], + [plot_min, plot_max], + color="gray", + linestyle="--", + label="$x=y$ line", + ) + + plt.xlabel(selector_labels[selector1] + " - " + parameters_labels[parameter]) + plt.ylabel(selector_labels[selector2] + " - " + parameters_labels[parameter]) + + if ( + not (plot_min == plot_max) + and (0 < int(plot_min / 5)) + and (0 < int(plot_max / 5)) + ): + plt.xlim(plot_min, plot_max) + plt.ylim(plot_min, plot_max) + + plt.xticks(range(0, int(plot_max), int((plot_max) / 5))) + plt.yticks(range(0, int(plot_max), int((plot_max) / 5))) + + plt.gca().set_aspect("equal", adjustable="box") + + plt.tight_layout() + + pdf_filename = ( + plots_dir + f"{parameter}_scatter_plot_{selector1}_vs_{selector2}.pdf" + ) + plt.savefig(pdf_filename, bbox_inches='tight') + # print(f"\nScatter plot saved to '{pdf_filename}' in the current working directory.") + plt.close() + +def bar_plot(parameter, selector1, selector2): + df = pd.read_csv(data_dir + parameter + ".csv") + + col1 = selector1 + "_" + parameter + col2 = selector2 + "_" + parameter + + if col1 not in df.columns: + print(f"Error: the column {col1} does not exist in the dataframe.") + return + if col2 not in df.columns: + print(f"Error: the column {col2} does not exist in the dataframe.") + return + + # Compute the difference + df["diff"] = df[col1] / df[col2] + + # Classify the differences + def classify(diff): + if diff < 1: + return "<1x" + elif diff == 1: + return "1x" + elif diff < 1.5: + return "1x-1.5x" + elif diff < 2: + return "1.5x-2x" + else: + return ">2x" + + df["diff_class"] = df["diff"].apply(classify) + + df.to_csv(data_dir + parameter + f"_{selector1}_vs_{selector2}_classified.csv") + + # For each unique value of the initial `instructions_number`, compute the % of each diff_class + group = ( + df.groupby("instructions_number")["diff_class"] + .value_counts(normalize=True) + .unstack(fill_value=0) + * 100 + ) + + # Ensure all classes are present for consistent coloring/order + class_order = ["<1x", "1x", "1x-1.5x", "1.5x-2x", ">2x"] + + # for c in class_order: + # if c not in group.columns: + # group[c] = 0 + group = group[class_order] + + # Colors for each class + class_colors = { + "<1x": light_blue, + "1x": dark_green, + "1x-1.5x": light_green, + "1.5x-2x": light_red, + ">2x": dark_red, + } + + similarity_df = pd.read_csv(data_dir + "similarity.csv") + similarity_percentages = {} + col_name = f"is_eqv_{selector2}" + for instr_num, group_df in similarity_df.groupby("instructions_number"): + total_count = len(group_df) + true_count = group_df[col_name].sum() + percentage = (true_count / total_count) * 100 if total_count > 0 else 0.0 + similarity_percentages[int(instr_num)] = percentage + + + def plot_columns(with_similarity=False): + bottom = np.zeros(len(group)) + similarity_df = pd.read_csv(data_dir + "similarity.csv") + similarity_df_grouped = similarity_df.groupby("instructions_number") + x = group.index.astype(str) + plt.figure(figsize=(10, 5)) + for c in class_order: + if c == "1x" and with_similarity: + similarity_list = list(similarity_percentages.values()) + remaining = [a - b for a, b in zip(group[c], similarity_list)] + plt.bar( + x, similarity_list, bottom=bottom, color=class_colors[c], hatch="//" + ) + bottom += similarity_list + plt.bar( + x, remaining, bottom=bottom, label=f"{c}", color=class_colors[c] + ) + bottom += remaining + else: + plt.bar(x, group[c], bottom=bottom, label=f"{c}", color=class_colors[c]) + bottom += group[c].values + + plt.xlabel("#instructions - LLVM IR") + plt.ylabel( + "%Programs", rotation="horizontal", horizontalalignment="left", y=1.05 + ) + plt.legend(ncols=5, bbox_to_anchor=(0.5, -0.5), loc="lower center") + plt.subplots_adjust(bottom=0.4) + plt.tight_layout() + + name_extension = "_similarity_" if with_similarity else "_" + pdf_filename = ( + plots_dir + + f"{parameter}_stacked_bar{name_extension}{selector1}_vs_{selector2}.pdf" + ) + plt.savefig(pdf_filename) + # print( + # f"\nStacked bar plot saved to '{pdf_filename}' in the current working directory." + # ) + plt.close() + + plot_columns() + if parameter == "tot_instructions": + plot_columns(with_similarity=True) + + +def violin_plot(parameter, selector1, selector2): + df = pd.read_csv(data_dir + parameter + ".csv") + + col1 = selector1 + "_" + parameter + col2 = selector2 + "_" + parameter + + if col1 not in df.columns: + print(f"Error: the column {col1} does not exist in the dataframe.") + return + if col2 not in df.columns: + print(f"Error: the column {col2} does not exist in the dataframe.") + return + + df["ratio"] = df[col1] / df[col2] + + num_above_50 = sum(df["ratio"] > 50) + + print(f"Number of programs with ratio above 50: {num_above_50} out of {len(df)}") + + # extract the columns with ratio > 50 + + high_ratio_df =( df[df["ratio"] > 50]).groupby("instructions_number") + for instr_num, group in high_ratio_df: + print(f"LLVM #Instructions: {instr_num}, #programs with ratio > 50 : {len(group)}") + + # remove points above 50 for y-axis scaling + + grouped = df.groupby("instructions_number")["ratio"].apply(list).reset_index() + + violin_data = grouped["ratio"].values + positions = grouped["instructions_number"].values + + + plt.figure(figsize=(10, 5)) + parts = plt.violinplot( + violin_data, + positions, + showmedians=True + ) + + for pc in parts["bodies"]: + pc.set_facecolor(light_green) + pc.set_edgecolor(light_green) + pc.set_alpha(1.0) + + plt.axhline(1, color=black, linestyle="--", linewidth=1, label="1x") + plt.text(positions[-1]*1.08, 1.02, "1x", color=black, ha='center', fontsize=20) + + for partname in ('cbars', 'cmins', 'cmaxes'): + if partname in parts: + parts[partname].set_edgecolor(light_gray) + parts[partname].set_linewidth(1) + parts['cmedians'].set_edgecolor(dark_green) + + plt.xlabel(f"#Instructions - LLVM IR") + plt.ylabel( + f"$\\frac{{\\text{{{parameters_labels[parameter]}{selector_labels[selector1]}}}}}{{\\text{{{parameters_labels[parameter]}{selector_labels[selector2]}}}}}$", + fontsize = 26, + rotation="horizontal", horizontalalignment="left", y=1.05 + ) + + # add a marker at the top of every column indicating the number of outliers removed + + max_ratio = df["ratio"].max() + + print(f"Max ratio for {parameter} between {selector1} and {selector2} is {max_ratio}") + + + if max_ratio > 200: + plt.yticks(np.arange(0, 270, 50)) + else: + plt.yticks(np.arange(0, math.ceil(df["ratio"].max()) + 2, 2)) + + plt.tight_layout() + + pdf_filename = ( + plots_dir + f"{parameter}_violin_{selector1}_vs_{selector2}.pdf" + ) + plt.savefig(pdf_filename) + # print(f"\nViolin plot saved to '{pdf_filename}' in the current working directory.") + plt.close() + + +def sorted_line_plot(parameter, selector1, selector2): + df = pd.read_csv(data_dir + parameter + ".csv") + + sorted_df = df.sort_values( + by=[selector1 + "_" + parameter, selector2 + "_" + parameter] + ) + plt.figure(figsize=(12, 5)) + + plt.plot( + range(len(sorted_df)), + sorted_df[selector1 + "_" + parameter], + label=selector_labels[selector1], + color=light_green, + ) + plt.plot( + range(len(sorted_df)), + sorted_df[selector2 + "_" + parameter], + label=selector_labels[selector2], + color=dark_green, + ) + + plt.xlabel("Program Index") + plt.ylabel( + parameters_labels[parameter], + rotation="horizontal", + horizontalalignment="left", + y=1, + ) + # plt.title(f'{parameters_labels[parameter]} Per Program, {selector1} vs. {selector2}') + # plt.yticks(range(int(plot_min), int(plot_max + 1), 1)) + plt.legend() + plt.tight_layout() + + pdf_filename = plots_dir + parameter + f"_{selector1}_vs_{selector2}_line.pdf" + plt.savefig(pdf_filename, bbox_inches='tight') + # print(f"\nPlot saved to '{pdf_filename}' in the current working directory.") + plt.close() + + avg_diff = ( + sorted_df[selector1 + "_" + parameter] - sorted_df[selector2 + "_" + parameter] + ).mean() + # Clean names for LaTeX command + + + +def overhead_plot(parameter, selector1, selector2): + """ + Plots the overhead of employing `selector1` against `selector2` + """ + df = pd.read_csv(data_dir + parameter + ".csv") + + sorted_df = df.sort_values( + by=[selector1 + "_" + parameter, selector2 + "_" + parameter], + ascending=[True, True], + ) + plt.figure(figsize=(10, 5)) + + if 0 < len(sorted_df): + plt.stackplot( + range(0, len(sorted_df)), + sorted_df[selector1 + "_" + parameter], + labels=[selector_labels[selector1]], + color=light_green, + ) + plt.stackplot( + range(0, len(sorted_df)), + sorted_df[selector2 + "_" + parameter], + labels=[selector_labels[selector2]], + color=white, + edgecolor=light_red, + ) + + plt.xlabel("Program Index") + plt.ylabel( + parameters_labels[parameter], + rotation="horizontal", + horizontalalignment="left", + y=1, + ) + plt.xticks(range(0, len(sorted_df), int(np.ceil(len(sorted_df) / 5)))) + plt.legend() + plt.tight_layout() + + pdf_filename = ( + plots_dir + f"{parameter}_overhead_{selector1}_vs_{selector2}.pdf" + ) + plt.savefig(pdf_filename, bbox_inches='tight') + # print(f"\nPlot saved to '{pdf_filename}' in the current working directory.") + plt.close() + +def geomean_plot_tot_cycles(): + parameters = ("#cycles", "#instructions") + # tot_cycles + df_cycles = pd.read_csv(data_dir + "tot_cycles.csv") + plt.figure(figsize=(6, 5)) + df_cycles['ratio_gisel'] = df_cycles['LEANMLIR_opt_tot_cycles'] / df_cycles['LLVM_globalisel_tot_cycles'] + df_cycles['ratio_sdag'] = df_cycles['LEANMLIR_opt_tot_cycles'] / df_cycles['LLVM_selectiondag_tot_cycles'] + geomean_gisel_cycles = np.exp(np.mean(np.log(df_cycles["ratio_gisel"]))) + geomean_sdag_cycles = np.exp(np.mean(np.log(df_cycles["ratio_sdag"]))) + #tot_instructions + df_instructions = pd.read_csv(data_dir + "tot_instructions.csv") + df_instructions['ratio_gisel'] = df_instructions['LEANMLIR_opt_tot_instructions'] / df_instructions['LLVM_globalisel_tot_instructions'] + df_instructions['ratio_sdag'] = df_instructions['LEANMLIR_opt_tot_instructions'] / df_instructions['LLVM_selectiondag_tot_instructions'] + geomean_gisel_instructions = np.exp(np.mean(np.log(df_instructions["ratio_gisel"]))) + geomean_sdag_instructions= np.exp(np.mean(np.log(df_instructions["ratio_sdag"]))) + geomeans_gisel = [geomean_gisel_instructions, geomean_gisel_cycles] + geomeans_sdag = [geomean_sdag_instructions, geomean_sdag_cycles] + + x = np.arange(len(parameters)) + width = 0.35 + + plt.bar(x - width/2, geomeans_gisel, width, label=selector_labels["LLVM_globalisel"], color=light_blue) + plt.bar(x + width/2, geomeans_sdag, width, label=selector_labels["LLVM_selectiondag"], color=light_red) + plt.axhline(1, color=black, linestyle="--", linewidth=2) + + plt.ylabel( + 'Geomean Ratio', + rotation="horizontal", + horizontalalignment="left", + y=1, + ) + plt.xticks(x, parameters) + plt.legend() + plt.tight_layout() + + pdf_filename = plots_dir + "geomean_comparison.pdf" + plt.savefig(pdf_filename) + print(f"\nGeometric mean plot saved to '{pdf_filename}' in the current working directory.") + plt.close() + + +def equivalent_plot_perc(): + df_similarity = (pd.read_csv(data_dir + "similarity.csv")) + + df_eqv_gisel = ( + df_similarity.groupby("instructions_number")["is_eqv_LLVM_globalisel"] + .value_counts(normalize=True) + .unstack(fill_value=0) + * 100 + ) + + df_eqv_sdag = ( + df_similarity.groupby("instructions_number")["is_eqv_LLVM_selectiondag"] + .value_counts(normalize=True) + .unstack(fill_value=0) + * 100 + ) + plt.figure(figsize=(7, 5)) + + width = 0.4 + + plt.bar((df_eqv_gisel.index) - width/2, (df_eqv_gisel[True]).to_list(), width, label=selector_labels["LLVM_globalisel"], color=light_blue) + plt.bar((df_eqv_gisel.index) + width/2, (df_eqv_sdag[True]).to_list(), width, label=selector_labels["LLVM_selectiondag"], color=light_red) + + plt.ylabel( + '% Identical Outputs', + rotation="horizontal", + horizontalalignment="left", + y=1.05, + ) + plt.xlabel("#Instructions - LLVM IR") + + plt.legend() + plt.tight_layout() + + pdf_filename = plots_dir + "equivalent_outputs.pdf" + plt.savefig(pdf_filename) + print(f"\nGeometric mean plot saved to '{pdf_filename}' in the current working directory.") + plt.close() + + +def proportional_bar_plot(parameter, selector1, selector2): + df = pd.read_csv(data_dir + parameter + ".csv") + + plt.figure(figsize=(7, 5)) + + col1 = selector1 + "_" + parameter + col2 = selector2 + "_" + parameter + + if col1 not in df.columns or col2 not in df.columns: + print( + f"Error: One or both columns ({col1}, {col2}) do not exist in the dataframe." + ) + return + + df['ratios'] = df[col1] / df[col2] + + average_ratios_by_instruction = ( + df.groupby('instructions_number')['ratios'] + .apply(lambda x: np.exp(np.log(x).mean())) + .reset_index(name='average_ratio') + ) + + print(selector2) + print(parameter) + print(max(df['ratios'])) + + + width = 0.8 + + plt.bar( + average_ratios_by_instruction["instructions_number"], + average_ratios_by_instruction["average_ratio"], + color=light_green, + width=width, + label=f"Avg. {parameters_labels[parameter]},$\\frac{{\\text{{{selector_labels[selector1]}}}}}{{\\text{{{selector_labels[selector2]}}}}}$" + ) + + plt.axhline(1, color=black, linestyle="--", linewidth=2) + + + + plt.xlabel("#Instructions - LLVM IR") + + plt.ylabel( + f"$\\frac{{\\text{{{parameters_labels[parameter]},{selector_labels[selector1]}}}}}{{\\text{{{parameters_labels[parameter]}{selector_labels[selector2]}}}}}$", + fontsize=26, + rotation="horizontal", horizontalalignment="left", y=1.08 + ) + + # if max(average_ratios_by_instruction["average_ratio"]) < 10: + # plt.yticks(np.arange(0, math.ceil(max(average_ratios_by_instruction["average_ratio"])+1), 0.5)) + # else : + # plt.yticks(np.arange(0, math.ceil(max(average_ratios_by_instruction["average_ratio"])+1), 100)) + if (selector2 == "LLVM_globalisel") and (parameter == "tot_instructions"): + plt.yticks(np.arange(0, 2, 0.5)) + plt.text((((average_ratios_by_instruction["instructions_number"]).to_list())[-1])*1.15, 0.95, f"GISel", color=black, ha='center', fontsize=20) + elif (selector2 == "LLVM_selectiondag") and (parameter == "tot_instructions"): + plt.yticks(np.arange(0, 3, 1)) + plt.text((((average_ratios_by_instruction["instructions_number"]).to_list())[-1])*1.15, 0.95, f"SDAG", color=black, ha='center', fontsize=20) + + + plt.xticks(np.arange(3, 9, 1)) + + plt.tight_layout() + + # uncomment to have numbers on top of the bars + # for bar in bars: + # height = bar.get_height() + # plt.text(bar.get_x() + bar.get_width()/2., height, + # f'{height:.2f}', + # ha='center', va='bottom') + + pdf_filename = ( + plots_dir + f"{parameter}_proportional_bar_{selector1}_vs_{selector2}.pdf" + ) + plt.savefig(pdf_filename) + print( + f"\nProportional bar plot saved to '{pdf_filename}' in the current working directory." + ) + plt.close() + + + + +def create_latex_command(parameters, filename): + f = open(filename, 'w') + + git_command = ["git", "rev-parse", "--short", "HEAD"] + result = subprocess.run( + git_command, cwd=ROOT_DIR_PATH, capture_output=True, text=True, check=True + ) + + commit_hash = result.stdout.strip() + + f.write(f"% Lean-mlir commit hash: {commit_hash}\n") + + f.write(f"% In the following commands the following rules apply:\n") + f.write(f"% A: class <1x\n") + f.write(f"% B: class 1x\n") + f.write(f"% C: class 1x-1.5x\n") + f.write(f"% D: class 1.5x-2x\n") + f.write(f"% E: class >2x\n") + f.write('\n\n') + + # print the percentage of programs in each of the above classes, for each number of instructions + for p in parameters: + df = pd.read_csv(data_dir + p + ".csv") + + df['ratios_gisel'] = df['LEANMLIR_opt_' + p] / df['LLVM_globalisel_' + p] + df['ratios_sdag'] = df['LEANMLIR_opt_' + p] / df['LLVM_selectiondag_' + p] + df['ratios_gisel_sdag'] = df['LLVM_globalisel_' + p] / df['LLVM_selectiondag_' + p] + df['ratios_gisel_class'] = df['ratios_gisel'].apply(lambda x: 'A' if x < 1 else 'B' if x == 1 else 'C' if x < 1.5 else 'D' if x < 2 else 'E') + df['ratios_sdag_class'] = df['ratios_sdag'].apply(lambda x: 'A' if x < 1 else 'B' if x == 1 else 'C' if x < 1.5 else 'D' if x < 2 else 'E') + df['ratios_gisel_sdag_class'] = df['ratios_gisel_sdag'].apply(lambda x: 'A' if x < 1 else 'B' if x == 1 else 'C' if x < 1.5 else 'D' if x < 2 else 'E') + + # max and min values + max_ratio_gisel = df["ratios_gisel"].max() + max_ratio_sdag = df["ratios_sdag"].max() + max_ratio_gisel_sdag = df["ratios_gisel_sdag"].max() + min_ratio_gisel = df["ratios_gisel"].min() + min_ratio_sdag = df["ratios_sdag"].min() + min_ratio_gisel_sdag = df["ratios_gisel_sdag"].min() + + if p == "tot_cycles": + p = 'NumCycles' + else: + p = 'NumInstr' + latex_command_max_gisel = f"\\newcommand{{\\MaxRatioLeanmlirVsGiselParam{p}}}{{{max_ratio_gisel:.2f}}}\n" + latex_command_max_sdag = f"\\newcommand{{\\MaxRatioLeanmlirVsSdagParam{p}}}{{{max_ratio_sdag:.2f}}}\n" + latex_command_max_gisel_sdag = f"\\newcommand{{\\MaxRatioGiselVsSdagParam{p}}}{{{max_ratio_gisel_sdag:.2f}}}\n" + latex_command_min_gisel = f"\\newcommand{{\\MinRatioLeanmlirVsGiselParam{p}}}{{{min_ratio_gisel:.2f}}}\n" + latex_command_min_sdag = f"\\newcommand{{\\MinRatioLeanmlirVsSdagParam{p}}}{{{min_ratio_sdag:.2f}}}\n" + latex_command_min_gisel_sdag = f"\\newcommand{{\\MinRatioGiselVsSdagParam{p}}}{{{min_ratio_gisel_sdag:.2f}}}\n" + + f.write(latex_command_max_gisel) + f.write(latex_command_max_sdag) + f.write(latex_command_min_gisel) + f.write(latex_command_min_sdag) + f.write(latex_command_max_gisel_sdag) + f.write(latex_command_min_gisel_sdag) + + + # calculate % of elements in each class + df_grouped_gisel = df.groupby('instructions_number')['ratios_gisel_class'].value_counts(normalize=True) * 100 + df_grouped_sdag = df.groupby('instructions_number')['ratios_sdag_class'].value_counts(normalize=True) * 100 + df_grouped_gisel_sdag = df.groupby('instructions_number')['ratios_gisel_sdag_class'].value_counts(normalize=True) * 100 + + + + # print a latex command for each percentage, specify in the name the class it belongs to + # and the `instructions_number` + + df_grouped_gisel = df_grouped_gisel.reset_index() + df_grouped_sdag = df_grouped_sdag.reset_index() + df_grouped_gisel_sdag = df_grouped_gisel_sdag.reset_index() + + for _, row in df_grouped_gisel.iterrows(): + c = row['ratios_gisel_class'] + percentage = row['proportion'] + instructions_number = num2words(row['instructions_number']) + latex_command = f"\\newcommand{{\\PercLeanmlirVsGiselParam{p}Class{c}Instr{instructions_number}}}{{{int(percentage)}\%}}\n" + f.write(latex_command) + for _, row in df_grouped_sdag.iterrows(): + c = row['ratios_sdag_class'] + percentage = row['proportion'] + instructions_number = num2words(row['instructions_number']) + latex_command = f"\\newcommand{{\\PercLeanmlirVsSdagParam{p}Class{c}Instr{instructions_number}}}{{{int(percentage)}\%}}\n" + f.write(latex_command) + + for _, row in df_grouped_gisel_sdag.iterrows(): + c = row['ratios_gisel_sdag_class'] + percentage = row['proportion'] + instructions_number = num2words(row['instructions_number']) + latex_command = f"\\newcommand{{\\PercGiselVsSdagParam{p}Class{c}Instr{instructions_number}}}{{{int(percentage)}\%}}\n" + f.write(latex_command) + + # geomean ratios and total geomeans + + geomeans_gisel = df.groupby('instructions_number')['ratios_gisel'].apply( + lambda x: np.exp(np.log(x).mean()) + ) + for instr_num, geomean_value in geomeans_gisel.items(): + instructions_number = num2words(instr_num) + latex_command = f"\\newcommand{{\\GeomeanLeanmlirVsGiselParam{p}Instr{instructions_number}}}{{{geomean_value:.1f}}}\n" + f.write(latex_command) + + geomeans_sdag = df.groupby('instructions_number')['ratios_sdag'].apply( + lambda x: np.exp(np.log(x).mean()) + ) + for instr_num, geomean_value in geomeans_sdag.items(): + instructions_number = num2words(instr_num) + latex_command = f"\\newcommand{{\\GeomeanLeanmlirVsSdagParam{p}Instr{instructions_number}}}{{{geomean_value:.1f}}}\n" + f.write(latex_command) + + # total geomeans + + geomean_gisel_tot = np.exp(np.log(df['ratios_gisel']).mean()) + latex_command_gisel_geomean = f"\\newcommand{{\\GeomeanTotLeanmlirVsGisel{p}}}{{{geomean_gisel_tot:.1f}}}\n" + f.write(latex_command_gisel_geomean) + + geomean_gisel_tot_perc = (np.exp(np.log(df['ratios_gisel']).mean()) - 1) * 100 + latex_command_gisel_geomean_perc = f"\\newcommand{{\\GeomeanTotLeanmlirVsGiselSlowDownPerc{p}}}{{{geomean_gisel_tot_perc:.1f}\%}}\n" + f.write(latex_command_gisel_geomean_perc) + + geomean_sdag_tot = np.exp(np.log(df['ratios_sdag']).mean()) + latex_command_sdag_geomean = f"\\newcommand{{\\GeomeanTotLeanmlirVsSdag{p}}}{{{geomean_sdag_tot:.1f}}}\n" + f.write(latex_command_sdag_geomean) + + geomean_sdag_tot_perc = (np.exp(np.log(df['ratios_sdag']).mean()) - 1) * 100 + latex_command_sdag_geomean_perc = f"\\newcommand{{\\GeomeanTotLeanmlirVsSdagSlowDownPerc{p}}}{{{geomean_sdag_tot_perc:.1f}\%}}\n" + f.write(latex_command_sdag_geomean_perc) + + + # print the percentage of programs that are identical, for each number of instructions + + df_similarity = pd.read_csv(data_dir + "similarity.csv") + + df_similarity_gisel = df_similarity.groupby('instructions_number')['is_eqv_LLVM_globalisel'].value_counts(normalize=True) * 100 + df_similarity_sdag = df_similarity.groupby('instructions_number')['is_eqv_LLVM_selectiondag'].value_counts(normalize=True) * 100 + + df_similarity_gisel = df_similarity_gisel.reset_index() + df_similarity_sdag = df_similarity_sdag.reset_index() + + for idx, row in df_similarity_gisel.iterrows(): + if row['is_eqv_LLVM_globalisel']: + percentage = row['proportion'] + instructions_number = num2words(row['instructions_number']) + latex_command = f"\\newcommand{{\\PercIdenticalGiselInstr{instructions_number}}}{{{int(percentage)}\%}}\n" + f.write(latex_command) + for idx, row in df_similarity_sdag.iterrows(): + if row['is_eqv_LLVM_selectiondag']: + percentage = row['proportion'] + instructions_number = num2words(row['instructions_number']) + latex_command = f"\\newcommand{{\\PercIdenticalSdagInstr{instructions_number}}}{{{int(percentage)}\%}}\n" + f.write(latex_command) + + # total similarity + + tot_similarity_gisel_true = df_similarity['is_eqv_LLVM_globalisel'].sum()/len(df_similarity)*100 + tot_similarity_sdag_true = df_similarity['is_eqv_LLVM_selectiondag'].sum()/len(df_similarity)*100 + + latex_command_similarity_tot_gisel = f"\\newcommand{{\\PercIdenticalGiselTot}}{{{tot_similarity_gisel_true:.1f}\%}}\n" + f.write(latex_command_similarity_tot_gisel) + latex_command_similarity_tot_sdag = f"\\newcommand{{\\PercIdenticalSdagTot}}{{{tot_similarity_sdag_true:.1f}\%}}\n" + f.write(latex_command_similarity_tot_sdag) + f.close() + + + + + + +def main(): + parser = argparse.ArgumentParser( + prog="plot", + description="Produce the plots to evaluate the performance of the Lean-MLIR certified Instruction Selection.", + ) + + parser.add_argument( + "-p", + "--parameters", + nargs="+", + choices=["tot_instructions", "tot_cycles", "tot_uops", "similarity", "all"], + default="all" + ) + + parser.add_argument( + "-t", + "--plot_type", + nargs="+", + choices=["scatter", "sorted", "stacked", "overhead", "violin", "all"], + default="all" + ) + + args = parser.parse_args() + + params_to_evaluate = ( + ["similarity", "tot_instructions", "tot_cycles", "tot_uops"] + if "all" in args.parameters + else args.parameters + ) + + plots_to_produce = ( + ["scatter", "sorted", "stacked", "overhead", "proportional", "violin"] + if "all" in args.plot_type + else args.plot_type + ) + + setup_benchmarking_directories() + for parameter in params_to_evaluate: + extract_data(LLVM_globalisel_results_DIR_PATH, "LLVM_globalisel", parameter) + extract_data(LLVM_selectiondag_results_DIR_PATH, "LLVM_selectiondag", parameter) + extract_data(LEANMLIR_opt_results_DIR_PATH, "LEANMLIR_opt", parameter) + + to_join = ["LEANMLIR_opt", "LLVM_globalisel", "LLVM_selectiondag"] + join_dataframes(to_join, parameter) + if parameter == "similarity": + continue + else: + # if "scatter" in plots_to_produce or "all" in plots_to_produce: + # scatter_plot(parameter, "LEANMLIR_opt", "LLVM_globalisel") + # scatter_plot(parameter, "LEANMLIR_opt", "LLVM_selectiondag") + # # scatter_plot(parameter, 'LLVM_globalisel', 'LLVM_selectiondag') + # if "sorted" in plots_to_produce or "all" in plots_to_produce: + # sorted_line_plot_all(parameter) + # sorted_line_plot(parameter, "LEANMLIR_opt", "LLVM_globalisel") + # sorted_line_plot(parameter, "LEANMLIR_opt", "LLVM_selectiondag") + # # sorted_line_plot(parameter, 'LLVM_globalisel', 'LLVM_selectiondag') + # if "overhead" in plots_to_produce or "all" in plots_to_produce: + # overhead_plot(parameter, "LEANMLIR_opt", "LLVM_globalisel") + # overhead_plot(parameter, "LEANMLIR_opt", "LLVM_selectiondag") + # # overhead_plot(parameter, 'LLVM_globalisel', 'LLVM_selectiondag') + if "stacked" in plots_to_produce or "all" in plots_to_produce: + bar_plot(parameter, "LEANMLIR_opt", "LLVM_globalisel") + bar_plot(parameter, "LEANMLIR_opt", "LLVM_selectiondag") + # bar_plot(parameter, 'LLVM_globalisel', 'LLVM_selectiondag') + if "violin" in plots_to_produce or "all" in plots_to_produce: + violin_plot(parameter, "LEANMLIR_opt", "LLVM_globalisel") + violin_plot(parameter, "LEANMLIR_opt", "LLVM_selectiondag") + violin_plot(parameter, "LLVM_globalisel", "LLVM_selectiondag") + # bar_plot(parameter, 'LLVM_globalisel', 'LLVM_selectiondag') + if "proportional" in plots_to_produce or "all" in plots_to_produce: + proportional_bar_plot(parameter, "LEANMLIR_opt", "LLVM_globalisel") + proportional_bar_plot(parameter, "LEANMLIR_opt", "LLVM_selectiondag") + + # proportional_bar_plot(parameter, 'LLVM_globalisel', 'LLVM_selectiondag') + + geomean_plot_tot_cycles() + equivalent_plot_perc() + create_latex_command(['tot_cycles', 'tot_instructions'], plots_dir + 'numerical_commands.tex') + +if __name__ == "__main__": + main() diff --git a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/pyproject.toml b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/pyproject.toml new file mode 100644 index 0000000000..51b655b812 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/pyproject.toml @@ -0,0 +1,12 @@ +[project] +name = "mca-analysis" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.13" +dependencies = [ + "evallib", +] + +[tool.uv.sources] +evallib = { path = "../../../../../evallib" } diff --git a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/run_mca.py b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/run_mca.py new file mode 100755 index 0000000000..eeac73c358 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/run_mca.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 + +import os +import shutil +import subprocess +import argparse +from evallib import taskqueue + +ROOT_DIR = ( + subprocess.check_output(["git", "rev-parse", "--show-toplevel"]) + .decode("utf-8") + .strip() +) +TIMEOUT = 1800 # seconds + +LLC_ASM_globalisel_DIR = ( + f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LLC_ASM_globalisel/" +) +LLC_ASM_selectiondag_DIR = ( + f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LLC_ASM_selectiondag/" +) +LLC_ASM_DIR = f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/LLC_ASM/" +XDSL_ASM_DIR = f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/XDSL_ASM/" +XDSL_opt_ASM_DIR = ( + f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/benchmarks/XDSL_opt_ASM/" +) +MCA_LEANMLIR_DIR = ( + f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LEANMLIR/" +) +MCA_LEANMLIR_opt_DIR = ( + f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LEANMLIR_opt/" +) +MCA_LLVM_globalisel_DIR = f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LLVM_globalisel/" +MCA_LLVM_selectiondag_DIR = f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/LLVM_selectiondag/" +LOGS_DIR = f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/logs/" + + +AUTOGEN_DIR_PATHS = [ + MCA_LEANMLIR_DIR, + MCA_LEANMLIR_opt_DIR, + MCA_LLVM_globalisel_DIR, + MCA_LLVM_selectiondag_DIR, + LOGS_DIR, +] + + +def setup_benchmarking_directories(): + """ + Create clean directories to store the benchmarks. + """ + results_dir = f"{ROOT_DIR}/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/results/" + if not os.path.exists(results_dir): + os.makedirs(results_dir) + for directory in AUTOGEN_DIR_PATHS: + if not os.path.exists(directory): + os.makedirs(directory) + else: + shutil.rmtree(directory) + os.makedirs(directory) + + +def run_command(cmd, log_file, timeout=TIMEOUT): + try: + print(cmd) + subprocess.Popen( + cmd, cwd=ROOT_DIR, stdout=log_file, stderr=log_file, shell=True + ).wait(timeout=timeout) + except subprocess.TimeoutExpired: + log_file.truncate(0) + log_file.write(f"timeout of {timeout} seconds reached\n") + print(f"{log_file} - timeout of {timeout} seconds reached") + + +def mca_analysis(input_file, output_file, log_file): + """ + Run MCA performance analysis on the RISCV asm `input_file`. + """ + cmd_base = "llvm-mca -mtriple=riscv64 -mcpu=sifive-u74 -mattr=+m,+zba,+zbb,+zbs " + cmd = cmd_base + input_file + " > " + output_file + run_command(cmd, log_file) + + +def run_tests(): + # clear results directory + setup_benchmarking_directories() + + # Parse CLI arguments + parser = argparse.ArgumentParser() + taskqueue.add_cli_arguments(parser) + + # idx = 0 + # for filename in os.listdir(XDSL_ASM_DIR): + # input_file = os.path.join(XDSL_ASM_DIR, filename) + # basename, _ = os.path.splitext(filename) + # output_file = os.path.join(MCA_LEANMLIR_DIR, basename + '.out') + # log_file = open(os.path.join(LOGS_DIR, 'xdsl_' + filename),'w') + # mca_analysis(input_file, output_file, log_file) + # idx += 1 + # percentage = ((float(idx) + float(1)) / float(len(os.listdir(XDSL_ASM_DIR)))) * 100 + # print(f"running mca analysis on lean-mlir asm: {percentage:.2f}%") + + idx = 0 + for filename in os.listdir(XDSL_opt_ASM_DIR): + input_file = os.path.join(XDSL_opt_ASM_DIR, filename) + basename, _ = os.path.splitext(filename) + output_file = os.path.join(MCA_LEANMLIR_opt_DIR, basename + ".out") + log_file = open(os.path.join(LOGS_DIR, "xdsl_opt_" + filename), "w") + mca_analysis(input_file, output_file, log_file) + idx += 1 + percentage = ( + (float(idx) + float(1)) / float(len(os.listdir(XDSL_opt_ASM_DIR))) + ) * 100 + print(f"running mca analysis on lean-mlir asm (opt): {percentage:.2f}%") + + idx = 0 + for filename in os.listdir(LLC_ASM_globalisel_DIR): + input_file = os.path.join(LLC_ASM_globalisel_DIR, filename) + basename, _ = os.path.splitext(filename) + output_file = os.path.join(MCA_LLVM_globalisel_DIR, basename + ".out") + log_file = open(os.path.join(LOGS_DIR, "llvm_globalisel_" + filename), "w") + mca_analysis(input_file, output_file, log_file) + idx += 1 + percentage = ( + (float(idx) + float(1)) / float(len(os.listdir(LLC_ASM_globalisel_DIR))) + ) * 100 + print(f"running mca analysis on llc asm (globalISel): {percentage:.2f}%") + + idx = 0 + for filename in os.listdir(LLC_ASM_selectiondag_DIR): + input_file = os.path.join(LLC_ASM_selectiondag_DIR, filename) + basename, _ = os.path.splitext(filename) + output_file = os.path.join(MCA_LLVM_selectiondag_DIR, basename + ".out") + log_file = open(os.path.join(LOGS_DIR, "llvm_selectiondag_" + filename), "w") + mca_analysis(input_file, output_file, log_file) + idx += 1 + percentage = ( + (float(idx) + float(1)) / float(len(os.listdir(LLC_ASM_selectiondag_DIR))) + ) * 100 + print(f"running mca analysis on llc asm (selectionDAG): {percentage:.2f}%") + + +def main(): + run_tests() + + +if __name__ == "__main__": + main() diff --git a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/similarity.py b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/similarity.py new file mode 100644 index 0000000000..2fb92676a9 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/similarity.py @@ -0,0 +1,72 @@ +import csv +import io + +def compute_similarity(file_path): + """ + Computes the similarity between the last two numerical columns of the provided data + from a file. + + Args: + file_path (str): The path to the file containing the data. The file must + be a CSV with a header row. + + Returns: + None: Prints the results directly to the console. + """ + total_runs = 0 + identical_runs = 0 + + # Use a try-except block to handle potential file errors, such as the file + # not being found. + try: + # Open the file and wrap it in a file-like object for the csv reader + with open(file_path, 'r') as data_file: + reader = csv.reader(data_file) + + # Skip the header row + header = next(reader) + print(f"Analyzing data from file '{file_path}' with columns: {', '.join(header)}") + + # Iterate through each row in the data + for row in reader: + # Skip any empty lines + if not row: + continue + + # Get the two numbers to compare. We use a try-except block to handle + # any potential errors in data format (e.g., non-numeric values). + try: + # The columns 'SelectionDAG' and 'our' are the third and fourth columns, + # which are at index 2 and 3 in a 0-based list. + value_selection_dag = float(row[2]) + value_our = float(row[3]) + + # Increment the total number of runs + total_runs += 1 + # Compare the two values and increment the identical_runs counter if they are the same + if value_selection_dag == value_our : + identical_runs += 1 + + except (ValueError, IndexError) as e: + print(f"Skipping row due to data format error: {row}. Error: {e}") + except FileNotFoundError: + print(f"Error: The file '{file_path}' was not found.") + return + except Exception as e: + print(f"An unexpected error occurred: {e}") + return + + # Calculate the similarity percentage if there were any runs + similarity_percentage = 0 + if total_runs > 0: + similarity_percentage = (identical_runs / total_runs) * 100 + + # Print the final results + print("-" * 30) + print(f"Total number of runs analyzed: {total_runs}") + print(f"Number of runs where values were identical: {identical_runs}") + print(f"Similarity Percentage: {similarity_percentage:.2f}%") + print("-" * 30) + +if __name__ == "__main__": + compute_similarity("pivoted_instructions_for_plot.csv") diff --git a/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/uv.lock b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/uv.lock new file mode 100644 index 0000000000..d660d961d1 --- /dev/null +++ b/SSA/Projects/LLVMRiscV/Evaluation/mca-analysis/uv.lock @@ -0,0 +1,46 @@ +version = 1 +revision = 3 +requires-python = ">=3.13" + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "evallib" +version = "0.1.0" +source = { directory = "../../../../../evallib" } +dependencies = [ + { name = "tqdm" }, +] + +[package.metadata] +requires-dist = [{ name = "tqdm", specifier = ">=4.67.1" }] + +[[package]] +name = "mca-analysis" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "evallib" }, +] + +[package.metadata] +requires-dist = [{ name = "evallib", directory = "../../../../../evallib" }] + +[[package]] +name = "tqdm" +version = "4.67.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737, upload-time = "2024-11-24T20:12:22.481Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540, upload-time = "2024-11-24T20:12:19.698Z" }, +] From f30131b2c321b920f317635d9b084878a0cd7d9c Mon Sep 17 00:00:00 2001 From: luisacicolini Date: Thu, 16 Jul 2026 17:03:08 +0100 Subject: [PATCH 10/13] remove useless sorry --- .../CIRCT/HandshakeToHW/fork_lowering.lean | 727 ------------------ 1 file changed, 727 deletions(-) diff --git a/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean b/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean index d099bdfd38..acfd80f988 100644 --- a/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean +++ b/SSA/Projects/CIRCT/HandshakeToHW/fork_lowering.lean @@ -893,732 +893,5 @@ def readyOut2UntilAllReceiversAre (rdOut1 rdOut2 : Stream' (BitVec 1)) := rdOut2 i = 1#1 → ∀ j, rdOut1 (i + j) = 0#1 → rdOut2 (i + j) = 1#1 -/-- the standard implementation of the fork refines the handshake fork (`TRY2.hw_fork`) -/ -theorem hw_fork_refines1_with_fork: - /- Given a handshake fork taking `a` as input and returning `(a, a)`, we take - its lowering (with input a bisimilar ready-valid wrapped stream) -/ - (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = project_stream (rtl.fork rdOut1 rdOut2 vldIn dataIn) → - /- We want to make sure that stalling is correctly modeled for `a` (input). - We constrain the input and prove that if the input behaves properly, - the output will. -/ - globallyValidUntilReady vldOut1 rdOut1 → - globallyValidUntilReady vldOut2 rdOut2 → - globallyValidUntilReady vldIn rdIn → - readyOut1UntilAllReceiversAre (rdOut1 := rdOut1) (rdOut2 := rdOut2) → - readyOut2UntilAllReceiversAre (rdOut1 := rdOut1) (rdOut2 := rdOut2) → - globallyValidAndData vldOut1 dataOut1 → - globallyValidAndData vldOut2 dataOut2 → - globallyValidAndData vldIn dataIn → - /- we assume no deadlock -/ - globallyFinallyReady rdIn → - globallyFinallyReady rdOut1 → - globallyFinallyReady rdOut2 → - /- if we know that the hshake input stream is bisimilar to the ready-valid input of the hw fork (`a ~ rdy vld i`), meaning that the two outputs are also bisimilar by transitivity-/ - /- we want to prove that the outputs of the handshake fork are respectively - bisimilar to the ready-valid wrapping of the output of the hardware fork -/ - (toStream rdIn vldIn dataIn) ~ (toStream rdOut1 vldOut1 dataOut1) := by - intros hfork hgvurOutt1 hvgurOut2 hgvurIn hout1 hout2 hgvdOut1 hgvdOut2 hgvdIn hgfrIn hgfrOut1 hgfrOut2 - /- if 0, 0 works we don't need bisimilarity -/ - /- the high-level fork will never wait for anything (whenever an input is available), - while the low-level one might have to, and depends on the `rd1` signal eventually being true. - if we choose `pred := Eq` the relation is too strong, the second goal is not provable. - -/ - apply Bisim.coinduct (pred := relation_fork) - · intros sin sout hrel - /- `sin` and `sout` exist at the handshake level of the design -/ - rcases hrel - expose_names - by_cases hvldExists : ∃ k, vldIn_1 k = 1#1 - · have := if_exists_first_exists hvldExists - obtain ⟨fstVldTrue, hfstVldTrue1, hfstVldTrue2⟩ := this - /- we need to find the first element that is transmitted -/ - have hfstSent := exists_first_transmitted_element - (data := dataIn_1) (vld := vldIn_1) (rdy := rdIn_1) (x := sin) - (by grind) (by assumption) (by assumption) - have ⟨fstRdyOut, hfstRdyOut⟩ := if_exists_first_exists (h_4 fstVldTrue) - have ⟨fstRdyOut2, hfstRdyOut2⟩ := if_exists_first_exists (h_5 fstVldTrue) - unfold globallyFinallyReady at h_4 - have hvldinout := vldIn_and_ready_implies_vldOut1 - (dataIn := dataIn_1) (vldIn := vldIn_1) (rdIn := rdIn_1) - (rdOut1 := rdOut1_1) (rdOut2 := rdOut2_1) (vldOut1 := vldOut1_1) (vldOut2 := vldOut2_1) - (dataOut1 := dataOut1_1) (dataOut2 := dataOut2_1) (by grind) (by grind) - have hvldinout2 := vldIn_and_ready_implies_vldOut2 - (dataIn := dataIn_1) (vldIn := vldIn_1) (rdIn := rdIn_1) - (rdOut1 := rdOut1_1) (rdOut2 := rdOut2_1) (vldOut1 := vldOut1_1) (vldOut2 := vldOut2_1) - (dataOut1 := dataOut1_1) (dataOut2 := dataOut2_1) (by grind) (by grind) - have hfstRec := exists_first_received_element - (data := dataOut1_1) (vld := vldOut1_1) (rdy := rdOut1_1) (x := sout) (hx := h_8) - have ⟨fstSentIdx, hfstSentIdx⟩ := hfstSent - exists fstSentIdx, (fstVldTrue + fstRdyOut) - and_intros - · apply relation_fork.intro - (Stream'.drop (fstSentIdx + 1) sin) (Stream'.drop (fstVldTrue + fstRdyOut + 1) sout) - (dataIn := Stream'.drop (fstSentIdx + 1) dataIn_1) - (rdIn := Stream'.drop (fstSentIdx + 1) rdIn_1) - (vldIn := Stream'.drop (fstSentIdx + 1) vldIn_1) - (vldOut1 := Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut1_1) - (vldOut2 := Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut2_1) - (dataOut1 := Stream'.drop (fstVldTrue + fstRdyOut + 1) dataOut1_1) - (dataOut2 := Stream'.drop (fstSentIdx + 1) dataOut2_1) - (rdOut1 := Stream'.drop (fstVldTrue + fstRdyOut + 1) rdOut1_1) - (rdOut2 := Stream'.drop (fstVldTrue + fstRdyOut + 1) rdOut2_1) - · simp_all - rfl - · simp_all - rfl - · unfold globallyValidUntilReady at ⊢ h - intro j hj - specialize h (j + fstSentIdx + 1) hj - obtain ⟨k, hk1, hk2, hk3⟩ := h - exists k - have hv : Stream'.drop (fstSentIdx + 1) vldIn_1 j = vldIn_1 (j + fstSentIdx + 1) := by rfl - rw [hv] at hj - have hv : Stream'.drop (fstSentIdx + 1) vldIn_1 (j + k) = vldIn_1 (j + k + fstSentIdx + 1) := by rfl - have hr : Stream'.drop (fstSentIdx + 1) rdIn_1 (j + k) = rdIn_1 (j + k + fstSentIdx + 1) := by rfl - simp [hv, hr, show j + k + fstSentIdx + 1 = j + fstSentIdx + 1 + k by omega, hk1, hk2] - intros n hn - have hn : Stream'.drop (fstSentIdx + 1) vldIn_1 (j + n) = vldIn_1 (j + n + fstSentIdx + 1) := by rfl - simp [hn] - specialize hk3 n (by omega) - simp [show j + n + fstSentIdx + 1 = j + fstSentIdx + 1 + n by omega, hk3] - · unfold globallyValidUntilReady at ⊢ h_1 - intro j hj - have hj2 : Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut1_1 j = vldOut1_1 (j + fstVldTrue + fstRdyOut + 1) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - rw [hj2] at hj - specialize h_1 (j + fstVldTrue + fstRdyOut + 1) hj - obtain ⟨k, hk1, hk2, hk3⟩ := h_1 - exists k - have hv : Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut1_1 (j + k) = vldOut1_1 (j + k + fstVldTrue + fstRdyOut + 1) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - have hr : Stream'.drop (fstVldTrue + fstRdyOut + 1) rdOut1_1 (j + k) = rdOut1_1 (j + k + fstVldTrue + fstRdyOut + 1) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - simp [hv, hr, show j + k + fstVldTrue + fstRdyOut + 1 = j + fstVldTrue + fstRdyOut + 1 + k by omega, hk1, hk2] - intros n hn - have hn : Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut1_1 (j + n) = vldOut1_1 (j + n + fstVldTrue + fstRdyOut + 1) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - simp [hn] - specialize hk3 n (by omega) - simp [show j + n + fstVldTrue + fstRdyOut + 1 = j + fstVldTrue + fstRdyOut + 1 + n by omega, hk3] - · unfold globallyValidUntilReady at ⊢ h_2 - intro j hj - have hj2 : Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut2_1 j = vldOut2_1 (j + fstVldTrue + fstRdyOut + 1) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - rw [hj2] at hj - specialize h_2 (j + fstVldTrue + fstRdyOut + 1) hj - obtain ⟨k, hk1, hk2, hk3⟩ := h_2 - exists k - have hv : Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut2_1 (j + k) = vldOut2_1 (j + k + fstVldTrue + fstRdyOut + 1) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - have hr : Stream'.drop (fstVldTrue + fstRdyOut + 1) rdOut2_1 (j + k) = rdOut2_1 (j + k + fstVldTrue + fstRdyOut + 1) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - simp [hv, hr, show j + k + fstVldTrue + fstRdyOut + 1 = j + fstVldTrue + fstRdyOut + 1 + k by omega, hk1, hk2] - intros n hn - have hn : Stream'.drop (fstVldTrue + fstRdyOut + 1) vldOut2_1 (j + n) = vldOut2_1 (j + n + fstVldTrue + fstRdyOut + 1) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - simp [hn] - specialize hk3 n (by omega) - simp [show j + n + fstVldTrue + fstRdyOut + 1 = j + fstVldTrue + fstRdyOut + 1 + n by omega, hk3] - · unfold globallyValidAndData at ⊢ h_3 - intro j - specialize h_3 (j + fstSentIdx + 1) - have hr : Stream'.drop (fstSentIdx + 1) dataIn_1 j = dataIn_1 (j + fstSentIdx + 1) := by rfl - have hr' : Stream'.drop (fstSentIdx + 1) dataIn_1 (j + 1) = dataIn_1 (j + 1 + fstSentIdx + 1) := by rfl - simp [hr, hr'] - simp [show j + 1 + fstSentIdx + 1 = j + fstSentIdx + 1 + 1 by omega] - intro h1 h2 - apply h_3 - have htmp : Stream'.drop (fstSentIdx + 1) vldIn_1 j = vldIn_1 (j + fstSentIdx + 1) := by rfl - rw [htmp] at h1 - simp [h1] - have htmp : Stream'.drop (fstSentIdx + 1) vldIn_1 (j + 1) = vldIn_1 (j + 1 + fstSentIdx + 1) := by rfl - simp [show j + 1 + fstSentIdx + 1 = j + fstSentIdx + 1 + 1 by omega, htmp] at h2 - simp [h2] - · unfold globallyFinallyReady - intros i - specialize h_4 (i + fstVldTrue + fstRdyOut + 1) - obtain ⟨k, hk⟩ := h_4 - exists k - have htmp : Stream'.drop (fstVldTrue + fstRdyOut + 1) rdOut1_1 (i + k) = rdOut1_1 (i + k + fstVldTrue + fstRdyOut + 1) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - simp [htmp, show i + k + fstVldTrue + fstRdyOut + 1 = i + fstVldTrue + fstRdyOut + 1 + k by omega, hk] - · unfold globallyFinallyReady at h_5 ⊢ - intro j - specialize h_5 (fstVldTrue + fstRdyOut + 1 + j) - obtain ⟨k, hk⟩ := h_5 - exists k - have h : Stream'.drop (fstVldTrue + fstRdyOut + 1) rdOut2_1 (j + k) = rdOut2_1 (fstVldTrue + fstRdyOut + 1 + j + k) := by - simp [Stream'.drop, Stream'.get] - congr 1 - omega - simp [h, hk] - · have : fstVldTrue ≤ fstSentIdx := by - simp_all - apply Classical.byContradiction - intro hcontra - specialize hfstVldTrue2 fstSentIdx (by omega) - simp [toStream, hfstVldTrue2] at hfstSentIdx - by_cases fstRecfst : fstRdyOut ≤ fstRdyOut2 - · /- first receiver comes first -/ - by_cases fstRecBeforeSent : fstVldTrue + fstRdyOut ≤ fstSentIdx - · /- first receiver before sent -/ - by_cases sndRecBeforeSent : fstVldTrue + fstRdyOut2 ≤ fstSentIdx - · /- second receiver before sent -/ - simp [project_stream] - and_intros - · funext i - have := rdOut1_before_allDone (hfork := h_6) (n := i) - /- what happens to `rdOut1` after data is dispatched? -/ - have heq : Stream'.drop (fstSentIdx + 1) rdIn_1 i = rdIn_1 (fstSentIdx + 1 + i) := by - simp [Stream'.drop] - congr 1 - grind - rw [heq] - by_cases hfalse : rdIn_1 (fstSentIdx + 1 + i) = 0#1 - · have := congr_fun h_7 (fstSentIdx + 1 + i) - unfold toStream at this - simp [hfalse] at * - rw [hw_fork_eq] - - have : ∀ k, ∀ i, Stream'.drop k rdOut1_1 i = rdOut1_1 (i + k) := by - intros - simp [Stream'.drop, Stream'.get] - simp [rtl.fork', Stream'.corec'] - unfold fork_corec - simp [comb_and, comb_xor, comb_or, hw_constant] - - sorry - · sorry - · sorry - · sorry - · sorry - · sorry - · /- first receiver after sent -/ - sorry - · /- first receiver after sent, implies second receiver after sent -/ - have : fstSentIdx ≤ fstVldTrue + fstRdyOut2 := by omega - sorry - · /- second receiver comes first -/ - by_cases fstRecBeforeSent : fstVldTrue + fstRdyOut ≤ fstSentIdx - · /- first receiver before sent, implies second receiver before sent -/ - have : fstVldTrue + fstRdyOut2 ≤ fstSentIdx := by omega - sorry - · /- first receiver after sent -/ - by_cases sndRecBeforeSent : fstVldTrue + fstRdyOut2 ≤ fstSentIdx - · /- second receiver before sent -/ - sorry - · /- first receiver after sent -/ - sorry - · simp [Stream'.get, h_8, h_7, toStream] - have h_6' : (rdIn_1, vldOut1_1, vldOut2_1, dataOut1_1, dataOut2_1) = - project_stream (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) := by - rw [← hw_fork_eq]; exact h_6 - have hdataeq := hw_fork_out0 (h := h_6') - by_cases hle : fstVldTrue ≤ fstSentIdx - · have hreadyIn : rdIn_1 fstSentIdx = 1#1 := by - unfold toStream at h_7 - have h_6sent := congr_fun h_7 fstSentIdx - simp [hfstSentIdx] at h_6sent - simp [h_6sent] - have hvalidIn: vldIn_1 fstSentIdx = 1#1 := by - unfold toStream at h_7 - have h_6sent := congr_fun h_7 fstSentIdx - simp [hfstSentIdx] at h_6sent - simp [h_6sent] - have hrdout : rdOut1_1 (fstVldTrue + fstRdyOut) = 1#1 := by - simp [hfstRdyOut] - have hvldout : vldOut1_1 (fstVldTrue + fstRdyOut) = 1#1 := by - have hbefore : ∀ j < fstVldTrue + fstRdyOut, rdOut1_1 j = 0#1 ∨ vldOut1_1 j = 0#1 := by - intro j hj - by_cases hjlt : j < fstVldTrue - · right; by_contra hc - have : vldOut1_1 j = 1#1 := by grind - have := vldOut1_implies_vldIn h_6 (n := j) (by assumption) - specialize hfstVldTrue2 j hjlt - simp [this] at hfstVldTrue2 - · left - have := hfstRdyOut.2 (j - fstVldTrue) (by omega) - rwa [Nat.add_sub_cancel' (by omega)] at this - rw [vldOut_eq_vldIn_of_fork_unitl_sent h_6 hbefore] - obtain ⟨k, hkrd, hkvld, hkall⟩ := h fstVldTrue hfstVldTrue1 - by_contra hlt; push_neg at hlt - have hrda : rdOut1_1 (fstVldTrue + k) = 0#1 := by - have := hfstRdyOut.2 k (by grind) - simpa using this - -- rdIn fires at fstVldTrue + k with k < fstRdyOut, but rdOut1 hasn't fired - have hh5 := h_6 - rw [hw_fork_eq] at h_6 - simp [project_stream] at h_6 - obtain ⟨hrdin, -⟩ := h_6 - have hcirc := congr_fun hrdin (fstVldTrue + k) - unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hcirc - generalize hst : Stream'.iterate - (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) - (fstVldTrue + k) = s at hcirc - obtain ⟨a, b, c⟩ := s - dsimp [fork_corec, comb_and, comb_xor, comb_or, hw_constant] at hcirc - have ha : a = fstVldTrue + k := by - have := @fork_corec_iter rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 (fstVldTrue + k) - simp [hst] at this - simp [this] - have hb0 : b = 0#1 := by - suffices key : ∀ m, (∀ j < m, rdOut1_1 j = 0#1 ∨ vldOut1_1 j = 0#1) → - (Stream'.iterate (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) - (0, 0#1, 0#1) m).2.1 = 0#1 by - have := key (fstVldTrue + k) (by - intro j hj - by_cases hjlt : j < fstVldTrue - · right; by_contra hc - have : vldOut1_1 j = 1#1 := true_of_width_one (b := vldOut1_1 j) hc - have := vldOut1_implies_vldIn hh5 (n := j) (by assumption) - specialize hfstVldTrue2 j hjlt - simp [this] at hfstVldTrue2 - · have hklt : k < fstRdyOut := by - by_contra hkge; push_neg at hkge - rcases Nat.lt_or_eq_of_le hkge with hlt' | rfl - · exact hlt (hkall fstRdyOut hlt') - · exact hlt hkvld - have hklt : k < fstRdyOut := by - by_contra hkge; push_neg at hkge - exact hlt (hkall fstRdyOut (by omega)) - left - have := hfstRdyOut.2 (j - fstVldTrue) (by omega) - rwa [Nat.add_sub_cancel' (by omega)] at this - ) - rw [hst] at this; simpa using this - intro m; induction m with - | zero => simp [Stream'.iterate] - | succ km ihkm => - intro hbef - have hbk := ihkm (fun j hj => hbef j (Nat.lt_succ_of_lt hj)) - generalize hsk : Stream'.iterate - (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) km = sk - obtain ⟨ak, bk, ck⟩ := sk - simp [hsk] at hbk; subst hbk - have hak : ak = km := by - have := @fork_corec_iter rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 km - simp [hsk] at this; omega - have hvldk : vldOut1_1 km = vldIn_1 ak := by - rw [hw_fork_eq] at hh5; simp [project_stream] at hh5 - obtain ⟨-, hvldout1, -⟩ := hh5 - have hn := congr_fun hvldout1 km - unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn - simp_rw [hsk] at hn - dsimp [fork_corec, comb_and, comb_xor, hw_constant] at hn - simp [hn] - ext k hk - simp [show k = 0 by omega] - have hkbef := hbef km (Nat.lt_succ_self km) - rw [iterate_back_succ, hsk]; simp only [Function.comp] - dsimp [fork_corec, comb_and, comb_xor, comb_or, hw_constant] - subst hak - rcases hkbef with hh | hh - · simp [hh] - · rw [hvldk] at hh; simp [hh] - rw [hkrd, hb0, ha] at hcirc - simp [hrda] at hcirc - simp [hvalidIn, hreadyIn, hrdout, hvldout] - rw [← hdataeq] - let diff := fstSentIdx - fstVldTrue - have hdiff : fstSentIdx = fstVldTrue + diff := by omega - have hdatain : dataIn_1 fstSentIdx = dataIn_1 fstVldTrue := by - rw [hdiff] - have := data_remains_constant_if (i := fstVldTrue) (rdy := rdIn_1) (vld := vldIn_1) (data := dataIn_1) - (by assumption) (by assumption) (by assumption) - obtain ⟨kd, hkd1, hkd2, hkd3, hkd4⟩ := this - by_cases hle : diff ≤ kd - · specialize hkd4 diff hle - apply hkd4 - · /- contra -/ - exfalso - have hkdlt : fstVldTrue + kd < fstSentIdx := by omega - have := hfstSentIdx.2 (fstVldTrue + kd) hkdlt - rw [h_7, toStream] at this - simp [hkd1, hkd2] at this - rw [hdatain] - symm - have := data_remains_constant_until_first (i := fstVldTrue) - (data := dataIn_1) (rdy := rdIn_1) (vld := vldIn_1) (by assumption) - (by assumption) (by assumption) - obtain ⟨k, hk1, hk2, hk3, hk4, hk5⟩ := this - have hkeqdiff : k = diff := by - apply Nat.le_antisymm - · by_contra hlt; push_neg at hlt - -- hlt : diff < k - have := hk5 diff (by omega) - rw [← hdiff] at this - simp [hreadyIn] at this - · by_contra hlt; push_neg at hlt - have := hfstSentIdx.2 (fstVldTrue + k) (by omega) - rw [h_7, toStream] at this - simp [hk1, hk2] at this - subst hkeqdiff - apply hk4 fstRdyOut - -- fstRdyOut ≤ diff, i.e., fstVldTrue + fstRdyOut ≤ fstSentIdx - -- proved by contradiction: if fstSentIdx < fstVldTrue + fstRdyOut, - -- allDone fires but rdOut1 hasn't, contradicting the circuit - have hrdyOutLe : fstVldTrue + fstRdyOut ≤ fstSentIdx := by - by_contra hlt; push_neg at hlt - have hh5 := h_6 - rw [hw_fork_eq] at h_6 - simp [project_stream] at h_6 - obtain ⟨hrdin, -⟩ := h_6 - have hcirc2 := congr_fun hrdin fstSentIdx - unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hcirc2 - generalize hst2 : Stream'.iterate - (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) - fstSentIdx = s2 at hcirc2 - obtain ⟨a2, b2, c2⟩ := s2 - dsimp [fork_corec, comb_and, comb_xor, comb_or, hw_constant] at hcirc2 - have ha2 : a2 = fstSentIdx := by - have := @fork_corec_iter rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 fstSentIdx - simp [hst2] at this; omega - have hb02 : b2 = 0#1 := by - suffices key2 : ∀ m, (∀ j < m, rdOut1_1 j = 0#1 ∨ vldOut1_1 j = 0#1) → - (Stream'.iterate (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) - (0, 0#1, 0#1) m).2.1 = 0#1 by - have := key2 fstSentIdx (by - intro j hj - by_cases hjlt : j < fstVldTrue - · right; by_contra hc - have : vldOut1_1 j = 1#1 := by grind - have := vldOut1_implies_vldIn hh5 (n := j) this - exact absurd (hfstVldTrue2 j hjlt) (by grind) - · left - have := hfstRdyOut.2 (j - fstVldTrue) (by omega) - rwa [Nat.add_sub_cancel' (by omega)] at this) - rw [hst2] at this; simpa using this - intro m; induction m with - | zero => simp [Stream'.iterate] - | succ km ihkm => - intro hbef - have hbk := ihkm (fun j hj => hbef j (Nat.lt_succ_of_lt hj)) - generalize hsk : Stream'.iterate - (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) km = sk - obtain ⟨ak, bk, ck⟩ := sk - simp [hsk] at hbk; subst hbk - have hak : ak = km := by - have := @fork_corec_iter rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 0 0#1 0#1 km - simp [hsk] at this; omega - have hvldk2 : vldOut1_1 km = vldIn_1 ak := by - rw [hw_fork_eq] at hh5; simp [project_stream] at hh5 - obtain ⟨-, hvldout1, -⟩ := hh5 - have hn := congr_fun hvldout1 km - unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hn - simp_rw [hsk] at hn - dsimp [fork_corec, comb_and, comb_xor, hw_constant] at hn - simp [hn] - ext k - simp [show k = 0 by omega] - rw [iterate_back_succ, hsk]; simp only [Function.comp] - dsimp [fork_corec, comb_and, comb_xor, comb_or, hw_constant] - subst hak - rcases hbef ak (Nat.lt_succ_self ak) with hh | hh - · simp [hh] - · rw [hvldk2] at hh; simp [hh] - have hrda2 : rdOut1_1 fstSentIdx = 0#1 := by - have := hfstRdyOut.2 (fstSentIdx - fstVldTrue) (by omega) - rwa [Nat.add_sub_cancel' (by omega)] at this - rw [hreadyIn, hb02, ha2, hrda2] at hcirc2 - simp at hcirc2 - omega - · /- contradiction: nothing can be sent before `fstSentIdx` -/ - simp_all - intro hcontra - specialize hfstVldTrue2 fstSentIdx hle - simp [toStream, hfstVldTrue2] at hfstSentIdx - · intro i hi - exact hfstSentIdx.2 i hi - · intros j hj - by_cases hj' : j < fstVldTrue - · simp [Stream'.get, h_8, toStream] - intro hvld - have := vldOut1_implies_vldIn h_6 (n := j) - have := hfstVldTrue2 j hj' - grind - · simp [h_8, toStream, Stream'.get] - let diff := j - fstVldTrue - have : j = fstVldTrue + diff := by omega - rw [this] - obtain ⟨h1,h2⟩ := hfstRdyOut - specialize h2 diff (by omega) - intro hc - simp [hc] at h2 - · /- if we never have a valid signal, all streams are empty and the relation holds trivially -/ - have hnonein := not_exists_transmitted_element (x := sin) (data := dataIn_1) (rdy := rdIn_1) - (vld := vldIn_1) (by grind) h_7 - /- the fork module will never transmit anything meaningful -/ - rw [hw_fork_eq] at h_6 - unfold project_stream at h_6 - simp at h_6 - have hhfork1 := h_6 - obtain ⟨hrd', hvld1', hvld2', hdata1', hdata2'⟩ := hhfork1 - rw [h_7, h_8] - have hnoneout : ∀ k, vldOut1_1 k = 0#1 := by - unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hvld1' - intros k - generalize hst : Stream'.iterate - (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) k = s at hvld1' - simp [fork_corec] at hvld1' - have hk := congr_fun hvld1' k - simp [comb_and, hw_constant] at hk - simp_all - - have : vldIn_1 (Stream'.iterate (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) k).1 = 0#1 := by - grind - simp [this] - have hnoneout2 : ∀ k, vldOut2_1 k = 0#1 := by - unfold rtl.fork' Stream'.corec' Stream'.corec Stream'.map Stream'.get at hvld2' - intros k - generalize hst : Stream'.iterate - (Prod.snd ∘ fork_corec rdOut1 rdOut2 vldIn dataIn) (0, 0#1, 0#1) k = s at hvld2' - simp [fork_corec] at hvld2' - have hk := congr_fun hvld2' k - simp [comb_and, hw_constant] at hk - simp_all - have : vldIn_1 (Stream'.iterate (Prod.snd ∘ fork_corec rdOut1_1 rdOut2_1 vldIn_1 dataIn_1) (0, 0#1, 0#1) k).1 = 0#1 := by - grind - simp [this] - have hnevldin : ∀ k, vldIn_1 k = 0#1 := by grind - have hnonet := not_exists_transmitted_element (x := sout) (data := dataOut1_1) (rdy := rdOut1_1) - (vld := vldOut1_1) (by grind) h_8 - exists 0, 0 - and_intros - · simp - generalize hxgen : Stream'.drop 1 (toStream rdIn_1 vldIn_1 dataIn_1) = y' - generalize hygen : Stream'.drop 1 (toStream rdOut1_1 vldOut1_1 dataOut1_1) = x' - apply relation_fork.intro (x := y') (y := x') - (dataIn := Stream'.drop 1 dataIn_1) - (rdIn := Stream'.drop 1 rdIn_1) - (vldIn := Stream'.drop 1 vldIn_1) - (vldOut1 := Stream'.drop 1 vldOut1_1) - (vldOut2 := Stream'.drop 1 vldOut2_1) - (dataOut1 := Stream'.drop 1 dataOut1_1) - (dataOut2 := Stream'.drop 1 dataOut2_1) - (rdOut1 := Stream'.drop 1 rdOut1_1) - (rdOut2 := Stream'.drop 1 rdOut2_1) - · rw [← hxgen] - rfl - · rw [← hygen] - rfl - · /- contra in hj: there is no i such that vldIn' = 1#1 -/ - unfold globallyValidUntilReady - intros j hj - specialize hnevldin (j + 1) - have : Stream'.drop 1 vldIn_1 j = vldIn_1 (j + 1) := by rfl - simp [this, hnevldin] at hj - · unfold globallyValidUntilReady - intros j hj - apply Classical.byContradiction - simp [Stream'.drop] at hj - have := hnoneout (1 + j) - simp [show vldOut1_1.get (j + 1) = vldOut1_1 (j + 1) by rfl] at hj - simp [Nat.add_comm (n := j), this] at hj - · unfold globallyValidUntilReady - intros j hj - apply Classical.byContradiction - simp [Stream'.drop] at hj - have := hnoneout2 (1 + j) - simp [show vldOut2_1.get (j + 1) = vldOut2_1 (j + 1) by rfl] at hj - simp [Nat.add_comm (n := j), this] at hj - · /- contra in hj: there is no i such that vldIn' = 1#1 -/ - unfold globallyValidAndData - intros j hj - have : Stream'.drop 1 vldIn_1 j = vldIn_1 (j + 1) := by rfl - specialize hnevldin (j + 1) - simp [this, hnevldin] at hj - · /- follows from `hgfrOut1'` -/ - unfold globallyFinallyReady at h_4 ⊢ - intros i - specialize h_4 (i + 1) - obtain ⟨j, hj⟩ := h_4 - exists j - have : Stream'.drop 1 rdOut1_1 (i + j) = rdOut1_1 ((i + j) + 1) := by rfl - rw [this, show i + j + 1 = i + 1 + j by omega, hj] - · unfold globallyFinallyReady at h_5 ⊢ - intros i - specialize h_5 (i + 1) - obtain ⟨j, hj⟩ := h_5 - exists j - have : Stream'.drop 1 rdOut2_1 (i + j) = rdOut2_1 ((i + j) + 1) := by rfl - rw [this, show i + j + 1 = i + 1 + j by omega, hj] - · /- after dropping one element, all the relations defined by the fork module remain. - We see this by unfolding the fork hypotheses -/ - unfold project_stream - simp - have h1 := fork'_of_all_none - (dataIn := Stream'.drop 1 dataIn_1) - (vldIn := Stream'.drop 1 vldIn_1) - (rdOut1 := Stream'.drop 1 rdOut1_1) - (rdOut2 := Stream'.drop 1 rdOut2_1) - (by - intro k - specialize hnevldin (k + 1) - simp [show Stream'.drop 1 vldIn_1 k = vldIn_1 (k + 1) by rfl, hnevldin] - ) - have h2 := fork'_of_all_none - (dataIn := dataIn_1) - (vldIn := vldIn_1) - (rdOut1 := rdOut1_1) - (rdOut2 := rdOut2_1) - (by grind) - rw [hw_fork_eq] - simp_all - and_intros - · rfl - · ext l n - have hlhs := hw_fork_out0 - (data_in := dataIn_1) - (vld_in := vldIn_1) - (rd0_in := rdOut1_1) - (rd1_in := rdOut2_1) - (rdy_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).1) - (vld0_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.1) - (vld1_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.1) - (data0_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) - (data1_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) - (by rw [← hw_fork_eq]; simp [project_stream]) (1 + l) - have hrhs := hw_fork_out0 - (rdy_out := fun i => - (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).1) - (vld0_out := fun i => - (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.1) - (vld1_out := fun i => - (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.1) - (data0_out := fun i => - (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.1) - (data1_out := fun i => - (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.2) - (by rw [← hw_fork_eq]; simp [project_stream]) l - simp [Stream'.drop] at hrhs - have h1 : Stream'.get (fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) (1 + l) = - (fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) (1 + l) := by rfl - simp [h1] - have h2 : (Stream'.get (fun i => - (rtl.fork' (Stream'.drop 1 rdOut1_1) - (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) - (Stream'.drop 1 dataIn_1) i).2.2.2.1) l) = - (fun i => - (rtl.fork' (Stream'.drop 1 rdOut1_1) - (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) - (Stream'.drop 1 dataIn_1) i).2.2.2.1) l := by rfl - simp [h2] - simp [← hrhs, ← hlhs] - simp [show dataIn_1.get (l + 1) = dataIn_1 (l + 1) by rfl, Nat.add_comm] - · ext l n - have hlhs := hw_fork_out1 - (data_in := dataIn_1) - (vld_in := vldIn_1) - (rd0_in := rdOut1_1) - (rd1_in := rdOut2_1) - (rdy_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).1) - (vld0_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.1) - (vld1_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.1) - (data0_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.1) - (data1_out := fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) - (by rw [← hw_fork_eq]; simp [project_stream]) (1 + l) - have hrhs := hw_fork_out1 - (rdy_out := fun i => - (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).1) - (vld0_out := fun i => - (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.1) - (vld1_out := fun i => - (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.1) - (data0_out := fun i => - (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.1) - (data1_out := fun i => - (rtl.fork' (Stream'.drop 1 rdOut1_1) (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) (Stream'.drop 1 dataIn_1) i).2.2.2.2) - (by rw [← hw_fork_eq]; simp [project_stream]) l - simp [Stream'.drop] at hrhs - - have h1 : Stream'.get (fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) (1 + l) = - (fun i => (rtl.fork' rdOut1_1 rdOut2_1 vldIn_1 dataIn_1 i).2.2.2.2) (1 + l) := by rfl - simp [h1] - have h2 : (Stream'.get (fun i => - (rtl.fork' (Stream'.drop 1 rdOut1_1) - (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) - (Stream'.drop 1 dataIn_1) i).2.2.2.2) l) = - (fun i => - (rtl.fork' (Stream'.drop 1 rdOut1_1) - (Stream'.drop 1 rdOut2_1) (Stream'.drop 1 vldIn_1) - (Stream'.drop 1 dataIn_1) i).2.2.2.2) l := by rfl - simp [h2] - simp [← hrhs, ← hlhs] - simp [show dataIn_1.get (l + 1) = dataIn_1 (l + 1) by rfl, Nat.add_comm] - · unfold toStream - congr - have : (fun i => if rdIn_1 i = 1#1 ∧ vldIn_1 i = 1#1 then some (dataIn_1 i) else none) = - fun i => none := by - ext k hk - grind - simp [this] - have : (fun i => if rdOut1_1 i = 1#1 ∧ vldOut1_1 i = 1#1 then some (dataOut1_1 i) else none) = - fun i => none := by - ext k hk - grind - simp [this] - · simp - · simp - · apply relation_fork.intro (toStream rdIn vldIn dataIn) (toStream rdOut1 vldOut1 dataOut1) - (dataOut2 := dataOut2) (vldOut2 := vldOut2) - · rfl - · rfl - · assumption - · assumption - · assumption - · congr - · assumption - · assumption - · assumption - - -theorem hw_fork_refines': - /- Given a handshake fork -/ - (x, y) = handshake.fork a → - /- we get the output of the corresponding lowered fork -/ - (rdy, vld1, vld2, o1, o2) = project_stream (a := BitVec 1) (rtl.fork rd1 rd2 vld data) → - /- if we know that the hshake input stream is bisimilar to the ready-valid input of the hw fork -/ - a ~ (toStream rdy vld data) → - /- We want to make sure that stalling is correctly modeled for `a` (input). - We constrain the input and prove that if the input behaves properly, - the output will. -/ - globallyValidUntilReady vld rdy → - globallyValidAndData vld data → - /- we assume no deadlock -/ - globallyFinallyReady rd1 → - globallyFinallyReady rd2 → - /- we want to prove that the outputs of the handshake fork are respectively - bisimilar to the ready-valid wrapping of the output of the hardware fork -/ - x ~ (toStream rd1 vld1 o1) ∧ y ~ (toStream rd2 vld2 o2) := by - intros handshake_fork hardware_fork inputs_bisim valready_ valdata_a finready1 finready2 - · unfold handshake.fork at handshake_fork - have heq : x = a := by - simp at handshake_fork - exact handshake_fork.1 - have heq' : y = a := by - simp at handshake_fork - exact handshake_fork.2 - rw [heq, heq'] - and_intros - · sorry - · sorry end HWComponents From f6f79982401fb490778f27580ef85c10a58b9d80 Mon Sep 17 00:00:00 2001 From: luisacicolini Date: Thu, 16 Jul 2026 17:14:45 +0100 Subject: [PATCH 11/13] add lemmas --- SSA/Projects/CIRCT/HandshakeToHW/add.lean | 277 ++++++++++++++++++++-- 1 file changed, 262 insertions(+), 15 deletions(-) diff --git a/SSA/Projects/CIRCT/HandshakeToHW/add.lean b/SSA/Projects/CIRCT/HandshakeToHW/add.lean index 637deaf535..9df2abbd8b 100644 --- a/SSA/Projects/CIRCT/HandshakeToHW/add.lean +++ b/SSA/Projects/CIRCT/HandshakeToHW/add.lean @@ -3,6 +3,7 @@ import SSA.Projects.CIRCT.Stream.Lemmas import SSA.Projects.CIRCT.Register.Basic import SSA.Projects.CIRCT.Register.Lemmas import SSA.Projects.CIRCT.Handshake.Handshake +import SSA.Projects.CIRCT.HandshakeToHW.HWForkSampling namespace HandshakeStream /-! @@ -15,6 +16,14 @@ namespace HandshakeStream of abstractions the content of streams has been concretized. We ignore buffers. + The `register_wrapper_generalized` definitions below are kept in one-to-one + correspondence with the compiler output (see the MLIR listings). The + *reasoning layer* (`Add` namespace at the end of this file) re-expresses the + composed circuit in the style of `HWForkSampling.lean` — every signal as a + pure function of the cycle index, the fork's `emitted` pair as the only + state — and connects the two via pointwise bridge lemmas, so that the `Fork` + library applies to the fork instance inside this composition. + See: https://github.com/opencompl/DC-semantics-simulation-evaluation/commit/bf86f7247a767d97516a05a29e313634e5172398 -/ @@ -177,19 +186,257 @@ def arith_addi_in_ui64_ui64_out_ui64 -- signals := #v[arg0_valid, out0_ready, out1_ready]} -- sorry +/-- + The composed `@add` module, in the same `register_wrapper_generalized` + encoding as the instantiated modules above. + + Contrary to what the sketch above suggests, **no fixed-point iteration is + needed** to wire the instances together: valids flow forward (they depend on + registers and input valids only) and readies flow backward (they depend on + the external `%out0_ready` and on valids only), so the instance graph is + combinationally acyclic. The composed `update_fun` is obtained by inlining + the two adders' ready/valid equations into the fork's; the only registers + are the fork's `emitted_0`/`emitted_1`. + + Input `signals` layout (as in the sketch above): + `#v[arg0_valid, arg1_valid, arg2, arg2_valid, out0_ready, out1_ready]`. + Output layout (as in `hw.output`): `result = #v[out0]`, + `signals = #v[arg0_ready, arg1_ready, arg2_ready, out0_valid, out1, out1_valid]`. +-/ +def add_rtl (inp : Stream' (wiresStruc 2 6 64)) : Stream' (wiresStruc 1 6 64) := + register_wrapper_generalized + (inputs := inp) + (init_regs := {result := #v[], signals := #v[0#1, 0#1]}) + (outops := 1) + (outsigs := 6) + (update_fun := fun (inp, regs) => + let a0v := inp.signals[0] -- arg0_valid + let a1v := inp.signals[1] -- arg1_valid + let arg2 := inp.signals[2] + let arg2v := inp.signals[3] + let or0 := inp.signals[4] -- out0_ready + let or1 := inp.signals[5] -- out1_ready + -- fork output valids (%3, %9 of the fork instance) + let f0v := (regs.signals[0] ^^^ 1#1) &&& a0v + let f1v := (regs.signals[1] ^^^ 1#1) &&& a0v + -- joins, forward (%0 of each addi instance) + let j0 := f0v &&& f1v -- arith_addi0.out0_valid + let j1 := j0 &&& a1v -- arith_addi1.out0_valid = out0_valid + -- readies, backward from %out0_ready (%1 of each addi instance) + let addi1_in_rdy := or0 &&& j1 -- arith_addi1.in0_ready = .in1_ready + let addi0_in_rdy := addi1_in_rdy &&& j0 -- arith_addi0.in{0,1}_ready = fork out readies + -- fork completion logic (%4, %5, %10, %11, %12 of the fork instance) + let done0 := (addi0_in_rdy &&& f0v) ||| regs.signals[0] + let done1 := (addi0_in_rdy &&& f1v) ||| regs.signals[1] + let allDone := done0 &&& done1 -- arg0_ready + let e0' := done0 &&& (allDone ^^^ 1#1) + let e1' := done1 &&& (allDone ^^^ 1#1) + -- data path + let out0 := (inp.result[0] + inp.result[0]) + inp.result[1] + ⟨{result := #v[out0], + signals := #v[allDone, addi1_in_rdy, or1, j1, arg2, arg2v]}, + {result := #v[], signals := #v[e0', e1']}⟩) + +/-! + ## Reasoning layer + + The composed circuit in the style of `HWForkSampling.lean`: every signal a + pure function of the cycle index, the fork's `emitted` pair as the only + state, and the `Fork` library reused through instantiation. +-/ +namespace Add + +open HWComponents + +variable (arg0Vld arg1Vld out0Rdy : Stream' (BitVec 1)) + +/-- The ready signal presented to *each* fork output by the adder chain, as a +pure function of the fork's register state `e` and the current inputs: the +external `out0_ready`, gated backward through `addi1`'s and `addi0`'s joins. +Both fork outputs receive this same signal. -/ +def readyThroughAdders (a0v a1v or0 : BitVec 1) (e : BitVec 1 × BitVec 1) : + BitVec 1 := + let f0v := comb_and (comb_xor e.1 (hw_constant true)) a0v -- fork.out0_valid + let f1v := comb_and (comb_xor e.2 (hw_constant true)) a0v -- fork.out1_valid + let j0 := comb_and f0v f1v -- addi0.out0_valid + let j1 := comb_and j0 a1v -- addi1.out0_valid + comb_and (comb_and or0 j1) j0 + +/-- Trajectory of the composed module's only registers — the fork's `emitted` +pair — under the readies computed by the adder chain. -/ +def regs : Nat → BitVec 1 × BitVec 1 + | 0 => (0#1, 0#1) + | n + 1 => + let rd := readyThroughAdders (arg0Vld n) (arg1Vld n) (out0Rdy n) (regs n) + Fork.stepRegs rd rd (arg0Vld n) (regs n) + +@[simp] theorem regs_zero : regs arg0Vld arg1Vld out0Rdy 0 = (0#1, 0#1) := rfl + +/-- The ready signal seen by both fork outputs, as a stream. -/ +def forkRdy (n : Nat) : BitVec 1 := + readyThroughAdders (arg0Vld n) (arg1Vld n) (out0Rdy n) + (regs arg0Vld arg1Vld out0Rdy n) + +theorem regs_succ (n : Nat) : + regs arg0Vld arg1Vld out0Rdy (n + 1) + = Fork.stepRegs (forkRdy arg0Vld arg1Vld out0Rdy n) + (forkRdy arg0Vld arg1Vld out0Rdy n) (arg0Vld n) + (regs arg0Vld arg1Vld out0Rdy n) := rfl + +/-- **Instantiation lemma**: the composed module's registers are exactly the +abstract fork's registers run against the environment `forkRdy` — the +fork-in-context is the abstract fork of `HWForkSampling.lean` applied to the +(self-consistent) readies computed by the adders, so the whole `Fork` library +applies to it. (Induction on `n`; both recursions step by `Fork.stepRegs` from +`(0#1, 0#1)`, and `forkRdy n` depends only on `regs n`, so the induction +hypothesis closes the loop.) -/ +theorem regs_eq_emitted (n : Nat) : + regs arg0Vld arg1Vld out0Rdy n + = Fork.emitted (forkRdy arg0Vld arg1Vld out0Rdy) + (forkRdy arg0Vld arg1Vld out0Rdy) arg0Vld n := by + sorry + +/-! Named signals of the composed module, defined through the `Fork` +instantiation so that the `Fork` library applies definitionally. -/ + +/-- Fork `out0_valid` inside the composition. -/ +def fork0Vld (n : Nat) : BitVec 1 := + Fork.vldOut1 (forkRdy arg0Vld arg1Vld out0Rdy) + (forkRdy arg0Vld arg1Vld out0Rdy) arg0Vld n + +/-- Fork `out1_valid` inside the composition. -/ +def fork1Vld (n : Nat) : BitVec 1 := + Fork.vldOut2 (forkRdy arg0Vld arg1Vld out0Rdy) + (forkRdy arg0Vld arg1Vld out0Rdy) arg0Vld n + +/-- Ready returned to the `arg0` producer (the fork's `in0_ready = allDone`). -/ +def arg0Rdy (n : Nat) : BitVec 1 := + Fork.allDone (forkRdy arg0Vld arg1Vld out0Rdy) + (forkRdy arg0Vld arg1Vld out0Rdy) arg0Vld n + +/-- `arith_addi0.out0_valid`: the join of the two fork outputs. -/ +def join0Vld (n : Nat) : BitVec 1 := + comb_and (fork0Vld arg0Vld arg1Vld out0Rdy n) + (fork1Vld arg0Vld arg1Vld out0Rdy n) + +/-- `arith_addi1.out0_valid = out0_valid` of the composed module. -/ +def out0Vld (n : Nat) : BitVec 1 := + comb_and (join0Vld arg0Vld arg1Vld out0Rdy n) (arg1Vld n) + +/-- Ready returned to the `arg1` producer (`arith_addi1.in1_ready`). -/ +def arg1Rdy (n : Nat) : BitVec 1 := + comb_and (out0Rdy n) (out0Vld arg0Vld arg1Vld out0Rdy n) + +variable (arg0 arg1 : Stream' (BitVec 64)) + +/-- Data path of the composed module: combinational, `out0 = (arg0 + arg0) + arg1`. -/ +def out0Data (n : Nat) : BitVec 64 := (arg0 n + arg0 n) + arg1 n + +/-! ### Bridge lemmas: compiler-output modules vs. named signals + +Pointwise characterizations of the `register_wrapper_generalized` definitions, +playing the role `hw_fork'_get` plays in `HWForkSampling.lean`. These are the +only lemmas that need to unfold `register_wrapper_generalized`. -/ + +/-- The fork module of the compiler output computes the `Fork` signals: with +`signals = #v[in0_valid, out0_ready, out1_ready]` in, it returns +`#v[allDone, vldOut1, vldOut2]` (and copies the data wire to both outputs). -/ +theorem handshake_fork_get (instruc : Stream' (wiresStruc 1 3 64)) (n : Nat) : + handshake_fork_in_ui64_out_ui64_ui64 instruc n + = { result := #v[(instruc n).result[0], (instruc n).result[0]], + signals := #v[ + Fork.allDone (fun k => (instruc k).signals[1]) + (fun k => (instruc k).signals[2]) + (fun k => (instruc k).signals[0]) n, + Fork.vldOut1 (fun k => (instruc k).signals[1]) + (fun k => (instruc k).signals[2]) + (fun k => (instruc k).signals[0]) n, + Fork.vldOut2 (fun k => (instruc k).signals[1]) + (fun k => (instruc k).signals[2]) + (fun k => (instruc k).signals[0]) n] } := by + sorry + +/-- The adder module of the compiler output is combinational join-and-add. -/ +theorem arith_addi_get (xst : Stream' (wiresStruc 2 3 64)) (n : Nat) : + arith_addi_in_ui64_ui64_out_ui64 xst n + = { result := #v[(xst n).result[0] + (xst n).result[1]], + signals := #v[ + comb_and ((xst n).signals[2]) + (comb_and ((xst n).signals[0]) ((xst n).signals[1])), + comb_and ((xst n).signals[2]) + (comb_and ((xst n).signals[0]) ((xst n).signals[1])), + comb_and ((xst n).signals[0]) ((xst n).signals[1])] } := by + sorry + +/-- The composed module of the compiler output computes the named signals of +this section (input `signals = #v[arg0_valid, arg1_valid, arg2, arg2_valid, +out0_ready, out1_ready]`). -/ +theorem add_rtl_get (inp : Stream' (wiresStruc 2 6 64)) (n : Nat) : + add_rtl inp n + = { result := #v[out0Data (fun k => (inp k).result[0]) + (fun k => (inp k).result[1]) n], + signals := #v[ + arg0Rdy (fun k => (inp k).signals[0]) (fun k => (inp k).signals[1]) + (fun k => (inp k).signals[4]) n, + arg1Rdy (fun k => (inp k).signals[0]) (fun k => (inp k).signals[1]) + (fun k => (inp k).signals[4]) n, + (inp n).signals[5], + out0Vld (fun k => (inp k).signals[0]) (fun k => (inp k).signals[1]) + (fun k => (inp k).signals[4]) n, + (inp n).signals[2], + (inp n).signals[3]] } := by + sorry + +/-! ### Composition facts -/ + +/-- **The fork never stalls inside this composition**: both fork outputs see +the same ready (`forkRdy`), and from clear registers both outputs are valid +together, so both receivers always accept in the same cycle — `allDone` fires +in the same cycle as the accepts and the registers never latch. (Induction on +`n`; the step is pointwise: `regs_succ`, `Fork.stepRegs`, `bv_decide`.) -/ +theorem regs_eq_zero (n : Nat) : + regs arg0Vld arg1Vld out0Rdy n = (0#1, 0#1) := by + sorry + +/-- With the registers identically clear the fork is transparent: `out0_valid` +is the conjunction of the input valids. (Pointwise from `regs_eq_zero`.) -/ +theorem out0Vld_eq (n : Nat) : + out0Vld arg0Vld arg1Vld out0Rdy n + = comb_and (arg0Vld n) (arg1Vld n) := by + sorry + +/-- With the registers identically clear, the ready returned to `arg0` is the +external ready gated by both valids: the composed module behaves as one +combinational join. (Pointwise from `regs_eq_zero`.) -/ +theorem arg0Rdy_eq (n : Nat) : + arg0Rdy arg0Vld arg1Vld out0Rdy n + = comb_and (out0Rdy n) (comb_and (arg0Vld n) (arg1Vld n)) := by + sorry + +/-! ### Correctness -/ + +/-- **Lowering correctness for the composed `add` module**: the handshake-level +program applied to the token streams of the two inputs is bisimilar to the +token stream of the RTL output. + +Proof plan: by `regs_eq_zero` and its corollaries the RTL side is a single +combinational join (`out0Vld_eq`, `arg0Rdy_eq`, data path `out0Data`); the +fork contributes no further proof obligations. What remains is the handshake +side: a sampling development for `syncMap₂`/`HandshakeOp.fork` (mirroring +`out1_sampling_bisim`) showing that the token stream of `syncMap₂ f xs ys` is +the `f`-image of the joined token streams. That join library is the next +reusable component. -/ +theorem add_lowering_correctness + (hvr0 : globallyValidUntilReady arg0Vld (arg0Rdy arg0Vld arg1Vld out0Rdy)) + (hvd0 : globallyValidAndData arg0Vld arg0) + (hvr1 : globallyValidUntilReady arg1Vld (arg1Rdy arg0Vld arg1Vld out0Rdy)) + (hvd1 : globallyValidAndData arg1Vld arg1) : + add_handshake + (toStream (arg0Rdy arg0Vld arg1Vld out0Rdy) arg0Vld arg0) + (toStream (arg1Rdy arg0Vld arg1Vld out0Rdy) arg1Vld arg1) + ~ toStream out0Rdy (out0Vld arg0Vld arg1Vld out0Rdy) + (out0Data arg0 arg1) := by + sorry -theorem lowering_correctness - (a b : Stream (BitVec 64)) -- handshake level - (a_readyvalid b_readyvalid : wiresStructStream 1 2 64) -- rtl level - (sig_readyValid : Vector (Stream' (BitVec 1)) 3) -- extra input signal - (hsig : ReadyValid sig_readyValid sig) - (hsig_a : ReadyValidStruc a_readyvalid a) (hsig_b : ReadyValidStruc b_readyvalid b) : - let inp : wiresStructStream 2 6 64 := { - result := #v[a_readyvalid.result[0], b_readyvalid.result[0]] - signals := #v[a_readyvalid.signals[1], b_readyvalid.signals[1], - sig_readyValid[0], sig_readyValid[2], - a_readyvalid.signals[0], b_readyvalid.signals[0]]} - let inp' := streams_to_wires inp - let rtl' := add_rtl inp' - let rtl := wires_to_streams rtl' - (add_handshake a b) ~ rtl.result[0] := by sorry +end Add +end HandshakeStream From 11fcd3282e2fb7b9f5fb87ba58d9d9670ed7984e Mon Sep 17 00:00:00 2001 From: luisacicolini Date: Fri, 17 Jul 2026 11:43:29 +0100 Subject: [PATCH 12/13] cleaned addition circuit --- SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean | 99 ++-- SSA/Projects/CIRCT/HandshakeToHW/add.lean | 278 ++++------ .../CIRCT/HandshakeToHW/transitivity.lean | 493 ++++++++++++++++++ 3 files changed, 636 insertions(+), 234 deletions(-) create mode 100644 SSA/Projects/CIRCT/HandshakeToHW/transitivity.lean diff --git a/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean b/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean index 87130f5a1e..7134a46442 100644 --- a/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean +++ b/SSA/Projects/CIRCT/HandshakeToHW/HWFork.lean @@ -20,15 +20,15 @@ def comb_xor (x y : BitVec 1) : BitVec 1 := BitVec.xor x y def comb_and (x y : BitVec 1) : BitVec 1 := BitVec.and x y @[bv_normalize, grind] -def comb_add (x y : BitVec 32) : BitVec 32 := BitVec.add x y +def comb_add (x y : BitVec w) : BitVec w := BitVec.add x y @[bv_normalize, grind] def comb_or (x y : BitVec 1) : BitVec 1 := BitVec.or x y namespace TRY1 -axiom esi_unwrap_vr : Stream (BitVec 32) → BitVec 1 → Stream (BitVec 32) × BitVec 1 -axiom esi_wrap_vr : Stream (BitVec 32) → BitVec 1 → Stream (BitVec 32) × BitVec 1 +axiom esi_unwrap_vr : Stream (BitVec w) → BitVec 1 → Stream (BitVec w) × BitVec 1 +axiom esi_wrap_vr : Stream (BitVec w) → BitVec 1 → Stream (BitVec w) × BitVec 1 /- This first implementation with all the "correct" types does not work because of the feedback between ready, valid and @@ -38,7 +38,7 @@ axiom esi_wrap_vr : Stream (BitVec 32) → BitVec 1 → Stream (BitVec 32) × Bi -/ #guard_msgs (drop error) in -def hw_fork_fails (_in0 : Stream (BitVec 32)) : Stream (BitVec 32) × Stream (BitVec 32) := +def hw_fork_fails (_in0 : Stream (BitVec w)) : Stream (BitVec w) × Stream (BitVec w) := let _true := hw_constant true let _false := hw_constant false let _2 := comb_xor _emitted_0 _true @@ -77,7 +77,7 @@ namespace TRY2 a `rdy` signal is received (no deadlock). -/ -def hw_fork (_in0 : Stream (BitVec 32)) : Stream (BitVec 32) × Stream (BitVec 32) := +def hw_fork (_in0 : Stream (BitVec w)) : Stream (BitVec w) × Stream (BitVec w) := (_in0, _in0) end TRY2 @@ -95,12 +95,12 @@ namespace TRY3 2. How do we model the nondeterministic signals (...some time later: we don't have to, we just expose them as streams) -/ -def hw_fork (_ready _ready_1 _valid : Stream' (BitVec 1)) (_in0 : Stream' (BitVec 32)) +def hw_fork (_ready _ready_1 _valid : Stream' (BitVec 1)) (_in0 : Stream' (BitVec w)) : Stream' ( BitVec 1 -- ready (_12) × BitVec 1 -- valid_0 (_3) × BitVec 1 -- valid_1 (_9) - × BitVec 32 -- rawOutput - × BitVec 32 -- rawOutput + × BitVec w -- rawOutput + × BitVec w -- rawOutput ) := Stream'.corec' (α := Nat × BitVec 1 × BitVec 1) (fun (i, _emitted_0, _emitted_1) => @@ -132,11 +132,11 @@ def hw_fork (_ready _ready_1 _valid : Stream' (BitVec 1)) (_in0 : Stream' (BitVe -/ def hw_add (_in0_valid _in1_valid _out0_ready : Stream' (BitVec 1)) - (_in0 _in1 : Stream' (BitVec 32)) + (_in0 _in1 : Stream' (BitVec w)) : Stream' ( BitVec 1 -- %in0_ready × BitVec 1 -- %in1_ready × BitVec 1 -- %out0_valid - × BitVec 32 -- %out0 + × BitVec w -- %out0 ) := Stream'.corec' (α := Nat) (fun i => @@ -155,31 +155,31 @@ def split_stream2 : Stream' (a × b × c × d × e) → Stream' a × Stream' b def combine_stream : Stream' a × Stream' b × Stream' c × Stream' d × Stream' e × Stream' f × Stream' g → Stream' (a × b × c × d × e × f × g) := fun gr i => (gr.1 i, gr.2.1 i, gr.2.2.1 i, gr.2.2.2.1 i, gr.2.2.2.2.1 i, gr.2.2.2.2.2.1 i, gr.2.2.2.2.2.2 i) -/-- +/- We have a working circuit, except that we took out the feedback into and output and an input. `fork_i_rdy -> add_out_rdy` -/ -def hw_add_fork af_a_valid af_b_valid af_a af_b af_o_rdy af_p_rdy add_out_rdy := - let add_a_valid := af_a_valid - let add_b_valid := af_b_valid - let add_a := af_a - let add_b := af_b - let (add_a_rdy, add_b_rdy, add_out_valid, add_out) := split_stream <| hw_add add_a_valid add_b_valid add_out_rdy add_a add_b - let fork_i_valid := add_out_valid - let fork_i := add_out - let fork_o_rdy := af_o_rdy - let fork_p_rdy := af_p_rdy - let (fork_i_rdy, fork_o_valid, fork_p_valid, fork_o, fork_p) := split_stream2 <| hw_fork fork_o_rdy fork_p_rdy fork_i_valid fork_i - combine_stream <| (fork_o_valid, fork_p_valid, fork_o, fork_p, add_a_rdy, add_b_rdy, fork_i_rdy) +-- def hw_add_fork af_a_valid af_b_valid af_a af_b af_o_rdy af_p_rdy add_out_rdy := +-- let add_a_valid := af_a_valid +-- let add_b_valid := af_b_valid +-- let add_a := af_a +-- let add_b := af_b +-- let (add_a_rdy, add_b_rdy, add_out_valid, add_out) := split_stream <| hw_add add_a_valid add_b_valid add_out_rdy add_a add_b +-- let fork_i_valid := add_out_valid +-- let fork_i := add_out +-- let fork_o_rdy := af_o_rdy +-- let fork_p_rdy := af_p_rdy +-- let (fork_i_rdy, fork_o_valid, fork_p_valid, fork_o, fork_p) := split_stream2 <| hw_fork fork_o_rdy fork_p_rdy fork_i_valid fork_i +-- combine_stream <| (fork_o_valid, fork_p_valid, fork_o, fork_p, add_a_rdy, add_b_rdy, fork_i_rdy) /-- The assumption is that you always converge in 2 steps, so this should faithfully implement add -> fork -/ -def hw_add_fork_fix af_a_valid af_b_valid af_a af_b af_o_rdy af_p_rdy := - let x := hw_add_fork af_a_valid af_b_valid af_a af_b af_o_rdy af_p_rdy (Stream'.const 0) - let x := hw_add_fork af_a_valid af_b_valid af_a af_b af_o_rdy af_p_rdy (fun i => (x i).2.2.2.2.2.2) - fun i => ((x i).1, (x i).2.1, (x i).2.2.1, (x i).2.2.2.1, (x i).2.2.2.2.1, (x i).2.2.2.2.2.1, (x i).2.2.2.2.2.2.1) +-- def hw_add_fork_fix af_a_valid af_b_valid af_a af_b af_o_rdy af_p_rdy := +-- let x := hw_add_fork af_a_valid af_b_valid af_a af_b af_o_rdy af_p_rdy (Stream'.const 0) +-- let x := hw_add_fork af_a_valid af_b_valid af_a af_b af_o_rdy af_p_rdy (fun i => (x i).2.2.2.2.2.2) +-- fun i => ((x i).1, (x i).2.1, (x i).2.2.1, (x i).2.2.2.1, (x i).2.2.2.2.1, (x i).2.2.2.2.2.1, (x i).2.2.2.2.2.2.1) def cyc {α} (l : List α) (h := by simp) := Stream'.cycle l h @@ -191,8 +191,8 @@ We can stabilise with two iterations: + We set `add_out_rdy` to that value, and check if `add_out_rdy` now equals `fork_i_rdy`. -/ -#eval Stream'.take 3 <| hw_add_fork_fix (cyc [0, 0, 1]) (cyc [0, 1, 1]) (cyc [11, 12, 13]) (cyc [21, 22, 23]) (cyc [1]) (cyc [1]) -#eval Stream'.take 3 <| hw_add_fork_fix (cyc [0, 0, 1]) (cyc [0, 1, 1]) (cyc [11, 12, 13]) (cyc [21, 22, 23]) (cyc [0, 0, 1]) (cyc [0, 0, 1]) +-- #eval Stream'.take 3 <| hw_add_fork_fix (cyc [0, 0, 1]) (cyc [0, 1, 1]) (cyc [11, 12, 13]) (cyc [21, 22, 23]) (cyc [1]) (cyc [1]) +-- #eval Stream'.take 3 <| hw_add_fork_fix (cyc [0, 0, 1]) (cyc [0, 1, 1]) (cyc [11, 12, 13]) (cyc [21, 22, 23]) (cyc [0, 0, 1]) (cyc [0, 0, 1]) /- #eval Stream'.take 1 <| hw_add_fork_fix (cyc [1]) (cyc [1]) (cyc [10]) (cyc [20]) (cyc [1]) (cyc [1]) - #eval Stream'.take 1 <| hw_add_fork_fix (cyc [1]) (cyc [1]) (cyc [10]) (cyc [20]) (cyc [1]) (cyc [1]) - #eval Stream'.take 1 <| hw_add_fork_fix (cyc [1]) (cyc [1]) (cyc [10]) (cyc [20]) (cyc [1]) (cyc [1]) -/ @@ -204,13 +204,13 @@ end TRY3 · delayed fork ~ normal fork -/ -/-- At the handshake level: (manual) delayed fork ~ normal fork: the outputs of the fork are bisimilar +/- At the handshake level: (manual) delayed fork ~ normal fork: the outputs of the fork are bisimilar for any delay (up to any numbers of `none` inserted, anywhere). -/ -theorem fork_refines {a x y x' y'} : - (x, y) = TRY2.hw_fork a → - x ~ x' → - y ~ y' → - x ~ x' ∧ y ~ y' := by grind +-- theorem fork_refines {a x y x' y'} : +-- (x, y) = TRY2.hw_fork a → +-- x ~ x' → +-- y ~ y' → +-- x ~ x' ∧ y ~ y' := by grind /-- Stream := Stream' (Option α) -/ def toStream {α} (rdy : Stream' (BitVec 1)) (vld : Stream' (BitVec 1)) (data : Stream' α) : Stream α := fun i => @@ -320,7 +320,7 @@ inductive relation_fork : Stream (BitVec w) → Stream (BitVec w) → Prop where /-- We unfold one step of the corecursive definition of `fork` -/ -def fork_corec (_ready _ready_1 _valid : Stream' (BitVec 1)) (_in0 : Stream' (BitVec 32)) := +def fork_corec (_ready _ready_1 _valid : Stream' (BitVec 1)) (_in0 : Stream' (BitVec w)) := fun (i, _emitted_0, _emitted_1) => let _true := hw_constant true let _false := hw_constant false @@ -341,12 +341,12 @@ def fork_corec (_ready _ready_1 _valid : Stream' (BitVec 1)) (_in0 : Stream' (Bi ((_12, _3, _9, _rawOutput, _rawOutput), (i+1, _1, _7)) /-- We re-define the fork circuit in terms of `fork_corec` -/ -def hw_fork' (_ready _ready_1 _valid : Stream' (BitVec 1)) (_in0 : Stream' (BitVec 32)) +def hw_fork' (_ready _ready_1 _valid : Stream' (BitVec 1)) (_in0 : Stream' (BitVec w)) : Stream' ( BitVec 1 -- ready (_12) × BitVec 1 -- valid_0 (_3) × BitVec 1 -- valid_1 (_9) - × BitVec 32 -- rawOutput - × BitVec 32 -- rawOutput + × BitVec w -- rawOutput + × BitVec w -- rawOutput ) := Stream'.corec' (α := Nat × BitVec 1 × BitVec 1) (fork_corec _ready _ready_1 _valid _in0) (0, 0#1, 0#1) @@ -354,7 +354,10 @@ def hw_fork' (_ready _ready_1 _valid : Stream' (BitVec 1)) (_in0 : Stream' (BitV /-- Prove that iterating `n` times starting from the `m`-th index of the stream yields the `n + m`-th index-/ -theorem fork_corec1 : +theorem fork_corec1 {w : Nat} + {rd0_in rd1_in vld_in : Stream' (BitVec 1)} + {data_in : Stream' (BitVec w)} + {m n : Nat} {x y : BitVec 1} : (Stream'.iterate (Prod.snd ∘ fork_corec rd0_in rd1_in vld_in data_in) (m, x, y) n).1 = n + m := by induction n generalizing m x y with | zero => grind [Stream'.iterate] @@ -484,7 +487,9 @@ theorem hw_fork_eq : TRY3.hw_fork rd0 rd1 vld data = hw_fork' rd0 rd1 vld data : unfold TRY3.hw_fork hw_fork' congr 1 -theorem vldOut1_implies_vldIn +theorem vldOut1_implies_vldIn {w : Nat} + {rdIn rdOut1 rdOut2 vldIn vldOut1 vldOut2 : Stream' (BitVec 1)} + {dataIn dataOut1 dataOut2 : Stream' (BitVec w)} {n : Nat} (h : (rdIn, vldOut1, vldOut2, dataOut1, dataOut2) = TRY3.split_stream2 (TRY3.hw_fork rdOut1 rdOut2 vldIn dataIn)) (hvld : vldOut1 n = 1#1) : vldIn n = 1#1 := by @@ -499,7 +504,7 @@ theorem vldOut1_implies_vldIn obtain ⟨a, b, c⟩ := s dsimp [fork_corec, comb_and, comb_xor, hw_constant] at hn have heq : a = n := by - have := @fork_corec1 rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 n + have := fork_corec1 (rd0_in := rdOut1) (rd1_in := rdOut2) (vld_in := vldIn) (data_in := dataIn) (m := 0) (x := 0#1) (y := 0#1) (n := n) rw [hst] at this simp at this assumption @@ -524,7 +529,7 @@ theorem vldOut2_implies_vldIn obtain ⟨a, b, c⟩ := s dsimp [fork_corec, comb_and, comb_xor, hw_constant] at hn have heq : a = n := by - have := @fork_corec1 rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 n + have := fork_corec1 (rd0_in := rdOut1) (rd1_in := rdOut2) (vld_in := vldIn) (data_in := dataIn) (m := 0) (x := 0#1) (y := 0#1) (n := n) rw [hst] at this simp at this assumption @@ -594,7 +599,7 @@ theorem vldOut_eq_vldIn_of_fork_unitl_sent simp [hsk] at hbk; subst hbk rw [iterate_back_succ, hsk] have hak : ak = k := by - have := @fork_corec1 rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 k + have := fork_corec1 (rd0_in := rdOut1) (rd1_in := rdOut2) (vld_in := vldIn) (data_in := dataIn) (m := 0) (x := 0#1) (y := 0#1) (n := k) simp [hsk] at this; omega have hk := hbef k (Nat.lt_succ_self k) simp only [Function.comp] @@ -644,7 +649,7 @@ theorem vldOut_eq_vldIn_of_fork_unitl_sent simp [h1] simp [hb] at hn have heq : a = n := by - have := @fork_corec1 rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 n + have := fork_corec1 (rd0_in := rdOut1) (rd1_in := rdOut2) (vld_in := vldIn) (data_in := dataIn) (m := 0) (x := 0#1) (y := 0#1) (n := n) rw [hst] at this simp at this assumption @@ -695,7 +700,7 @@ theorem vldOut_eq_vldIn_of_fork_unitl_sent2 obtain ⟨ak, bk, ck⟩ := sk simp [hsk] at hck; subst hck have hak : ak = k := by - have := @fork_corec1 rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 k + have := fork_corec1 (rd0_in := rdOut1) (rd1_in := rdOut2) (vld_in := vldIn) (data_in := dataIn) (m := 0) (x := 0#1) (y := 0#1) (n := k) grind have hvldk : vldOut2 k = vldIn ak := by have h := congr_fun hvldout2 k @@ -716,7 +721,7 @@ theorem vldOut_eq_vldIn_of_fork_unitl_sent2 have hvldInA : vldIn ak = 0#1 := by grind simp [hvldInA]; have heq : a = n := by - have := @fork_corec1 rdOut1 rdOut2 vldIn dataIn 0 0#1 0#1 n + have := fork_corec1 (rd0_in := rdOut1) (rd1_in := rdOut2) (vld_in := vldIn) (data_in := dataIn) (m := 0) (x := 0#1) (y := 0#1) (n := n) rw [hst] at this simp at this assumption diff --git a/SSA/Projects/CIRCT/HandshakeToHW/add.lean b/SSA/Projects/CIRCT/HandshakeToHW/add.lean index 9df2abbd8b..03f330c4d2 100644 --- a/SSA/Projects/CIRCT/HandshakeToHW/add.lean +++ b/SSA/Projects/CIRCT/HandshakeToHW/add.lean @@ -4,6 +4,7 @@ import SSA.Projects.CIRCT.Register.Basic import SSA.Projects.CIRCT.Register.Lemmas import SSA.Projects.CIRCT.Handshake.Handshake import SSA.Projects.CIRCT.HandshakeToHW.HWForkSampling +import SSA.Projects.CIRCT.HandshakeToHW.HWFork namespace HandshakeStream /-! @@ -16,14 +17,6 @@ namespace HandshakeStream of abstractions the content of streams has been concretized. We ignore buffers. - The `register_wrapper_generalized` definitions below are kept in one-to-one - correspondence with the compiler output (see the MLIR listings). The - *reasoning layer* (`Add` namespace at the end of this file) re-expresses the - composed circuit in the style of `HWForkSampling.lean` — every signal as a - pure function of the cycle index, the fork's `emitted` pair as the only - state — and connects the two via pointwise bridge lemmas, so that the `Fork` - library applies to the fork instance inside this composition. - See: https://github.com/opencompl/DC-semantics-simulation-evaluation/commit/bf86f7247a767d97516a05a29e313634e5172398 -/ @@ -77,35 +70,11 @@ def add_handshake (a b : Stream' (Option (BitVec 64))) := %12 = comb.and %5, %11 {sv.namehint = "allDone"} : i1 hw.output %12, %in0, %3, %in0, %9 : i1, i64, i1, i64, i1 } + + This fork is the same as the basic fork module. -/ -def handshake_fork_in_ui64_out_ui64_ui64 - (instruc : Stream' (wiresStruc 1 3 64)) : - Stream' (wiresStruc 2 3 64) := - register_wrapper_generalized - (inputs := instruc) - (init_regs := {result := #v[], signals := #v[0#1, 0#1]}) - (outops := 2) - (outsigs := 3) - (update_fun := - fun (inp, regs) => - let v2 := regs.signals[0] ^^^ 1#1 -- emitted_0 - let v3 := v2 &&& inp.signals[0] -- in0_valid - let v4 := inp.signals[1] &&& v3 -- out0_ready - let v5 := v4 ||| regs.signals[0] - let v8 := regs.signals[1] ^^^ 1#1 -- emitted_1 - let v9 := v8 &&& inp.signals[0] -- in0_valid - let v10 := inp.signals[2] &&& v9 -- out1_ready - let v11 := v10 ||| regs.signals[1] - let v12 := v5 &&& v11 - let v0 := v12 ^^^ 1#1 - let v1 := v5 &&& v0 - let v6 := v12 ^^^ 1#1 - let v7 := v11 &&& v6 - let updated_reg0 := v1 - let updated_reg1 := v7 - ⟨{result := #v[inp.result[0], inp.result[0]], signals := #v[v12, v3, v9]}, - {result := #v[], signals := #v[updated_reg0, updated_reg1]}⟩ - ) +def handshake_fork_in_ui64_out_ui64_ui64 (ready ready_1 valid : Stream' (BitVec 1)) (in0 : Stream' (BitVec 64)) := + HWComponents.TRY3.hw_fork ready ready_1 valid in0 /-- Second RTL module: @@ -117,23 +86,23 @@ def handshake_fork_in_ui64_out_ui64_ui64 hw.output %1, %1, %2, %0 : i1, i1, i64, i1 } + This circuit is purely combinational. + -/ -def arith_addi_in_ui64_ui64_out_ui64 - (xst : Stream' (wiresStruc 2 3 64)) : - Stream' (wiresStruc 1 3 64) := - register_wrapper_generalized - (inputs := xst) - (init_regs := {result := #v[], signals := #v[]}) - (outops := 1) - (outsigs := 3) - (update_fun := - fun (inp, regs) => - let v0 := inp.signals[0] &&& inp.signals[1] -- in0_valid &&& in1_valid - let v1 := inp.signals[2] &&& v0 -- out0_ready - let v2 := inp.result[0] + inp.result[1] - ⟨{result := #v[v2], signals := #v[v1, v1, v0]}, - {result := #v[], signals := #v[]}⟩ - ) +def arith_addi_in_ui64_ui64_out_ui64 (in0_valid in1_valid out0_ready: Stream' (BitVec 1)) (in0 in1 : Stream' (BitVec 64)) : + Stream' ( + BitVec 1 -- in0_ready + × BitVec 1 -- in1_ready + × BitVec 64 -- out0 + × BitVec 1 -- out0_valid + ) := + Stream'.corec' (α := Nat) (fun i => + let out0_valid := HWComponents.comb_and (in0_valid i) (in1_valid i) + let in0_ready := HWComponents.comb_and (out0_ready i) out0_valid + let out1_ready := HWComponents.comb_and (out0_ready i) out0_valid + let out0 := HWComponents.comb_add (in0 i) (in1 i) + ((in0_ready, out1_ready, out0, out0_valid), (i + 1)) + ) 0 /-- Third RTL module: @@ -157,85 +126,71 @@ def arith_addi_in_ui64_ui64_out_ui64 hw.output %handshake_fork0.in0_ready, %arith_addi1.in1_ready, %out1_ready, %arith_addi1.out0, %arith_addi1.out0_valid, %arg2, %arg2_valid : i1, i1, i1, i64, i1, i0, i1 } --/ --- def add_rtl - /- - xst.result[0] = arg0 - xst.result[1] = arg1 - xst.signals[0] = arg0_valid - xst.signals[1] = arg1_valid - xst.signals[2] = arg2 - xst.signals[3] = arg2_valid - xst.signals[4] = out0_ready - xst.signals[5] = out1_ready - -/ - -- (inp : Stream' (wiresStruc 2 6 64)) : Stream' (wiresStruc 1 6 64) := - -- let arg0 := inp.resul[0] - -- let arg1 := inp.resut[1] - -- let arg0_valid := inp.signal[0] - -- let arg1_valid := inp.signal[1] - -- let arg2 := inp.signal[2] - -- let arg2_valid := inp.signal[3] - -- let out0_ready := inp.signal[4] - -- let out1_ready := inp.signal[5] - -- let fork_in : wiresStruc 1 3 64 := - -- {result := #v[arg0], - -- /- `out0_ready` and `out1_ready` are incorrect (see above). - -- we need to iteratively compute all the values in the current state of the circuit - -- (until fixed point). -/ - -- signals := #v[arg0_valid, out0_ready, out1_ready]} - -- sorry -/-- - The composed `@add` module, in the same `register_wrapper_generalized` - encoding as the instantiated modules above. - - Contrary to what the sketch above suggests, **no fixed-point iteration is - needed** to wire the instances together: valids flow forward (they depend on - registers and input valids only) and readies flow backward (they depend on - the external `%out0_ready` and on valids only), so the instance graph is - combinationally acyclic. The composed `update_fun` is obtained by inlining - the two adders' ready/valid equations into the fork's; the only registers - are the fork's `emitted_0`/`emitted_1`. - - Input `signals` layout (as in the sketch above): - `#v[arg0_valid, arg1_valid, arg2, arg2_valid, out0_ready, out1_ready]`. - Output layout (as in `hw.output`): `result = #v[out0]`, - `signals = #v[arg0_ready, arg1_ready, arg2_ready, out0_valid, out1, out1_valid]`. + The composed `@add` module: we need to inline + the two adders' ready/valid equations into the fork's; the only registers are the fork's `emitted_0`/`emitted_1`. + + We also treat the `i0` type as `i1`, since the `BitVec 0` type in lean is degenerate. + -/ -def add_rtl (inp : Stream' (wiresStruc 2 6 64)) : Stream' (wiresStruc 1 6 64) := - register_wrapper_generalized - (inputs := inp) - (init_regs := {result := #v[], signals := #v[0#1, 0#1]}) - (outops := 1) - (outsigs := 6) - (update_fun := fun (inp, regs) => - let a0v := inp.signals[0] -- arg0_valid - let a1v := inp.signals[1] -- arg1_valid - let arg2 := inp.signals[2] - let arg2v := inp.signals[3] - let or0 := inp.signals[4] -- out0_ready - let or1 := inp.signals[5] -- out1_ready - -- fork output valids (%3, %9 of the fork instance) - let f0v := (regs.signals[0] ^^^ 1#1) &&& a0v - let f1v := (regs.signals[1] ^^^ 1#1) &&& a0v - -- joins, forward (%0 of each addi instance) - let j0 := f0v &&& f1v -- arith_addi0.out0_valid - let j1 := j0 &&& a1v -- arith_addi1.out0_valid = out0_valid - -- readies, backward from %out0_ready (%1 of each addi instance) - let addi1_in_rdy := or0 &&& j1 -- arith_addi1.in0_ready = .in1_ready - let addi0_in_rdy := addi1_in_rdy &&& j0 -- arith_addi0.in{0,1}_ready = fork out readies - -- fork completion logic (%4, %5, %10, %11, %12 of the fork instance) - let done0 := (addi0_in_rdy &&& f0v) ||| regs.signals[0] - let done1 := (addi0_in_rdy &&& f1v) ||| regs.signals[1] - let allDone := done0 &&& done1 -- arg0_ready - let e0' := done0 &&& (allDone ^^^ 1#1) - let e1' := done1 &&& (allDone ^^^ 1#1) - -- data path - let out0 := (inp.result[0] + inp.result[0]) + inp.result[1] - ⟨{result := #v[out0], - signals := #v[allDone, addi1_in_rdy, or1, j1, arg2, arg2v]}, - {result := #v[], signals := #v[e0', e1']}⟩) +def add_rtl (arg0_valid arg1_valid arg2 arg2_valid out0_ready out1_ready : Stream' (BitVec 1)) (arg0 arg1 : Stream' (BitVec 64)) : + Stream' ( + BitVec 1 -- arg0_ready + × BitVec 1 -- arg1_ready + × BitVec 1 -- arg2_ready + × BitVec 64 -- out0 + × BitVec 1 -- out0_valid + × BitVec 1 --out1 + × BitVec 1 --out1_valid + ) := + + Stream'.corec' (α := Nat × BitVec 1 × BitVec 1) (fun (i, _emitted_0, _emitted_1) => + /- + %handshake_fork0.in0_ready, %handshake_fork0.out0, %handshake_fork0.out0_valid, %handshake_fork0.out1, %handshake_fork0.out1_valid = + hw.instance "handshake_fork0" @handshake_fork_in_ui64_out_ui64_ui64 + (in0: %arg0: i64, in0_valid: %arg0_valid: i1, clock: %clock: !seq.clock, reset: %reset: i1, out0_ready: %arith_addi0.in0_ready: i1, out1_ready: %arith_addi0.in1_ready: i1) -> + (in0_ready: i1, out0: i64, out0_valid: i1, out1: i64, out1_valid: i1) + -/ + let _true := HWComponents.hw_constant true + let _false := HWComponents.hw_constant false + let _2 := HWComponents.comb_xor _emitted_0 _true + let fork_valid0 := HWComponents.comb_and _2 (arg0_valid i) + let _8 := HWComponents.comb_xor _emitted_1 _true + let fork_valid1 := HWComponents.comb_and _8 (arg0_valid i) + let fork_rawOutput := arg0 i + /- + %arith_addi0.in0_ready, %arith_addi0.in1_ready, %arith_addi0.out0, %arith_addi0.out0_valid = + hw.instance "arith_addi0" @arith_addi_in_ui64_ui64_out_ui64 + (in0: %handshake_fork0.out0: i64, in0_valid: %handshake_fork0.out0_valid: i1, in1: %handshake_fork0.out1: i64, in1_valid: %handshake_fork0.out1_valid: i1, out0_ready: %arith_addi1.in0_ready: i1) -> + (in0_ready: i1, in1_ready: i1, out0: i64, out0_valid: i1) + -/ + let add0_out0_valid := HWComponents.comb_and fork_valid0 fork_valid1 + let add0_out0 := HWComponents.comb_add fork_rawOutput fork_rawOutput + /- + %arith_addi1.in0_ready, %arith_addi1.in1_ready, %arith_addi1.out0, %arith_addi1.out0_valid = + hw.instance "arith_addi1" @arith_addi_in_ui64_ui64_out_ui64 + (in0: %arith_addi0.out0: i64, in0_valid: %arith_addi0.out0_valid: i1, in1: %arg1: i64, in1_valid: %arg1_valid: i1, out0_ready: %out0_ready: i1) -> + (in0_ready: i1, in1_ready: i1, out0: i64, out0_valid: i1) + + -/ + let add1_out0_valid := HWComponents.comb_and add0_out0_valid (arg1_valid i) + let add1_in0_ready := HWComponents.comb_and (out0_ready i) add1_out0_valid + let add1_in1_ready := HWComponents.comb_and (out0_ready i) add1_out0_valid + let add0_in0_ready := HWComponents.comb_and add1_in0_ready add0_out0_valid + let _4 := HWComponents.comb_and add0_in0_ready fork_valid0 + let _5 := HWComponents.comb_or _4 _emitted_0 -- done0 + let add0_in1_ready := HWComponents.comb_and add1_in0_ready add0_out0_valid + let _10 := HWComponents.comb_and add0_in1_ready fork_valid1 + let _11 := HWComponents.comb_or _10 _emitted_1 -- done1 + let fork_ready := HWComponents.comb_and _5 _11 -- allDone + let _0 := HWComponents.comb_xor fork_ready _true + let _6 := HWComponents.comb_xor fork_ready _true + let _7 := HWComponents.comb_and _11 _6 + let _1 := HWComponents.comb_and _5 _0 + let add1_out0 := HWComponents.comb_add add0_out0 (arg1 i) + ((fork_ready, add1_in1_ready, (out1_ready i), add1_out0, add1_out0_valid, (arg2 i), (arg2_valid i)), (i + 1, _1, _7)) + ) (0, 0#1, 0#1) + /-! ## Reasoning layer @@ -270,7 +225,7 @@ def regs : Nat → BitVec 1 × BitVec 1 let rd := readyThroughAdders (arg0Vld n) (arg1Vld n) (out0Rdy n) (regs n) Fork.stepRegs rd rd (arg0Vld n) (regs n) -@[simp] theorem regs_zero : regs arg0Vld arg1Vld out0Rdy 0 = (0#1, 0#1) := rfl +@[simp] theorem regs_zero : regs arg0Vld arg1Vld out0Rdy 0 = (0#1, 0#1) := by rfl /-- The ready signal seen by both fork outputs, as a stream. -/ def forkRdy (n : Nat) : BitVec 1 := @@ -281,7 +236,7 @@ theorem regs_succ (n : Nat) : regs arg0Vld arg1Vld out0Rdy (n + 1) = Fork.stepRegs (forkRdy arg0Vld arg1Vld out0Rdy n) (forkRdy arg0Vld arg1Vld out0Rdy n) (arg0Vld n) - (regs arg0Vld arg1Vld out0Rdy n) := rfl + (regs arg0Vld arg1Vld out0Rdy n) := by rfl /-- **Instantiation lemma**: the composed module's registers are exactly the abstract fork's registers run against the environment `forkRdy` — the @@ -294,7 +249,11 @@ theorem regs_eq_emitted (n : Nat) : regs arg0Vld arg1Vld out0Rdy n = Fork.emitted (forkRdy arg0Vld arg1Vld out0Rdy) (forkRdy arg0Vld arg1Vld out0Rdy) arg0Vld n := by - sorry + induction n + · simp [Fork.emitted] + · case _ m ihm => + simp [regs_succ, ihm, Fork.emitted] + /-! Named signals of the composed module, defined through the `Fork` instantiation so that the `Fork` library applies definitionally. -/ @@ -332,61 +291,6 @@ variable (arg0 arg1 : Stream' (BitVec 64)) /-- Data path of the composed module: combinational, `out0 = (arg0 + arg0) + arg1`. -/ def out0Data (n : Nat) : BitVec 64 := (arg0 n + arg0 n) + arg1 n -/-! ### Bridge lemmas: compiler-output modules vs. named signals - -Pointwise characterizations of the `register_wrapper_generalized` definitions, -playing the role `hw_fork'_get` plays in `HWForkSampling.lean`. These are the -only lemmas that need to unfold `register_wrapper_generalized`. -/ - -/-- The fork module of the compiler output computes the `Fork` signals: with -`signals = #v[in0_valid, out0_ready, out1_ready]` in, it returns -`#v[allDone, vldOut1, vldOut2]` (and copies the data wire to both outputs). -/ -theorem handshake_fork_get (instruc : Stream' (wiresStruc 1 3 64)) (n : Nat) : - handshake_fork_in_ui64_out_ui64_ui64 instruc n - = { result := #v[(instruc n).result[0], (instruc n).result[0]], - signals := #v[ - Fork.allDone (fun k => (instruc k).signals[1]) - (fun k => (instruc k).signals[2]) - (fun k => (instruc k).signals[0]) n, - Fork.vldOut1 (fun k => (instruc k).signals[1]) - (fun k => (instruc k).signals[2]) - (fun k => (instruc k).signals[0]) n, - Fork.vldOut2 (fun k => (instruc k).signals[1]) - (fun k => (instruc k).signals[2]) - (fun k => (instruc k).signals[0]) n] } := by - sorry - -/-- The adder module of the compiler output is combinational join-and-add. -/ -theorem arith_addi_get (xst : Stream' (wiresStruc 2 3 64)) (n : Nat) : - arith_addi_in_ui64_ui64_out_ui64 xst n - = { result := #v[(xst n).result[0] + (xst n).result[1]], - signals := #v[ - comb_and ((xst n).signals[2]) - (comb_and ((xst n).signals[0]) ((xst n).signals[1])), - comb_and ((xst n).signals[2]) - (comb_and ((xst n).signals[0]) ((xst n).signals[1])), - comb_and ((xst n).signals[0]) ((xst n).signals[1])] } := by - sorry - -/-- The composed module of the compiler output computes the named signals of -this section (input `signals = #v[arg0_valid, arg1_valid, arg2, arg2_valid, -out0_ready, out1_ready]`). -/ -theorem add_rtl_get (inp : Stream' (wiresStruc 2 6 64)) (n : Nat) : - add_rtl inp n - = { result := #v[out0Data (fun k => (inp k).result[0]) - (fun k => (inp k).result[1]) n], - signals := #v[ - arg0Rdy (fun k => (inp k).signals[0]) (fun k => (inp k).signals[1]) - (fun k => (inp k).signals[4]) n, - arg1Rdy (fun k => (inp k).signals[0]) (fun k => (inp k).signals[1]) - (fun k => (inp k).signals[4]) n, - (inp n).signals[5], - out0Vld (fun k => (inp k).signals[0]) (fun k => (inp k).signals[1]) - (fun k => (inp k).signals[4]) n, - (inp n).signals[2], - (inp n).signals[3]] } := by - sorry - /-! ### Composition facts -/ /-- **The fork never stalls inside this composition**: both fork outputs see diff --git a/SSA/Projects/CIRCT/HandshakeToHW/transitivity.lean b/SSA/Projects/CIRCT/HandshakeToHW/transitivity.lean new file mode 100644 index 0000000000..4d2558c74f --- /dev/null +++ b/SSA/Projects/CIRCT/HandshakeToHW/transitivity.lean @@ -0,0 +1,493 @@ +/- +This file was generated by Aristotle. + +Lean version: leanprover/lean4:v4.24.0 +Mathlib version: f897ebcf72cd16f89ab4577d0c826cd14afaafc7 +This project request had uuid: 7fcea134-cfac-4390-8a80-0d75c6fc938e +-/ + +/- +We define a stream type `MyStream` (as `Stream` is already defined in Mathlib) and a bisimulation relation `Bisim` on it. We prove that `Bisim` is an equivalence relation, specifically proving transitivity in `stream_bisim_trans`. Note that the theorem is named `stream_bisim_trans` because `trans` is a reserved name in Lean/Mathlib. The proof uses coinduction and several helper lemmas handling `none` values and stepping through the streams. +-/ + +import Mathlib + +open scoped BigOperators +open scoped Real +open scoped Nat +open scoped Classical +open scoped Pointwise + +set_option maxHeartbeats 0 +set_option maxRecDepth 4000 +set_option synthInstance.maxHeartbeats 20000 +set_option synthInstance.maxSize 128 + +set_option relaxedAutoImplicit false +set_option autoImplicit false + +noncomputable section + +#check Stream + +#check Stream' +#check Stream'.get +#check Stream'.drop + +def MyStream (β : Type) := Stream' (Option β) + +def BisimGen {α : Type} (R : MyStream α → MyStream α → Prop) (a b : MyStream α) : Prop := + ∃ n m, R (a.drop (n + 1)) (b.drop (m + 1)) ∧ + Stream'.get a n = Stream'.get b m ∧ + (∀ i < n, Stream'.get a i = none) ∧ + (∀ j < m, Stream'.get b j = none) + +lemma BisimGen_mono {α : Type} : Monotone (@BisimGen α) := by + -- To prove monotonicity, we need to show that if $R \subseteq S$, then $\text{BisimGen } R \subseteq \text{BisimGen } S$. + intros R S hRS x y hxy + simp [BisimGen]; + -- Since $R \subseteq S$, the condition for $BisimGen R x y$ implies the same condition for $BisimGen S x y$. + obtain ⟨n, m, hR, hxy⟩ := hxy; + use n, m; + aesop + +def Bisim {α : Type} : MyStream α → MyStream α → Prop := + OrderHom.gfp ⟨@BisimGen α, BisimGen_mono⟩ + +infix:50 " ~ " => Bisim + +theorem Bisim.coinduct {α : Type} {R : MyStream α → MyStream α → Prop} + (h : ∀ a b, R a b → BisimGen R a b) : + ∀ a b, R a b → a ~ b := by + aesop; + refine' ⟨ _, _ ⟩; + exact True; + aesop + +theorem Bisim.step {α : Type} {a b : MyStream α} {n m : Nat} : + Bisim (a.drop (n + 1)) (b.drop (m + 1)) → + Stream'.get a n = Stream'.get b m → + (∀ i < n, Stream'.get a i = none) → + (∀ j < m, Stream'.get b j = none) → + Bisim a b := by + intros h1 h2 h3 h4; + -- By definition of bisimilarity, we need to show that $a \sim b$. + unfold Bisim at *; simp_all +decide [ Stream'.get ] ; + -- Let's unfold the definition of the bisimulation relation. + unfold OrderHom.gfp at *; simp_all +decide [ BisimGen ] ; + -- Let's choose the relation R that includes the pairs (a, b) and (Stream'.drop (n + 1) a, Stream'.drop (m + 1) b). + obtain ⟨R, hR⟩ := h1; + use fun x y => x = a ∧ y = b ∨ R x y; + aesop; + intro x y hxy; aesop; + · constructor <;> aesop; + · have := left _ _ h_1; unfold BisimGen at this; aesop; + constructor <;> aesop + +#check Stream'.cons + +/- +Bisimulation is symmetric. +-/ +lemma Bisim_symm {α : Type} {a b : MyStream α} : a ~ b → b ~ a := by + intro hab; + -- By definition of bisimulation, we need to show that for all `n`, `a.get n = b.get n` and `a.drop n ≤ b.drop n` and `b.drop n ≤ a.drop n`. + apply Bisim.coinduct; + swap; + tauto; + intro a b hab; + obtain ⟨ n, m, hnm ⟩ := hab; + obtain ⟨ f, hf ⟩ := m; + aesop; + obtain ⟨ n, m, hnm ⟩ := left _ _ hnm; + refine' ⟨ m, n, _, _, _, _ ⟩ <;> aesop; + exact? + +/- +If two streams are bisimilar via witnesses n and m, then dropping any prefix of the first stream (up to n) preserves bisimilarity to the second stream. +-/ +lemma Bisim_drop_of_witness {α : Type} {a b : MyStream α} {n m : Nat} : + Bisim (a.drop (n + 1)) (b.drop (m + 1)) → + Stream'.get a n = Stream'.get b m → + (∀ i < n, Stream'.get a i = none) → + (∀ j < m, Stream'.get b j = none) → + ∀ k < n, Bisim (a.drop (k + 1)) b := by + intro h_bisim h_eq h_none_a h_none_b k hk + -- We want to show a.drop (k+1) ~ b + -- We can use Bisim.step with N = n - (k+1) and M = m + apply Bisim.step (n := n - (k + 1)) (m := m) + · -- Bisim (a.drop (k+1).drop (N+1)) (b.drop (m+1)) + -- a.drop (k+1).drop (n - (k+1) + 1) = a.drop (n+1) + convert h_bisim using 1; + rw [ Stream'.drop_drop, tsub_add_eq_add_tsub ( by linarith ) ]; + rw [ add_tsub_cancel_of_le ( by linarith ) ] + · -- get + norm_num +zetaDelta at *; + grind + · -- none a + exact fun i hi => by simpa [ Nat.add_comm ] using h_none_a ( k + 1 + i ) ( by linarith [ Nat.sub_add_cancel ( by linarith : k + 1 ≤ n ) ] ) ; + · -- none b + assumption + +/- +Unfolding lemma for Bisim. +-/ +lemma Bisim_eq {α : Type} {a b : MyStream α} : Bisim a b ↔ BisimGen Bisim a b := by + have h_bisim_rec : Bisim = fun a b => BisimGen (Bisim : MyStream α → MyStream α → Prop) a b := by + apply le_antisymm; + · apply OrderHom.gfp_le; + intro R hR; + -- Since R is a bisimulation, we have R ≤ Bisim. + have hR_le_Bisim : R ≤ Bisim := by + apply Bisim.coinduct; assumption; + intro a b hab; + exact hR a b hab |> fun ⟨ n, m, hnm, h_eq, h_left, h_right ⟩ => ⟨ n, m, hR_le_Bisim _ _ hnm, h_eq, h_left, h_right ⟩; + · intro a b h; + convert Bisim.step _ _ _ _; + exact h.choose + exact h.choose_spec.choose + exact h.choose_spec.choose_spec.1 + exact h.choose_spec.choose_spec.2.1 + exact h.choose_spec.choose_spec.2.2.1 + exact h.choose_spec.choose_spec.2.2.2; + exact? + +/- +If a stream matches another stream after dropping a prefix of nones, then it matches from the beginning. +-/ +lemma Bisim_cons_none {α : Type} {a b : MyStream α} {k : Nat} : + Bisim (a.drop (k + 1)) b → + (∀ i ≤ k, Stream'.get a i = none) → + Bisim a b := by + -- Let's unfold the BisimGen relation. + intros h_drop h_none + rw [Bisim_eq]; + -- Assume `a.drop (k+1) ~ b`. Then `BisimGen Bisim (a.drop (k+1)) b`. + obtain ⟨n', m', h_gen, h_eq, h_none_left, h_none_right⟩ : ∃ n' m', Bisim (a.drop (k + 1 + n' + 1)) (b.drop (m' + 1)) ∧ (a.drop (k + 1)).get n' = b.get m' ∧ (∀ i < n', (a.drop (k + 1)).get i = none) ∧ (∀ j < m', b.get j = none) := by + rw [Bisim_eq] at h_drop; + cases h_drop ; aesop; + use k + 1 + n', m'; + aesop; + by_cases hi : i ≤ k; + · exact h_none i hi; + · convert h_none_left ( i - ( k + 1 ) ) ( by omega ) using 1; + rw [ Nat.add_sub_cancel' ( by linarith ) ] + +/- +If a stream matches another stream after dropping a prefix of nones, then it matches from the beginning. +-/ +lemma Bisim_cons_none_v2 {α : Type} {a b : MyStream α} {k : Nat} : + Bisim (a.drop (k + 1)) b → + (∀ i ≤ k, Stream'.get a i = none) → + Bisim a b := by + exact? + +/- +If a stream matches another stream after dropping a prefix of nones, then it matches from the beginning. +-/ +lemma Bisim_cons_none_v3 {α : Type} {a b : MyStream α} {k : Nat} : + Bisim (a.drop (k + 1)) b → + (∀ i ≤ k, Stream'.get a i = none) → + Bisim a b := by + exact? + +/- +Bisimulation is reflexive. +-/ +lemma Bisim_refl {α : Type} (a : MyStream α) : a ~ a := by + apply Bisim.coinduct (R := fun x y => x = y) + · intro x y h + rw [h] + use 0, 0 + simp + · rfl + +/- +If a stream matches another stream after dropping a prefix of nones, then it matches from the beginning. +-/ +lemma Bisim_cons_none_final {α : Type} {a b : MyStream α} {k : Nat} : + Bisim (a.drop (k + 1)) b → + (∀ i ≤ k, Stream'.get a i = none) → + Bisim a b := by + exact? + +/- +Dropping a prefix of the second stream preserves bisimilarity if the prefix consists of nones. +-/ +lemma Bisim_drop_right {α : Type} {a b : MyStream α} {n m : Nat} : + Bisim (a.drop (n + 1)) (b.drop (m + 1)) → + Stream'.get a n = Stream'.get b m → + (∀ i < n, Stream'.get a i = none) → + (∀ j < m, Stream'.get b j = none) → + ∀ k < m, Bisim a (b.drop (k + 1)) := by + intros h_bisim h_eq h_none_a h_none_b k hk + apply Bisim_symm + apply Bisim_drop_of_witness (n := m) (m := n) + · apply Bisim_symm + exact h_bisim + · rw [h_eq] + · exact h_none_b + · exact h_none_a + · exact hk + +/- +If a stream matches another stream after dropping a prefix of nones, then it matches from the beginning. +-/ +lemma Bisim_cons_none_proven {α : Type} {a b : MyStream α} {k : Nat} : + Bisim (a.drop (k + 1)) b → + (∀ i ≤ k, Stream'.get a i = none) → + Bisim a b := by + bound; + -- Apply the lemma Bisim_cons_none_final with the given hypotheses. + apply Bisim_cons_none_final a_1 a_2 + +/- +Bisimulation implies the transitivity relation. +-/ +lemma Bisim_le_R {α : Type} {a c : MyStream α} : a ~ c → ∃ b, a ~ b ∧ b ~ c := by + intro h + use c + constructor + · exact h + · apply Bisim_refl + +/- +Bisimulation skips nones. +-/ +lemma Bisim_skip_nones {α : Type} {a b : MyStream α} {k : Nat} : + Bisim a b → + (∀ i < k, Stream'.get b i = none) → + ∃ n m, Bisim (a.drop (n + 1)) (b.drop (m + 1)) ∧ + Stream'.get a n = Stream'.get b m ∧ + (∀ i < n, Stream'.get a i = none) ∧ + (∀ j < m, Stream'.get b j = none) ∧ + m ≥ k := by + intro h₁ h₂; induction' k with k ih; + · rw [ Bisim_eq ] at h₁; aesop; + · obtain ⟨ n, m, h₃, h₄, h₅, h₆, h₇ ⟩ := ih fun i hi => h₂ i ( Nat.lt_succ_of_lt hi ); + by_cases h₈ : m = k; + · -- Since $m = k$, we can apply the induction hypothesis to $m + 1$. + obtain ⟨ n', m', h₈, h₉, h₁₀, h₁₁ ⟩ := Bisim_eq.mp h₃; + use n + 1 + n', m + 1 + m'; ( + simp_all +arith +decide [ Stream'.get ]; + aesop; + · simp_all +arith +decide [ Stream'.drop ]; + exact h₉; + · by_cases hi : i < n + 1; + · cases lt_or_eq_of_le ( Nat.le_of_lt_succ hi ) <;> aesop; + · cases le_iff_exists_add'.mp ( by linarith : n + 1 ≤ i ) ; aesop; + convert h₁₀ ( w ) ( by linarith ) using 1; + · by_cases hj : j ≤ m; + · exact h₂ j hj; + · specialize h₁₁ ( j - ( m + 1 ) ) ; simp_all +arith +decide [ Nat.sub_add_cancel ( by linarith : m + 1 ≤ j ) ]; + by_cases hj' : j - ( m + 1 ) < m' <;> simp_all +decide [ Stream'.drop ]; + · rwa [ Nat.sub_add_cancel ( by linarith ) ] at h₁₁; + · grind); + · exact ⟨ n, m, h₃, h₄, h₅, h₆, Nat.lt_of_le_of_ne h₇ ( Ne.symm h₈ ) ⟩ + +/- +If a stream starts with none, dropping the first element preserves bisimilarity. +-/ +lemma Bisim_drop_none_left {α : Type} {a b : MyStream α} : + Bisim a b → Stream'.get a 0 = none → Bisim (a.drop 1) b := by + intro h; + -- Unfold `a ~ b` to `n, m`. + obtain ⟨n, m, h_next⟩ := Bisim_eq.mp h; + rcases n with ( _ | n ) <;> aesop; + · rw [ eq_comm ] at left_1 ; aesop; + -- By `Bisim_cons_none_proven`, since `b.drop (m+1)` is bisimilar to `a.drop 1` and `b` has nones up to `m+1`, we can conclude that `b` is bisimilar to `a.drop 1`. + have h_bisim : Bisim b (Stream'.drop 1 a) := by + apply Bisim_cons_none_proven; + exact?; + exact fun i hi => if hi' : i < m then right i hi' else by rw [ le_antisymm hi ( Nat.le_of_not_lt hi' ) ] ; assumption; + exact?; + · exact Bisim_drop_of_witness left left_1 left_2 right 0 ( Nat.zero_lt_succ _ ) + +/- +Bisimulation exact match for values. +-/ +lemma Bisim_match_some {α : Type} {a b : MyStream α} {k : Nat} {v : α} : + Bisim a b → + (∀ i < k, Stream'.get b i = none) → + Stream'.get b k = some v → + ∃ l, Stream'.get a l = some v ∧ + (∀ i < l, Stream'.get a i = none) ∧ + Bisim (a.drop (l + 1)) (b.drop (k + 1)) := by + intro h_bisim h_none h_some + obtain ⟨n, m, h_next, h_eq, h_none_a, h_none_b, hm⟩ := Bisim_skip_nones h_bisim h_none + have h_mk : m = k := by + by_contra h_ne + have h_gt : m > k := lt_of_le_of_ne hm (Ne.symm h_ne) + have h_none_k : Stream'.get b k = none := h_none_b k h_gt + rw [h_some] at h_none_k + contradiction + subst h_mk + use n + refine ⟨?_, h_none_a, h_next⟩ + rw [h_eq, h_some] + +/- +Bisimulation preserves all nones. +-/ +lemma Bisim_all_nones {α : Type} {a b : MyStream α} : + Bisim a b → (∀ i, Stream'.get a i = none) → (∀ j, Stream'.get b j = none) := by + intro h; + -- Assume b has a value v at position j. Let k be the index of the first value in b. + by_contra h_contra + obtain ⟨j, v, hv⟩ : ∃ j v, b.get j = some v ∧ ∀ i < j, b.get i = none := by + aesop; + exact ⟨ Nat.find ( ⟨ w, by aesop ⟩ : ∃ i, Stream'.get b i ≠ none ), ⟨ Classical.choose ( Option.ne_none_iff_exists'.mp ( Nat.find_spec ( ⟨ w, by aesop ⟩ : ∃ i, Stream'.get b i ≠ none ) ) ), Classical.choose_spec ( Option.ne_none_iff_exists'.mp ( Nat.find_spec ( ⟨ w, by aesop ⟩ : ∃ i, Stream'.get b i ≠ none ) ) ) ⟩, fun i hi => by aesop ⟩; + have := Bisim_match_some h hv.2 hv.1; + aesop + +/- +Streams of all nones are bisimilar. +-/ +lemma Bisim_all_nones_bisim {α : Type} {a b : MyStream α} : + (∀ i, Stream'.get a i = none) → (∀ j, Stream'.get b j = none) → a ~ b := by + intros ha hb + apply Bisim.coinduct (R := fun x y => (∀ i, Stream'.get x i = none) ∧ (∀ j, Stream'.get y j = none)) + · intro x y h + rcases h with ⟨hx, hy⟩ + use 0, 0 + refine ⟨?_, ?_, ?_, ?_⟩ + · constructor + · intro i + rw [Stream'.get_drop] + apply hx + · intro j + rw [Stream'.get_drop] + apply hy + · rw [hx 0, hy 0] + · intro i hi; omega + · intro j hj; omega + · exact ⟨ha, hb⟩ + +/- +Bisimulation satisfies the generator property for transitivity. +-/ +lemma BisimGen_trans {α : Type} {x z : MyStream α} : + (∃ y, x ~ y ∧ y ~ z) → BisimGen (fun a b => ∃ c, a ~ c ∧ c ~ b) x z := by + cases isEmpty_or_nonempty α <;> aesop; + · -- Since α is empty, any element in α must be none. Therefore, BisimGen holds because both components are none. + use 0, 0; + aesop; + · have h_all_nones : ∀ s : MyStream α, (∀ i, (s.get i) = none) := by + exact fun s i => Option.eq_none_iff_forall_not_mem.mpr fun x hx => h.elim x; + exact ⟨ z, by exact Bisim_all_nones_bisim ( fun i => h_all_nones _ _ ) ( fun i => h_all_nones _ _ ), by exact Bisim_all_nones_bisim ( fun i => h_all_nones _ _ ) ( fun i => h_all_nones _ _ ) ⟩; + · exact Subsingleton.elim _ _; + · -- Split into cases based on whether z has a value or not. + by_cases hz : ∃ k v, z.get k = some v ∧ ∀ i < k, z.get i = none; + · obtain ⟨ k, v, hv₁, hv₂ ⟩ := hz; + -- By definition of bisimulation, there exists some $l, m$ such that $x \sim y$, $y \sim z$, and $x$ and $y$ match at $l, m$. + obtain ⟨ l, hl₁, hl₂, hl₃ ⟩ := Bisim_match_some right hv₂ hv₁; + -- By definition of bisimulation, there exists some $n, m$ such that $x \sim y$, $y \sim z$, and $x$ and $y$ match at $n, m$. + obtain ⟨ n, hn₁, hn₂, hn₃ ⟩ := Bisim_match_some left hl₂ hl₁; + refine' ⟨ n, k, _, _, _, _ ⟩ <;> aesop; + · -- Since z has no values, it must be all nones. + have hz_all_nones : ∀ k, z.get k = none := by + contrapose! hz; + -- By the well-ordering principle, there exists a least element in the set of indices where `z` has a value. + obtain ⟨k, hk⟩ : ∃ k, z.get k ≠ none ∧ ∀ j < k, z.get j = none := by + exact ⟨ Nat.find hz, Nat.find_spec hz, fun j hj => by aesop ⟩; + cases h : z.get k <;> aesop; + -- Since w is bisimilar to z and z is all nones, w must also be all nones. + have hw_all_nones : ∀ k, w.get k = none := by + have := Bisim_all_nones ( Bisim_symm ‹_› ) ; aesop; + -- Since x is bisimilar to w and w is all nones, x must also be all nones. + have hx_all_nones : ∀ k, x.get k = none := by + apply Bisim_all_nones; + exacts [ Bisim_symm left, hw_all_nones ]; + use 0, 0; + aesop; + use w.drop 1; + aesop; + · exact?; + · exact? + +/- +Bisimulation preserves all nones. +-/ +lemma Bisim_all_nones_v2 {α : Type} {a b : MyStream α} : + Bisim a b → (∀ i, Stream'.get a i = none) → (∀ j, Stream'.get b j = none) := by + exact? + +/- +Bisimulation preserves all nones. +-/ +lemma Bisim_all_nones_proven {α : Type} {a b : MyStream α} : + Bisim a b → (∀ i, Stream'.get a i = none) → (∀ j, Stream'.get b j = none) := by + exact? + +/- +Bisimulation satisfies the generator property for transitivity. +-/ +lemma BisimGen_trans_proven {α : Type} {x z : MyStream α} : + (∃ y, x ~ y ∧ y ~ z) → BisimGen (fun a b => ∃ c, a ~ c ∧ c ~ b) x z := by + exact? + +/- +Bisimulation generator property for all nones case. +-/ +lemma BisimGen_trans_none {α : Type} {x y z : MyStream α} : + Bisim x y → Bisim y z → (∀ k, Stream'.get z k = none) → + BisimGen (fun a b => ∃ c, a ~ c ∧ c ~ b) x z := by + intro hxy hyz h_none_z + have h_none_y : ∀ i, Stream'.get y i = none := Bisim_all_nones_proven (Bisim_symm hyz) h_none_z + have h_none_x : ∀ i, Stream'.get x i = none := Bisim_all_nones_proven (Bisim_symm hxy) h_none_y + use 0, 0 + refine ⟨?_, ?_, ?_, ?_⟩ + · use y.drop 1 + constructor + · apply Bisim_all_nones_bisim + · intro i; rw [Stream'.get_drop]; apply h_none_x + · intro i; rw [Stream'.get_drop]; apply h_none_y + · apply Bisim_all_nones_bisim + · intro i; rw [Stream'.get_drop]; apply h_none_y + · intro i; rw [Stream'.get_drop]; apply h_none_z + · rw [h_none_x 0, h_none_z 0] + · intro i hi; omega + · intro j hj; omega + +/- +Bisimulation generator property for value case. +-/ +lemma BisimGen_trans_some {α : Type} {x y z : MyStream α} : + Bisim x y → Bisim y z → (∃ k, Stream'.get z k ≠ none) → + BisimGen (fun a b => ∃ c, a ~ c ∧ c ~ b) x z := by + simp +zetaDelta at *; + intro hxy hyz k hk_nonnone + by_contra h_contra; + exact h_contra ( BisimGen_trans <| by aesop ) + +/- +Bisimulation satisfies the generator property for transitivity (final). +-/ +lemma BisimGen_trans_final {α : Type} {x z : MyStream α} : + (∃ y, x ~ y ∧ y ~ z) → BisimGen (fun a b => ∃ c, a ~ c ∧ c ~ b) x z := by + intro h + obtain ⟨y, hxy, hyz⟩ := h + by_cases h_val : ∃ k, Stream'.get z k ≠ none + · exact BisimGen_trans_some hxy hyz h_val + · push_neg at h_val + exact BisimGen_trans_none hxy hyz h_val + +/- +Transitivity of bisimulation. +-/ +theorem stream_bisim_trans {α : Type} {a b c : MyStream α} : a ~ b → b ~ c → a ~ c := by + intros hab hbc + apply Bisim.coinduct (R := fun x z => ∃ y, x ~ y ∧ y ~ z) + · intro x z h + exact BisimGen_trans_final h + · exact ⟨b, hab, hbc⟩ + +/- +Transitivity of bisimulation. +-/ +theorem bisim_transitivity {α : Type} {a b c : MyStream α} : a ~ b → b ~ c → a ~ c := by + intros hab hbc + apply Bisim.coinduct (R := fun x z => ∃ y, x ~ y ∧ y ~ z) + · intro x z h + exact BisimGen_trans_final h + · exact ⟨b, hab, hbc⟩ From 832a74d2df0c0190b9213d7b45e3e5b174c77306 Mon Sep 17 00:00:00 2001 From: luisacicolini Date: Fri, 17 Jul 2026 14:06:31 +0100 Subject: [PATCH 13/13] add --- SSA/Projects/CIRCT/Handshake/Handshake.lean | 20 ++ SSA/Projects/CIRCT/HandshakeToHW/add.lean | 253 ++++++++++++++++++-- SSA/Projects/CIRCT/Stream/Lemmas.lean | 101 ++++++++ 3 files changed, 353 insertions(+), 21 deletions(-) diff --git a/SSA/Projects/CIRCT/Handshake/Handshake.lean b/SSA/Projects/CIRCT/Handshake/Handshake.lean index bf0aaf0716..6b3409cd7b 100644 --- a/SSA/Projects/CIRCT/Handshake/Handshake.lean +++ b/SSA/Projects/CIRCT/Handshake/Handshake.lean @@ -120,6 +120,26 @@ def fork (x : Stream α) : Stream α × Stream α := let x' := x.tail (x0, x0, x') +/-- The handshake fork duplicates its input stream: both outputs are `x` +itself. (Its `corec_prod` emits the current head twice and advances by +`tail`, so the corec state after `n` steps is `x.drop n` and the output at +position `n` is `x n` on both sides.) -/ +theorem fork_eq (x : Stream α) : fork x = (x, x) := by + have hiter : ∀ (n : Nat), + Stream'.iterate Stream'.tail x n = Stream'.drop n x := by + intro n + induction n with + | zero => rfl + | succ k ih => + show Stream'.tail (Stream'.iterate Stream'.tail x k) = _ + rw [ih] + exact Stream'.tail_drop' + refine Prod.ext ?_ ?_ <;> funext n <;> + · show ((Stream'.iterate Stream'.tail x n) 0 : Option α) = x n + rw [hiter] + show x.get (0 + n) = x.get n + rw [Nat.zero_add] + -- not entirely nondeterministic (still picks left first) def controlMerge (x y : Stream α) : Stream α × Stream (BitVec 1) := corec_prod (β := Stream α × Stream α) (x, y) fun ⟨x, y⟩ => diff --git a/SSA/Projects/CIRCT/HandshakeToHW/add.lean b/SSA/Projects/CIRCT/HandshakeToHW/add.lean index 03f330c4d2..03babab149 100644 --- a/SSA/Projects/CIRCT/HandshakeToHW/add.lean +++ b/SSA/Projects/CIRCT/HandshakeToHW/add.lean @@ -191,6 +191,66 @@ def add_rtl (arg0_valid arg1_valid arg2 arg2_valid out0_ready out1_ready : Strea ((fork_ready, add1_in1_ready, (out1_ready i), add1_out0, add1_out0_valid, (arg2 i), (arg2_valid i)), (i + 1, _1, _7)) ) (0, 0#1, 0#1) +/-- The update function of `add_rtl`, extracted verbatim (the analogue of +`fork_corec` for the fork): one combinational cycle of the composed module as +a function of the corec state `(i, emitted_0, emitted_1)`. -/ +def add_rtl_corec (arg0_valid arg1_valid arg2 arg2_valid out0_ready out1_ready : + Stream' (BitVec 1)) (arg0 arg1 : Stream' (BitVec 64)) := + fun ((i, _emitted_0, _emitted_1) : Nat × BitVec 1 × BitVec 1) => + let _true := HWComponents.hw_constant true + let _false := HWComponents.hw_constant false + let _2 := HWComponents.comb_xor _emitted_0 _true + let fork_valid0 := HWComponents.comb_and _2 (arg0_valid i) + let _8 := HWComponents.comb_xor _emitted_1 _true + let fork_valid1 := HWComponents.comb_and _8 (arg0_valid i) + let fork_rawOutput := arg0 i + let add0_out0_valid := HWComponents.comb_and fork_valid0 fork_valid1 + let add0_out0 := HWComponents.comb_add fork_rawOutput fork_rawOutput + let add1_out0_valid := HWComponents.comb_and add0_out0_valid (arg1_valid i) + let add1_in0_ready := HWComponents.comb_and (out0_ready i) add1_out0_valid + let add1_in1_ready := HWComponents.comb_and (out0_ready i) add1_out0_valid + let add0_in0_ready := HWComponents.comb_and add1_in0_ready add0_out0_valid + let _4 := HWComponents.comb_and add0_in0_ready fork_valid0 + let _5 := HWComponents.comb_or _4 _emitted_0 -- done0 + let add0_in1_ready := HWComponents.comb_and add1_in0_ready add0_out0_valid + let _10 := HWComponents.comb_and add0_in1_ready fork_valid1 + let _11 := HWComponents.comb_or _10 _emitted_1 -- done1 + let fork_ready := HWComponents.comb_and _5 _11 -- allDone + let _0 := HWComponents.comb_xor fork_ready _true + let _6 := HWComponents.comb_xor fork_ready _true + let _7 := HWComponents.comb_and _11 _6 + let _1 := HWComponents.comb_and _5 _0 + let add1_out0 := HWComponents.comb_add add0_out0 (arg1 i) + ((fork_ready, add1_in1_ready, (out1_ready i), add1_out0, add1_out0_valid, (arg2 i), (arg2_valid i)), (i + 1, _1, _7)) + +/-- `add_rtl`, re-expressed through the named update function (the analogue of +`hw_fork'`). -/ +def add_rtl' (arg0_valid arg1_valid arg2 arg2_valid out0_ready out1_ready : + Stream' (BitVec 1)) (arg0 arg1 : Stream' (BitVec 64)) : + Stream' ( + BitVec 1 -- arg0_ready + × BitVec 1 -- arg1_ready + × BitVec 1 -- arg2_ready + × BitVec 64 -- out0 + × BitVec 1 -- out0_valid + × BitVec 1 --out1 + × BitVec 1 --out1_valid + ) := + Stream'.corec' (α := Nat × BitVec 1 × BitVec 1) + (add_rtl_corec arg0_valid arg1_valid arg2 arg2_valid out0_ready out1_ready + arg0 arg1) + (0, 0#1, 0#1) + +/-- The transcription and its named-update form agree (the analogue of +`hw_fork_eq`). -/ +theorem add_rtl_eq + {arg0_valid arg1_valid arg2 arg2_valid out0_ready out1_ready : + Stream' (BitVec 1)} {arg0 arg1 : Stream' (BitVec 64)} : + add_rtl arg0_valid arg1_valid arg2 arg2_valid out0_ready out1_ready arg0 arg1 + = add_rtl' arg0_valid arg1_valid arg2 arg2_valid out0_ready out1_ready + arg0 arg1 := by + unfold add_rtl add_rtl' add_rtl_corec + congr 1 /-! ## Reasoning layer @@ -259,38 +319,68 @@ theorem regs_eq_emitted (n : Nat) : instantiation so that the `Fork` library applies definitionally. -/ /-- Fork `out0_valid` inside the composition. -/ +@[bv_normalize] def fork0Vld (n : Nat) : BitVec 1 := Fork.vldOut1 (forkRdy arg0Vld arg1Vld out0Rdy) (forkRdy arg0Vld arg1Vld out0Rdy) arg0Vld n /-- Fork `out1_valid` inside the composition. -/ +@[bv_normalize] def fork1Vld (n : Nat) : BitVec 1 := Fork.vldOut2 (forkRdy arg0Vld arg1Vld out0Rdy) (forkRdy arg0Vld arg1Vld out0Rdy) arg0Vld n /-- Ready returned to the `arg0` producer (the fork's `in0_ready = allDone`). -/ +@[bv_normalize] def arg0Rdy (n : Nat) : BitVec 1 := Fork.allDone (forkRdy arg0Vld arg1Vld out0Rdy) (forkRdy arg0Vld arg1Vld out0Rdy) arg0Vld n /-- `arith_addi0.out0_valid`: the join of the two fork outputs. -/ +@[bv_normalize] def join0Vld (n : Nat) : BitVec 1 := comb_and (fork0Vld arg0Vld arg1Vld out0Rdy n) (fork1Vld arg0Vld arg1Vld out0Rdy n) /-- `arith_addi1.out0_valid = out0_valid` of the composed module. -/ +@[bv_normalize] def out0Vld (n : Nat) : BitVec 1 := comb_and (join0Vld arg0Vld arg1Vld out0Rdy n) (arg1Vld n) + /-- Ready returned to the `arg1` producer (`arith_addi1.in1_ready`). -/ +@[bv_normalize] def arg1Rdy (n : Nat) : BitVec 1 := comb_and (out0Rdy n) (out0Vld arg0Vld arg1Vld out0Rdy n) variable (arg0 arg1 : Stream' (BitVec 64)) /-- Data path of the composed module: combinational, `out0 = (arg0 + arg0) + arg1`. -/ +@[bv_normalize] def out0Data (n : Nat) : BitVec 64 := (arg0 n + arg0 n) + arg1 n +/-! ### The transcription computes the named signals -/ + +/-- `add_rtl`'s corec state is `(n, regs n)` — the analogue of +`iterate_eq_emitted`. (Induction on `n`; the register updates of +`add_rtl_corec` are, after zeta-reduction, exactly +`Fork.stepRegs (readyThroughAdders …) (readyThroughAdders …) (arg0Vld n)`.) -/ +theorem add_rtl_iterate {arg2 arg2Vld out1Rdy : Stream' (BitVec 1)} (n : Nat) : + Stream'.iterate + (Prod.snd ∘ add_rtl_corec arg0Vld arg1Vld arg2 arg2Vld out0Rdy out1Rdy + arg0 arg1) + (0, 0#1, 0#1) n + = (n, regs arg0Vld arg1Vld out0Rdy n) := by + induction n + · simp [Stream'.iterate] + · case _ m ihm => + simp [Stream'.iterate, ihm] + unfold add_rtl_corec + simp + simp [regs_succ, Fork.stepRegs] + exact Prod.mk_inj.mp _root_.rfl + + /-! ### Composition facts -/ /-- **The fork never stalls inside this composition**: both fork outputs see @@ -300,14 +390,24 @@ in the same cycle as the accepts and the registers never latch. (Induction on `n`; the step is pointwise: `regs_succ`, `Fork.stepRegs`, `bv_decide`.) -/ theorem regs_eq_zero (n : Nat) : regs arg0Vld arg1Vld out0Rdy n = (0#1, 0#1) := by - sorry + induction n + · simp + · case _ m ihm => + simp [regs_succ, ihm, Fork.stepRegs] + bv_decide /-- With the registers identically clear the fork is transparent: `out0_valid` is the conjunction of the input valids. (Pointwise from `regs_eq_zero`.) -/ theorem out0Vld_eq (n : Nat) : out0Vld arg0Vld arg1Vld out0Rdy n = comb_and (arg0Vld n) (arg1Vld n) := by - sorry + have hreg : Fork.emitted (forkRdy arg0Vld arg1Vld out0Rdy) + (forkRdy arg0Vld arg1Vld out0Rdy) arg0Vld n = (0#1, 0#1) := + (regs_eq_emitted arg0Vld arg1Vld out0Rdy n).symm.trans + (regs_eq_zero arg0Vld arg1Vld out0Rdy n) + simp [out0Vld, join0Vld, fork0Vld, fork1Vld, + Fork.vldOut1_def, Fork.vldOut2_def, Fork.e0, Fork.e1, hreg] + bv_decide /-- With the registers identically clear, the ready returned to `arg0` is the external ready gated by both valids: the composed module behaves as one @@ -315,32 +415,143 @@ combinational join. (Pointwise from `regs_eq_zero`.) -/ theorem arg0Rdy_eq (n : Nat) : arg0Rdy arg0Vld arg1Vld out0Rdy n = comb_and (out0Rdy n) (comb_and (arg0Vld n) (arg1Vld n)) := by - sorry + have hreg : Fork.emitted (forkRdy arg0Vld arg1Vld out0Rdy) + (forkRdy arg0Vld arg1Vld out0Rdy) arg0Vld n = (0#1, 0#1) := + (regs_eq_emitted arg0Vld arg1Vld out0Rdy n).symm.trans + (regs_eq_zero arg0Vld arg1Vld out0Rdy n) + simp [arg0Rdy, Fork.allDone_def, Fork.done0_def, Fork.fire1_def, Fork.vldOut1_def, Fork.e0, + Fork.done1, Fork.vldOut2_def, Fork.fire2, Fork.e1, hreg, comb_and, comb_or, comb_xor, hw_constant, + forkRdy, readyThroughAdders, regs_eq_zero] + bv_decide + +/-- Pointwise characterization of the composed module — the analogue of +`hw_fork'_get`. With `regs_eq_zero`, the corec state is the literal `(0, 0)` +pair, the transcription's body fully reduces, and the named signals collapse +through `out0Vld_eq`/`arg0Rdy_eq`; every component is then `rfl` or a width-1 +boolean fact. -/ +theorem add_rtl'_get {arg2 arg2Vld out1Rdy : Stream' (BitVec 1)} (n : Nat) : + add_rtl' arg0Vld arg1Vld arg2 arg2Vld out0Rdy out1Rdy arg0 arg1 n + = (arg0Rdy arg0Vld arg1Vld out0Rdy n, + arg1Rdy arg0Vld arg1Vld out0Rdy n, + out1Rdy n, + out0Data arg0 arg1 n, + out0Vld arg0Vld arg1Vld out0Rdy n, + arg2 n, arg2Vld n) := by + unfold add_rtl' Stream'.corec' Stream'.corec Stream'.map Stream'.get + simp only [Function.comp_apply] + rw [add_rtl_iterate, regs_eq_zero] + simp only [add_rtl_corec] + simp only [arg1Rdy, out0Vld_eq, arg0Rdy_eq, out0Data] + simp only [HWComponents.comb_and, HWComponents.comb_or, HWComponents.comb_xor, + HWComponents.hw_constant, HWComponents.comb_add, comb_and, + reduceIte, Prod.mk.injEq] + and_intros <;> first | rfl | bv_decide /-! ### Correctness -/ -/-- **Lowering correctness for the composed `add` module**: the handshake-level -program applied to the token streams of the two inputs is bisimilar to the -token stream of the RTL output. - -Proof plan: by `regs_eq_zero` and its corollaries the RTL side is a single +/-- Split a stream of `add_rtl`-shaped 7-tuples into its component streams +(mirrors `TRY3.split_stream2` for the fork's 5-tuples). -/ +def split_stream7 {a b c d e f g : Type} : + Stream' (a × b × c × d × e × f × g) → + Stream' a × Stream' b × Stream' c × Stream' d × Stream' e × Stream' f + × Stream' g := fun s => + (fun i => (s i).1, fun i => (s i).2.1, fun i => (s i).2.2.1, + fun i => (s i).2.2.2.1, fun i => (s i).2.2.2.2.1, + fun i => (s i).2.2.2.2.2.1, fun i => (s i).2.2.2.2.2.2) + +/-- The components produced by `add_rtl` are exactly the named signals of this +section — the analogue of `hw_fork_components`. (Route: an +`iterate_eq_emitted`-style lemma identifying `add_rtl`'s corec state with +`(n, regs n)`, then read off each output component pointwise.) -/ +theorem add_rtl_components + {arg2 arg2Vld out1Rdy : Stream' (BitVec 1)} + {arg0Rdy' arg1Rdy' arg2Rdy' out0Vld' out1' out1Vld' : Stream' (BitVec 1)} + {out0' : Stream' (BitVec 64)} + (hadd : (arg0Rdy', arg1Rdy', arg2Rdy', out0', out0Vld', out1', out1Vld') + = split_stream7 (add_rtl arg0Vld arg1Vld arg2 arg2Vld out0Rdy out1Rdy + arg0 arg1)) : + arg0Rdy' = arg0Rdy arg0Vld arg1Vld out0Rdy + ∧ arg1Rdy' = arg1Rdy arg0Vld arg1Vld out0Rdy + ∧ arg2Rdy' = out1Rdy + ∧ out0' = out0Data arg0 arg1 + ∧ out0Vld' = out0Vld arg0Vld arg1Vld out0Rdy + ∧ out1' = arg2 ∧ out1Vld' = arg2Vld := by + simp [add_rtl_eq, split_stream7, Prod.mk.injEq] at hadd + obtain ⟨h1, h2, h3, h4, h5, h6, h7⟩ := hadd + and_intros + · simp [h1, add_rtl'_get] + · simp [h2, add_rtl'_get] + · simp [h3, add_rtl'_get] + · simp [h4, add_rtl'_get] + · simp [h5, add_rtl'_get] + · simp [h6, add_rtl'_get] + · simp [h7, add_rtl'_get] + + +/-- **Lowering correctness for the composed `add` module**: given the RTL +circuit `add_rtl` (via its output streams, bound by `hadd` — the analogue of +the fork equation in `hw_fork_refines_out1`), the handshake-level program +applied to the token streams of the two inputs is bisimilar to the token +stream of the RTL output. + +Proof plan: `add_rtl_components` + `subst` reduce the goal to the named +signals; by `regs_eq_zero` and its corollaries the RTL side is a single combinational join (`out0Vld_eq`, `arg0Rdy_eq`, data path `out0Data`); the fork contributes no further proof obligations. What remains is the handshake -side: a sampling development for `syncMap₂`/`HandshakeOp.fork` (mirroring -`out1_sampling_bisim`) showing that the token stream of `syncMap₂ f xs ys` is -the `f`-image of the joined token streams. That join library is the next -reusable component. -/ +side: `HandshakeOp.fork x = (x, x)` and a `syncMap₂_aligned` lemma (when the +two argument streams carry their `some`s at identical positions, `syncMap₂ f` +is the pointwise zip). Both token inputs here fire at the same instants +(`arg0Rdy ∧ arg0Vld` and `arg1Rdy ∧ arg1Vld` both reduce to +`out0Rdy ∧ arg0Vld ∧ arg1Vld`), so the two sides are pointwise *equal* and +`~` follows by reflexivity — the handshake contract hypotheses are not needed: +with the registers identically clear the composed module is memoryless, and +the contracts only existed to tame register skew. -/ theorem add_lowering_correctness - (hvr0 : globallyValidUntilReady arg0Vld (arg0Rdy arg0Vld arg1Vld out0Rdy)) - (hvd0 : globallyValidAndData arg0Vld arg0) - (hvr1 : globallyValidUntilReady arg1Vld (arg1Rdy arg0Vld arg1Vld out0Rdy)) - (hvd1 : globallyValidAndData arg1Vld arg1) : + {arg2 arg2Vld out1Rdy : Stream' (BitVec 1)} + {arg0Rdy' arg1Rdy' arg2Rdy' out0Vld' out1' out1Vld' : Stream' (BitVec 1)} + {out0' : Stream' (BitVec 64)} + (hadd : (arg0Rdy', arg1Rdy', arg2Rdy', out0', out0Vld', out1', out1Vld') + = split_stream7 (add_rtl arg0Vld arg1Vld arg2 arg2Vld out0Rdy out1Rdy + arg0 arg1)) : add_handshake - (toStream (arg0Rdy arg0Vld arg1Vld out0Rdy) arg0Vld arg0) - (toStream (arg1Rdy arg0Vld arg1Vld out0Rdy) arg1Vld arg1) - ~ toStream out0Rdy (out0Vld arg0Vld arg1Vld out0Rdy) - (out0Data arg0 arg1) := by - sorry + (toStream arg0Rdy' arg0Vld arg0) + (toStream arg1Rdy' arg1Vld arg1) + ~ toStream out0Rdy out0Vld' out0' := by + obtain ⟨h1, h2, -, h4, h5, -, -⟩ := + add_rtl_components arg0Vld arg1Vld out0Rdy arg0 arg1 hadd + subst h1 h2 h4 h5 + have hcase : ∀ b : BitVec 1, b = 0#1 ∨ b = 1#1 := by + intro b + by_cases hb : b = 1#1 + · exact Or.inr hb + · exact Or.inl (HWComponents.false_of_width_one _ hb) + have hbisim_of_eq : ∀ {a b : Stream (BitVec 64)}, a = b → a ~ b := by + intro a b heq + rw [heq] + exact HandshakeStream.rfl + unfold add_handshake + rw [HandshakeOp.fork_eq] + dsimp only [] + rw [syncMap₂_aligned (fun _ => Iff.rfl)] + have hal : ∀ n, + ((alignedZip BitVec.add + (toStream (arg0Rdy arg0Vld arg1Vld out0Rdy) arg0Vld arg0) + (toStream (arg0Rdy arg0Vld arg1Vld out0Rdy) arg0Vld arg0)) n).isSome + ↔ (toStream (arg1Rdy arg0Vld arg1Vld out0Rdy) arg1Vld arg1 n).isSome := by + intro n + rcases hcase (arg0Vld n) with h0 | h0 <;> + rcases hcase (arg1Vld n) with ha | ha <;> + rcases hcase (out0Rdy n) with hr | hr <;> + simp [alignedZip, toStream, arg1Rdy, out0Vld_eq, arg0Rdy_eq, h0, ha, hr, + HWComponents.comb_and] + rw [syncMap₂_aligned hal] + apply hbisim_of_eq + funext n + rcases hcase (arg0Vld n) with h0 | h0 <;> + rcases hcase (arg1Vld n) with ha | ha <;> + rcases hcase (out0Rdy n) with hr | hr <;> + simp [alignedZip, toStream, arg1Rdy, out0Vld_eq, arg0Rdy_eq, out0Data, + h0, ha, hr, HWComponents.comb_and, BitVec.add_eq] end Add end HandshakeStream diff --git a/SSA/Projects/CIRCT/Stream/Lemmas.lean b/SSA/Projects/CIRCT/Stream/Lemmas.lean index 8e50944471..a558813c58 100644 --- a/SSA/Projects/CIRCT/Stream/Lemmas.lean +++ b/SSA/Projects/CIRCT/Stream/Lemmas.lean @@ -337,3 +337,104 @@ theorem syncMap2_syncMap2_eq_syncMap3 (f : α → β → γ) (g : γ → ε → -- (h : ∀ a b c, f a b c = g a b c) : -- syncMap₂ f xs ys = syncMap₂ g xs ys := by -- sorry + +/-! ### `syncMap₂` on aligned streams + +When the two argument streams carry their `some`s at identical positions, the +synchronizer never has to buffer: each step consumes one position of *both* +streams, and the output is the pointwise zip. `syncMap₂Step` names the update +function of `syncMap₂` (verbatim) so that its corec state can be +characterized, following the `fork_corec`/`add_rtl_corec` pattern. -/ + +/-- The update function of `syncMap₂`, extracted verbatim. -/ +def syncMap₂Step (f : α → β → γ) : + Stream α × Stream β → Option γ × (Stream α × Stream β) := fun ⟨xs, ys⟩ => + match xs 0, ys 0 with + | some x, some y => ⟨some <| f x y, xs.tail, ys.tail⟩ + | _, _ => + let xs := if (xs 0).isNone then xs.tail else xs + let ys := if (ys 0).isNone then ys.tail else ys + ⟨none, xs, ys⟩ + +theorem syncMap₂_eq_step {f : α → β → γ} {xs : Stream α} {ys : Stream β} : + syncMap₂ f xs ys = HandshakeStream.corec (xs, ys) (syncMap₂Step f) := _root_.rfl + +/-- On aligned streams, the corec state of `syncMap₂` after `n` steps is the +pair of `n`-fold tails: whether the heads are both `some` or (by alignment) +both `none`, the step advances both streams. -/ +theorem syncMap₂_aligned_iterate {f : α → β → γ} {xs : Stream α} {ys : Stream β} + (h : ∀ n, (xs n).isSome ↔ (ys n).isSome) (n : Nat) : + Stream'.iterate (fun s => (syncMap₂Step f s).2) (xs, ys) n + = (Stream'.drop n xs, Stream'.drop n ys) := by + induction n with + | zero => rfl + | succ k ih => + show (syncMap₂Step f + (Stream'.iterate (fun s => (syncMap₂Step f s).2) (xs, ys) k)).2 = _ + rw [ih] + have hx0 : (Stream'.drop k xs) 0 = xs k := by + show xs.get (0 + k) = xs.get k + rw [Nat.zero_add] + have hy0 : (Stream'.drop k ys) 0 = ys k := by + show ys.get (0 + k) = ys.get k + rw [Nat.zero_add] + unfold syncMap₂Step + dsimp only [] + rw [hx0, hy0] + rcases hxk : xs k with _ | x + · rcases hyk : ys k with _ | y + · simp + · exfalso + have hc := h k + rw [hxk, hyk] at hc + simp at hc + · rcases hyk : ys k with _ | y + · exfalso + have hc := h k + rw [hxk, hyk] at hc + simp at hc + · simp + +/-- The pointwise zip of two option streams: fires exactly where both fire. +Named (rather than inlined as a `match`-lambda) so that statements about it +share one `match` auxiliary and remain `rw`-compatible. -/ +def alignedZip (f : α → β → γ) (xs : Stream α) (ys : Stream β) : Stream γ := + fun n => + match xs n, ys n with + | some a, some b => some (f a b) + | _, _ => none + +/-- **`syncMap₂` on aligned streams is the pointwise zip**: if the two +argument streams carry their `some`s at identical positions, the synchronizer +fires exactly at those positions, with the `f`-image of the two values. -/ +theorem syncMap₂_aligned {f : α → β → γ} {xs : Stream α} {ys : Stream β} + (h : ∀ n, (xs n).isSome ↔ (ys n).isSome) : + syncMap₂ f xs ys = alignedZip f xs ys := by + funext n + unfold alignedZip + rw [syncMap₂_eq_step] + show (syncMap₂Step f + (Stream'.iterate (fun s => (syncMap₂Step f s).2) (xs, ys) n)).1 = _ + rw [syncMap₂_aligned_iterate h] + have hx0 : (Stream'.drop n xs) 0 = xs n := by + show xs.get (0 + n) = xs.get n + rw [Nat.zero_add] + have hy0 : (Stream'.drop n ys) 0 = ys n := by + show ys.get (0 + n) = ys.get n + rw [Nat.zero_add] + unfold syncMap₂Step + dsimp only [] + rw [hx0, hy0] + rcases hxk : xs n with _ | x + · rcases hyk : ys n with _ | y + · simp + · exfalso + have hc := h n + rw [hxk, hyk] at hc + simp at hc + · rcases hyk : ys n with _ | y + · exfalso + have hc := h n + rw [hxk, hyk] at hc + simp at hc + · simp