Skip to content

Commit 91746d1

Browse files
rmacnak-googleCommit Queue
authored andcommitted
[vm, compiler] Add binary op reductions for the reflexive case.
TEST=vm/dart/binary_op_reductions_il_test Change-Id: Ice3f4e40db670f29f466d4f0ae85bac46b6fae20 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/392161 Reviewed-by: Alexander Markov <[email protected]> Commit-Queue: Ryan Macnak <[email protected]>
1 parent a8e9cc4 commit 91746d1

File tree

2 files changed

+371
-0
lines changed

2 files changed

+371
-0
lines changed
Lines changed: 357 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,357 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:expect/expect.dart';
6+
import 'package:vm/testing/il_matchers.dart';
7+
8+
@pragma('vm:never-inline')
9+
@pragma('vm:testing:print-flow-graph')
10+
int and(int x) {
11+
return x & x;
12+
}
13+
14+
void matchIL$and(FlowGraph graph) {
15+
graph.dump();
16+
graph.match([
17+
match.block('Graph', []),
18+
match.block('Function', [
19+
'x' << match.Parameter(index: 0),
20+
match.DartReturn('x'),
21+
]),
22+
]);
23+
}
24+
25+
@pragma('vm:never-inline')
26+
@pragma('vm:testing:print-flow-graph')
27+
int and0(int x) {
28+
return x & 0;
29+
}
30+
31+
void matchIL$and0(FlowGraph graph) {
32+
graph.dump();
33+
graph.match([
34+
match.block('Graph', [
35+
'c_zero' << match.UnboxedConstant(value: 0),
36+
]),
37+
match.block('Function', [
38+
match.DartReturn('c_zero'),
39+
]),
40+
]);
41+
}
42+
43+
@pragma('vm:never-inline')
44+
@pragma('vm:testing:print-flow-graph')
45+
int and_1(int x) {
46+
return x & -1;
47+
}
48+
49+
void matchIL$and_1(FlowGraph graph) {
50+
graph.dump();
51+
graph.match([
52+
match.block('Graph', []),
53+
match.block('Function', [
54+
'x' << match.Parameter(index: 0),
55+
match.DartReturn('x'),
56+
]),
57+
]);
58+
}
59+
60+
@pragma('vm:never-inline')
61+
@pragma('vm:testing:print-flow-graph')
62+
int or(int x) {
63+
return x | x;
64+
}
65+
66+
void matchIL$or(FlowGraph graph) {
67+
graph.dump();
68+
graph.match([
69+
match.block('Graph', []),
70+
match.block('Function', [
71+
'x' << match.Parameter(index: 0),
72+
match.DartReturn('x'),
73+
]),
74+
]);
75+
}
76+
77+
@pragma('vm:never-inline')
78+
@pragma('vm:testing:print-flow-graph')
79+
int or0(int x) {
80+
return x | 0;
81+
}
82+
83+
void matchIL$or0(FlowGraph graph) {
84+
graph.dump();
85+
graph.match([
86+
match.block('Graph', []),
87+
match.block('Function', [
88+
'x' << match.Parameter(index: 0),
89+
match.DartReturn('x'),
90+
]),
91+
]);
92+
}
93+
94+
@pragma('vm:never-inline')
95+
@pragma('vm:testing:print-flow-graph')
96+
int or_1(int x) {
97+
return x | -1;
98+
}
99+
100+
void matchIL$or_1(FlowGraph graph) {
101+
graph.dump();
102+
graph.match([
103+
match.block('Graph', [
104+
'c_minus_one' << match.UnboxedConstant(value: -1),
105+
]),
106+
match.block('Function', [
107+
match.DartReturn('c_minus_one'),
108+
]),
109+
]);
110+
}
111+
112+
@pragma('vm:never-inline')
113+
@pragma('vm:testing:print-flow-graph')
114+
int xor(int x) {
115+
return x ^ x;
116+
}
117+
118+
void matchIL$xor(FlowGraph graph) {
119+
graph.dump();
120+
graph.match([
121+
match.block('Graph', [
122+
'c_zero' << match.UnboxedConstant(value: 0),
123+
]),
124+
match.block('Function', [
125+
match.DartReturn('c_zero'),
126+
]),
127+
]);
128+
}
129+
130+
@pragma('vm:never-inline')
131+
@pragma('vm:testing:print-flow-graph')
132+
int xor0(int x) {
133+
return x ^ 0;
134+
}
135+
136+
void matchIL$xor0(FlowGraph graph) {
137+
graph.dump();
138+
graph.match([
139+
match.block('Graph', []),
140+
match.block('Function', [
141+
'x' << match.Parameter(index: 0),
142+
match.DartReturn('x'),
143+
]),
144+
]);
145+
}
146+
147+
@pragma('vm:never-inline')
148+
@pragma('vm:testing:print-flow-graph')
149+
int add0(int x) {
150+
return x + 0;
151+
}
152+
153+
void matchIL$add0(FlowGraph graph) {
154+
graph.dump();
155+
graph.match([
156+
match.block('Graph', []),
157+
match.block('Function', [
158+
'x' << match.Parameter(index: 0),
159+
match.DartReturn('x'),
160+
]),
161+
]);
162+
}
163+
164+
@pragma('vm:never-inline')
165+
@pragma('vm:testing:print-flow-graph')
166+
int sub(int x) {
167+
return x - x;
168+
}
169+
170+
void matchIL$sub(FlowGraph graph) {
171+
graph.dump();
172+
graph.match([
173+
match.block('Graph', [
174+
'c_zero' << match.UnboxedConstant(value: 0),
175+
]),
176+
match.block('Function', [
177+
match.DartReturn('c_zero'),
178+
]),
179+
]);
180+
}
181+
182+
@pragma('vm:never-inline')
183+
@pragma('vm:testing:print-flow-graph')
184+
int sub0(int x) {
185+
return x - 0;
186+
}
187+
188+
void matchIL$sub0(FlowGraph graph) {
189+
graph.dump();
190+
graph.match([
191+
match.block('Graph', []),
192+
match.block('Function', [
193+
'x' << match.Parameter(index: 0),
194+
match.DartReturn('x'),
195+
]),
196+
]);
197+
}
198+
199+
@pragma('vm:never-inline')
200+
@pragma('vm:testing:print-flow-graph')
201+
int mul0(int x) {
202+
return x * 0;
203+
}
204+
205+
void matchIL$mul0(FlowGraph graph) {
206+
graph.dump();
207+
graph.match([
208+
match.block('Graph', [
209+
'c_zero' << match.UnboxedConstant(value: 0),
210+
]),
211+
match.block('Function', [
212+
match.DartReturn('c_zero'),
213+
]),
214+
]);
215+
}
216+
217+
@pragma('vm:never-inline')
218+
@pragma('vm:testing:print-flow-graph')
219+
int mul1(int x) {
220+
return x * 1;
221+
}
222+
223+
void matchIL$mul1(FlowGraph graph) {
224+
graph.dump();
225+
graph.match([
226+
match.block('Graph', []),
227+
match.block('Function', [
228+
'x' << match.Parameter(index: 0),
229+
match.DartReturn('x'),
230+
]),
231+
]);
232+
}
233+
234+
@pragma('vm:never-inline')
235+
@pragma('vm:testing:print-flow-graph')
236+
int div1(int x) {
237+
return x ~/ 1;
238+
}
239+
240+
void matchIL$div1(FlowGraph graph) {
241+
graph.dump();
242+
graph.match([
243+
match.block('Graph', []),
244+
match.block('Function', [
245+
'x' << match.Parameter(index: 0),
246+
match.DartReturn('x'),
247+
]),
248+
]);
249+
}
250+
251+
@pragma('vm:never-inline')
252+
@pragma('vm:testing:print-flow-graph')
253+
int sll0(int x) {
254+
return x << 0;
255+
}
256+
257+
void matchIL$sll0(FlowGraph graph) {
258+
graph.dump();
259+
graph.match([
260+
match.block('Graph', []),
261+
match.block('Function', [
262+
'x' << match.Parameter(index: 0),
263+
match.DartReturn('x'),
264+
]),
265+
]);
266+
}
267+
268+
@pragma('vm:never-inline')
269+
@pragma('vm:testing:print-flow-graph')
270+
int sra0(int x) {
271+
return x >> 0;
272+
}
273+
274+
void matchIL$sra0(FlowGraph graph) {
275+
graph.dump();
276+
graph.match([
277+
match.block('Graph', []),
278+
match.block('Function', [
279+
'x' << match.Parameter(index: 0),
280+
match.DartReturn('x'),
281+
]),
282+
]);
283+
}
284+
285+
@pragma('vm:never-inline')
286+
@pragma('vm:testing:print-flow-graph')
287+
int srl0(int x) {
288+
return x >>> 0;
289+
}
290+
291+
void matchIL$srl0(FlowGraph graph) {
292+
graph.dump();
293+
graph.match([
294+
match.block('Graph', []),
295+
match.block('Function', [
296+
'x' << match.Parameter(index: 0),
297+
match.DartReturn('x'),
298+
]),
299+
]);
300+
}
301+
302+
@pragma('vm:never-inline')
303+
@pragma('vm:testing:print-flow-graph')
304+
int srl64(int x) {
305+
return x >>> 64;
306+
}
307+
308+
void matchIL$srl64(FlowGraph graph) {
309+
graph.dump();
310+
graph.match([
311+
match.block('Graph', [
312+
'c_zero' << match.UnboxedConstant(value: 0),
313+
]),
314+
match.block('Function', [
315+
match.DartReturn('c_zero'),
316+
]),
317+
]);
318+
}
319+
320+
main() {
321+
Expect.equals(1, and(1));
322+
Expect.equals(2, and(2));
323+
Expect.equals(0, and0(1));
324+
Expect.equals(0, and0(2));
325+
Expect.equals(1, and_1(1));
326+
Expect.equals(2, and_1(2));
327+
Expect.equals(1, or(1));
328+
Expect.equals(2, or(2));
329+
Expect.equals(1, or0(1));
330+
Expect.equals(2, or0(2));
331+
Expect.equals(-1, or_1(1));
332+
Expect.equals(-1, or_1(2));
333+
Expect.equals(0, xor(1));
334+
Expect.equals(0, xor(2));
335+
Expect.equals(1, xor0(1));
336+
Expect.equals(2, xor0(2));
337+
Expect.equals(1, add0(1));
338+
Expect.equals(2, add0(2));
339+
Expect.equals(0, sub(1));
340+
Expect.equals(0, sub(2));
341+
Expect.equals(1, sub0(1));
342+
Expect.equals(2, sub0(2));
343+
Expect.equals(0, mul0(1));
344+
Expect.equals(0, mul0(2));
345+
Expect.equals(1, mul1(1));
346+
Expect.equals(2, mul1(2));
347+
Expect.equals(1, div1(1));
348+
Expect.equals(2, div1(2));
349+
Expect.equals(1, sll0(1));
350+
Expect.equals(2, sll0(2));
351+
Expect.equals(1, sra0(1));
352+
Expect.equals(2, sra0(2));
353+
Expect.equals(1, srl0(1));
354+
Expect.equals(2, srl0(2));
355+
Expect.equals(0, srl64(1));
356+
Expect.equals(0, srl64(2));
357+
}

runtime/vm/compiler/backend/il.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2397,6 +2397,20 @@ Definition* BinaryIntegerOpInstr::Canonicalize(FlowGraph* flow_graph) {
23972397
SetInputAt(1, l);
23982398
}
23992399

2400+
if (left()->definition() == right()->definition()) {
2401+
switch (op_kind()) {
2402+
case Token::kBIT_AND:
2403+
case Token::kBIT_OR:
2404+
return left()->definition();
2405+
case Token::kBIT_XOR:
2406+
case Token::kSUB:
2407+
return flow_graph->TryCreateConstantReplacementFor(this,
2408+
Object::smi_zero());
2409+
default:
2410+
break;
2411+
}
2412+
}
2413+
24002414
int64_t rhs;
24012415
if (!Evaluator::ToIntegerConstant(right(), &rhs)) {
24022416
return this;

0 commit comments

Comments
 (0)