1- // RUN: tutorial-opt %s | FileCheck %s
1+ // RUN: tutorial-opt %s --noisy-reduce-noise-optimizer | FileCheck %s
22// Check for syntax
33
4- // CHECK-LABEL: test_op_syntax
5- func.func @test_op_syntax () -> i5 {
4+ // CHECK-LABEL: test_insert_noise_reduction_ops_mul
5+ // CHECK: [[V0:%.*]] = arith.constant 3
6+ // CHECK-NEXT: [[V1:%.*]] = arith.constant 4
7+ // CHECK-NEXT: [[V2:%.*]] = noisy.encode [[V0]]
8+ // CHECK-NEXT: [[V3:%.*]] = noisy.encode [[V1]]
9+ // CHECK-NEXT: [[V4:%.*]] = noisy.mul [[V2]], [[V3]]
10+ // CHECK-NEXT: [[V4_R:%.*]] = noisy.reduce_noise [[V4]]
11+ // CHECK-NEXT: [[V5:%.*]] = noisy.mul [[V4_R]], [[V4_R]]
12+ // CHECK-NEXT: [[V5_R:%.*]] = noisy.reduce_noise [[V5]]
13+ // CHECK-NEXT: [[V6:%.*]] = noisy.mul [[V5_R]], [[V5_R]]
14+ // CHECK-NEXT: [[V6_R:%.*]] = noisy.reduce_noise [[V6]]
15+ // This last mul does not need to be reduced
16+ // CHECK-NEXT: [[V7:%.*]] = noisy.mul [[V6_R]], [[V6_R]]
17+ // CHECK-NEXT: [[V8:%.*]] = noisy.decode [[V7]]
18+ // CHECK-NEXT: return
19+ func.func @test_insert_noise_reduction_ops_mul () -> i5 {
620 %0 = arith.constant 3 : i5
721 %1 = arith.constant 4 : i5
822 %2 = noisy.encode %0 : i5 -> !noisy.i32
@@ -14,3 +28,133 @@ func.func @test_op_syntax() -> i5 {
1428 %8 = noisy.decode %7 : !noisy.i32 -> i5
1529 return %8 : i5
1630}
31+
32+ // CHECK-LABEL: test_insert_noise_reduction_ops_add_none_needed
33+ // CHECK-NOT: noisy.reduce_noise
34+ func.func @test_insert_noise_reduction_ops_add_none_needed () -> i5 {
35+ %0 = arith.constant 3 : i5
36+ %1 = arith.constant 4 : i5
37+ %2 = noisy.encode %0 : i5 -> !noisy.i32
38+ %3 = noisy.encode %1 : i5 -> !noisy.i32
39+ %4 = noisy.add %2 , %3 : !noisy.i32
40+ %5 = noisy.add %4 , %4 : !noisy.i32
41+ %6 = noisy.add %5 , %5 : !noisy.i32
42+ %7 = noisy.add %6 , %6 : !noisy.i32
43+ %8 = noisy.decode %7 : !noisy.i32 -> i5
44+ return %8 : i5
45+ }
46+
47+
48+ // CHECK-LABEL: test_add_after_mul
49+ // CHECK: noisy.mul
50+ // CHECK: noisy.reduce_noise
51+ // CHECK: noisy.add
52+ // CHECK: noisy.add
53+ // CHECK: noisy.add
54+ // CHECK: noisy.add
55+ // CHECK: noisy.decode
56+ // CHECK: return
57+ func.func @test_add_after_mul () -> i5 {
58+ %0 = arith.constant 3 : i5
59+ %1 = arith.constant 4 : i5
60+ %2 = noisy.encode %0 : i5 -> !noisy.i32
61+ %3 = noisy.encode %1 : i5 -> !noisy.i32
62+ // Noise: 12
63+ %4 = noisy.mul %2 , %3 : !noisy.i32
64+ // Noise: 24
65+ %5 = noisy.add %4 , %3 : !noisy.i32
66+ // Noise: 25
67+ %6 = noisy.add %5 , %5 : !noisy.i32
68+ // Noise: 26
69+ %7 = noisy.add %6 , %6 : !noisy.i32
70+ // Noise: 27
71+ %8 = noisy.add %7 , %7 : !noisy.i32
72+ %9 = noisy.decode %8 : !noisy.i32 -> i5
73+ return %9 : i5
74+ }
75+
76+ // This test checks that the solver can find a single insertion point
77+ // for a reduce_noise op that handles two branches, each of which would
78+ // also need a reduce_noise op if handled separately.
79+ // CHECK-LABEL: test_single_insertion_branching
80+ // CHECK: noisy.mul
81+ // CHECK-NOT: noisy.add
82+ // CHECK-COUNT-1: noisy.reduce_noise
83+ // CHECK-NOT: noisy.reduce_noise
84+ func.func @test_single_insertion_branching () -> i5 {
85+ %0 = arith.constant 3 : i5
86+ %1 = arith.constant 4 : i5
87+ %2 = noisy.encode %0 : i5 -> !noisy.i32
88+ %3 = noisy.encode %1 : i5 -> !noisy.i32
89+ // Noise: 12
90+ %4 = noisy.mul %2 , %3 : !noisy.i32
91+ // Noise: 24
92+
93+ // branch 1
94+ %b1 = noisy.add %4 , %3 : !noisy.i32
95+ // Noise: 25
96+ %b2 = noisy.add %b1 , %3 : !noisy.i32
97+ // Noise: 25
98+ %b3 = noisy.add %b2 , %3 : !noisy.i32
99+ // Noise: 26
100+ %b4 = noisy.add %b3 , %3 : !noisy.i32
101+ // Noise: 27
102+
103+ // branch 2
104+ %c1 = noisy.sub %4 , %2 : !noisy.i32
105+ // Noise: 25
106+ %c2 = noisy.sub %c1 , %3 : !noisy.i32
107+ // Noise: 25
108+ %c3 = noisy.sub %c2 , %3 : !noisy.i32
109+ // Noise: 26
110+ %c4 = noisy.sub %c3 , %3 : !noisy.i32
111+ // Noise: 27
112+
113+ %x1 = noisy.decode %b4 : !noisy.i32 -> i5
114+ %x2 = noisy.decode %c4 : !noisy.i32 -> i5
115+ %x3 = arith.addi %x1 , %x2 : i5
116+ return %x3 : i5
117+ }
118+
119+ // same as test_single_insertion_branching, but because the last two values
120+ // are multiplied, we need two reduce_noise ops, one on each branch.
121+ // CHECK-LABEL: test_double_insertion_branching
122+ // CHECK: noisy.mul
123+ // CHECK: noisy.add
124+ // CHECK-COUNT-2: noisy.reduce_noise
125+ // CHECK-NOT: noisy.reduce_noise
126+ // CHECK: noisy.mul
127+ func.func @test_double_insertion_branching () -> i5 {
128+ %0 = arith.constant 3 : i5
129+ %1 = arith.constant 4 : i5
130+ %2 = noisy.encode %0 : i5 -> !noisy.i32
131+ %3 = noisy.encode %1 : i5 -> !noisy.i32
132+ // Noise: 12
133+ %4 = noisy.mul %2 , %3 : !noisy.i32
134+ // Noise: 24
135+
136+ // branch 1
137+ %b1 = noisy.add %4 , %3 : !noisy.i32
138+ // Noise: 25
139+ %b2 = noisy.add %b1 , %3 : !noisy.i32
140+ // Noise: 25
141+ %b3 = noisy.add %b2 , %3 : !noisy.i32
142+ // Noise: 26
143+ %b4 = noisy.add %b3 , %3 : !noisy.i32
144+ // Noise: 27
145+
146+ // branch 2
147+ %c1 = noisy.add %4 , %2 : !noisy.i32
148+ // Noise: 25
149+ %c2 = noisy.add %c1 , %3 : !noisy.i32
150+ // Noise: 25
151+ %c3 = noisy.add %c2 , %3 : !noisy.i32
152+ // Noise: 26
153+ %c4 = noisy.add %c3 , %3 : !noisy.i32
154+ // Noise: 27
155+
156+ %exit = noisy.mul %b4 , %c4 : !noisy.i32
157+
158+ %x1 = noisy.decode %exit : !noisy.i32 -> i5
159+ return %x1 : i5
160+ }
0 commit comments