17 MachineOperatorReducer::MachineOperatorReducer(JSGraph* jsgraph)
18 : jsgraph_(jsgraph) {}
21 MachineOperatorReducer::~MachineOperatorReducer() {}
24 Node* MachineOperatorReducer::Float32Constant(
volatile float value) {
25 return graph()->NewNode(common()->Float32Constant(value));
29 Node* MachineOperatorReducer::Float64Constant(
volatile double value) {
30 return jsgraph()->Float64Constant(value);
34 Node* MachineOperatorReducer::Int32Constant(
int32_t value) {
35 return jsgraph()->Int32Constant(value);
39 Node* MachineOperatorReducer::Int64Constant(int64_t value) {
40 return graph()->NewNode(common()->Int64Constant(value));
45 Reduction MachineOperatorReducer::Reduce(Node* node) {
46 switch (node->opcode()) {
47 case IrOpcode::kProjection:
48 return ReduceProjection(OpParameter<size_t>(node), node->InputAt(0));
49 case IrOpcode::kWord32And: {
51 if (m.right().Is(0))
return Replace(m.right().node());
52 if (m.right().Is(-1))
return Replace(m.left().node());
54 return ReplaceInt32(m.left().Value() & m.right().Value());
56 if (m.LeftEqualsRight())
return Replace(m.left().node());
59 case IrOpcode::kWord32Or: {
61 if (m.right().Is(0))
return Replace(m.left().node());
62 if (m.right().Is(-1))
return Replace(m.right().node());
64 return ReplaceInt32(m.left().Value() | m.right().Value());
66 if (m.LeftEqualsRight())
return Replace(m.left().node());
67 if (m.left().IsWord32Shl() && m.right().IsWord32Shr()) {
70 if (mleft.left().node() == mright.left().node()) {
72 if (mright.right().IsInt32Sub()) {
74 if (mrightright.left().Is(32) &&
75 mrightright.right().node() == mleft.right().node()) {
76 node->set_op(machine()->Word32Ror());
77 node->ReplaceInput(0, mleft.left().node());
78 node->ReplaceInput(1, mleft.right().node());
83 if (mleft.right().IsInRange(0, 31) &&
84 mright.right().Is(32 - mleft.right().Value())) {
85 node->set_op(machine()->Word32Ror());
86 node->ReplaceInput(0, mleft.left().node());
87 node->ReplaceInput(1, mleft.right().node());
92 if (m.left().IsWord32Shr() && m.right().IsWord32Shl()) {
96 if (mleft.left().node() == mright.left().node()) {
97 if (mleft.right().IsInt32Sub()) {
99 if (mleftright.left().Is(32) &&
100 mleftright.right().node() == mright.right().node()) {
101 node->set_op(machine()->Word32Ror());
102 node->ReplaceInput(0, mright.left().node());
103 node->ReplaceInput(1, mright.right().node());
104 return Changed(node);
108 if (mright.right().IsInRange(0, 31) &&
109 mleft.right().Is(32 - mright.right().Value())) {
110 node->set_op(machine()->Word32Ror());
111 node->ReplaceInput(0, mright.left().node());
112 node->ReplaceInput(1, mright.right().node());
113 return Changed(node);
119 case IrOpcode::kWord32Xor: {
121 if (m.right().Is(0))
return Replace(m.left().node());
122 if (m.IsFoldable()) {
123 return ReplaceInt32(m.left().Value() ^ m.right().Value());
125 if (m.LeftEqualsRight())
return ReplaceInt32(0);
128 case IrOpcode::kWord32Shl: {
130 if (m.right().Is(0))
return Replace(m.left().node());
131 if (m.IsFoldable()) {
132 return ReplaceInt32(m.left().Value() << m.right().Value());
134 if (m.right().IsInRange(1, 31)) {
137 if (m.left().IsWord32Sar() || m.left().IsWord32Shr()) {
139 if (mleft.right().Is(m.right().Value())) {
140 node->set_op(machine()->Word32And());
141 node->ReplaceInput(0, mleft.left().node());
143 1, Uint32Constant(~((1U << m.right().Value()) - 1U)));
144 return Changed(node);
150 case IrOpcode::kWord32Shr: {
152 if (m.right().Is(0))
return Replace(m.left().node());
153 if (m.IsFoldable()) {
154 return ReplaceInt32(m.left().Value() >> m.right().Value());
158 case IrOpcode::kWord32Sar: {
160 if (m.right().Is(0))
return Replace(m.left().node());
161 if (m.IsFoldable()) {
162 return ReplaceInt32(m.left().Value() >> m.right().Value());
166 case IrOpcode::kWord32Ror: {
168 if (m.right().Is(0))
return Replace(m.left().node());
169 if (m.IsFoldable()) {
175 case IrOpcode::kWord32Equal: {
177 if (m.IsFoldable()) {
178 return ReplaceBool(m.left().Value() == m.right().Value());
180 if (m.left().IsInt32Sub() && m.right().Is(0)) {
182 node->ReplaceInput(0, msub.left().node());
183 node->ReplaceInput(1, msub.right().node());
184 return Changed(node);
187 if (m.LeftEqualsRight())
return ReplaceBool(
true);
190 case IrOpcode::kInt32Add: {
192 if (m.right().Is(0))
return Replace(m.left().node());
193 if (m.IsFoldable()) {
194 return ReplaceInt32(
static_cast<uint32_t>(m.left().Value()) +
195 static_cast<uint32_t>(m.right().Value()));
199 case IrOpcode::kInt32Sub: {
201 if (m.right().Is(0))
return Replace(m.left().node());
202 if (m.IsFoldable()) {
203 return ReplaceInt32(
static_cast<uint32_t>(m.left().Value()) -
204 static_cast<uint32_t>(m.right().Value()));
206 if (m.LeftEqualsRight())
return ReplaceInt32(0);
209 case IrOpcode::kInt32Mul: {
211 if (m.right().Is(0))
return Replace(m.right().node());
212 if (m.right().Is(1))
return Replace(m.left().node());
213 if (m.IsFoldable()) {
214 return ReplaceInt32(m.left().Value() * m.right().Value());
216 if (m.right().Is(-1)) {
217 node->set_op(machine()->Int32Sub());
218 node->ReplaceInput(0, Int32Constant(0));
219 node->ReplaceInput(1, m.left().node());
220 return Changed(node);
222 if (m.right().IsPowerOf2()) {
223 node->set_op(machine()->Word32Shl());
224 node->ReplaceInput(1, Int32Constant(
WhichPowerOf2(m.right().Value())));
225 return Changed(node);
229 case IrOpcode::kInt32Div: {
231 if (m.right().Is(1))
return Replace(m.left().node());
236 if (m.IsFoldable() && !m.right().Is(0)) {
237 if (m.right().Is(-1))
return ReplaceInt32(-m.left().Value());
238 return ReplaceInt32(m.left().Value() / m.right().Value());
240 if (m.right().Is(-1)) {
241 node->set_op(machine()->Int32Sub());
242 node->ReplaceInput(0, Int32Constant(0));
243 node->ReplaceInput(1, m.left().node());
244 return Changed(node);
248 case IrOpcode::kInt32UDiv: {
250 if (m.right().Is(1))
return Replace(m.left().node());
254 if (m.IsFoldable() && !m.right().Is(0)) {
255 return ReplaceInt32(m.left().Value() / m.right().Value());
257 if (m.right().IsPowerOf2()) {
258 node->set_op(machine()->Word32Shr());
259 node->ReplaceInput(1, Int32Constant(
WhichPowerOf2(m.right().Value())));
260 return Changed(node);
264 case IrOpcode::kInt32Mod: {
266 if (m.right().Is(1))
return ReplaceInt32(0);
267 if (m.right().Is(-1))
return ReplaceInt32(0);
272 if (m.IsFoldable() && !m.right().Is(0)) {
273 return ReplaceInt32(m.left().Value() % m.right().Value());
277 case IrOpcode::kInt32UMod: {
279 if (m.right().Is(1))
return ReplaceInt32(0);
283 if (m.IsFoldable() && !m.right().Is(0)) {
284 return ReplaceInt32(m.left().Value() % m.right().Value());
286 if (m.right().IsPowerOf2()) {
287 node->set_op(machine()->Word32And());
288 node->ReplaceInput(1, Int32Constant(m.right().Value() - 1));
289 return Changed(node);
293 case IrOpcode::kInt32LessThan: {
295 if (m.IsFoldable()) {
296 return ReplaceBool(m.left().Value() < m.right().Value());
298 if (m.left().IsInt32Sub() && m.right().Is(0)) {
300 node->ReplaceInput(0, msub.left().node());
301 node->ReplaceInput(1, msub.right().node());
302 return Changed(node);
304 if (m.left().Is(0) && m.right().IsInt32Sub()) {
306 node->ReplaceInput(0, msub.right().node());
307 node->ReplaceInput(1, msub.left().node());
308 return Changed(node);
310 if (m.LeftEqualsRight())
return ReplaceBool(
false);
313 case IrOpcode::kInt32LessThanOrEqual: {
315 if (m.IsFoldable()) {
316 return ReplaceBool(m.left().Value() <= m.right().Value());
318 if (m.left().IsInt32Sub() && m.right().Is(0)) {
320 node->ReplaceInput(0, msub.left().node());
321 node->ReplaceInput(1, msub.right().node());
322 return Changed(node);
324 if (m.left().Is(0) && m.right().IsInt32Sub()) {
326 node->ReplaceInput(0, msub.right().node());
327 node->ReplaceInput(1, msub.left().node());
328 return Changed(node);
330 if (m.LeftEqualsRight())
return ReplaceBool(
true);
333 case IrOpcode::kUint32LessThan: {
335 if (m.left().Is(
kMaxUInt32))
return ReplaceBool(
false);
336 if (m.right().Is(0))
return ReplaceBool(
false);
337 if (m.IsFoldable()) {
338 return ReplaceBool(m.left().Value() < m.right().Value());
340 if (m.LeftEqualsRight())
return ReplaceBool(
false);
343 case IrOpcode::kUint32LessThanOrEqual: {
345 if (m.left().Is(0))
return ReplaceBool(
true);
346 if (m.right().Is(
kMaxUInt32))
return ReplaceBool(
true);
347 if (m.IsFoldable()) {
348 return ReplaceBool(m.left().Value() <= m.right().Value());
350 if (m.LeftEqualsRight())
return ReplaceBool(
true);
353 case IrOpcode::kFloat64Add: {
355 if (m.right().IsNaN()) {
356 return Replace(m.right().node());
358 if (m.IsFoldable()) {
359 return ReplaceFloat64(m.left().Value() + m.right().Value());
363 case IrOpcode::kFloat64Sub: {
365 if (m.right().Is(0) && (Double(m.right().Value()).Sign() > 0)) {
366 return Replace(m.left().node());
368 if (m.right().IsNaN()) {
369 return Replace(m.right().node());
371 if (m.left().IsNaN()) {
372 return Replace(m.left().node());
374 if (m.IsFoldable()) {
375 return ReplaceFloat64(m.left().Value() - m.right().Value());
379 case IrOpcode::kFloat64Mul: {
381 if (m.right().Is(1))
return Replace(m.left().node());
382 if (m.right().IsNaN()) {
383 return Replace(m.right().node());
385 if (m.IsFoldable()) {
386 return ReplaceFloat64(m.left().Value() * m.right().Value());
390 case IrOpcode::kFloat64Div: {
392 if (m.right().Is(1))
return Replace(m.left().node());
393 if (m.right().IsNaN()) {
394 return Replace(m.right().node());
396 if (m.left().IsNaN()) {
397 return Replace(m.left().node());
399 if (m.IsFoldable()) {
400 return ReplaceFloat64(m.left().Value() / m.right().Value());
404 case IrOpcode::kFloat64Mod: {
406 if (m.right().Is(0)) {
407 return ReplaceFloat64(base::OS::nan_value());
409 if (m.right().IsNaN()) {
410 return Replace(m.right().node());
412 if (m.left().IsNaN()) {
413 return Replace(m.left().node());
415 if (m.IsFoldable()) {
416 return ReplaceFloat64(
modulo(m.left().Value(), m.right().Value()));
420 case IrOpcode::kChangeFloat32ToFloat64: {
422 if (m.HasValue())
return ReplaceFloat64(m.Value());
425 case IrOpcode::kChangeFloat64ToInt32: {
427 if (m.HasValue())
return ReplaceInt32(
FastD2I(m.Value()));
428 if (m.IsChangeInt32ToFloat64())
return Replace(m.node()->InputAt(0));
431 case IrOpcode::kChangeFloat64ToUint32: {
433 if (m.HasValue())
return ReplaceInt32(
FastD2UI(m.Value()));
434 if (m.IsChangeUint32ToFloat64())
return Replace(m.node()->InputAt(0));
437 case IrOpcode::kChangeInt32ToFloat64: {
439 if (m.HasValue())
return ReplaceFloat64(
FastI2D(m.Value()));
442 case IrOpcode::kChangeInt32ToInt64: {
444 if (m.HasValue())
return ReplaceInt64(m.Value());
447 case IrOpcode::kChangeUint32ToFloat64: {
449 if (m.HasValue())
return ReplaceFloat64(
FastUI2D(m.Value()));
452 case IrOpcode::kChangeUint32ToUint64: {
454 if (m.HasValue())
return ReplaceInt64(
static_cast<uint64_t
>(m.Value()));
457 case IrOpcode::kTruncateFloat64ToInt32: {
459 if (m.HasValue())
return ReplaceInt32(
DoubleToInt32(m.Value()));
460 if (m.IsChangeInt32ToFloat64())
return Replace(m.node()->InputAt(0));
463 case IrOpcode::kTruncateInt64ToInt32: {
465 if (m.HasValue())
return ReplaceInt32(
static_cast<int32_t>(m.Value()));
466 if (m.IsChangeInt32ToInt64())
return Replace(m.node()->InputAt(0));
469 case IrOpcode::kTruncateFloat64ToFloat32: {
472 if (m.IsChangeFloat32ToFloat64())
return Replace(m.node()->InputAt(0));
482 Reduction MachineOperatorReducer::ReduceProjection(
size_t index, Node* node) {
483 switch (node->opcode()) {
484 case IrOpcode::kInt32AddWithOverflow: {
485 DCHECK(index == 0 || index == 1);
487 if (m.IsFoldable()) {
490 m.right().Value(), &val);
491 return ReplaceInt32((index == 0) ? val : ovf);
493 if (m.right().Is(0)) {
494 return (index == 0) ? Replace(m.left().node()) : ReplaceInt32(0);
498 case IrOpcode::kInt32SubWithOverflow: {
499 DCHECK(index == 0 || index == 1);
501 if (m.IsFoldable()) {
504 m.right().Value(), &val);
505 return ReplaceInt32((index == 0) ? val : ovf);
507 if (m.right().Is(0)) {
508 return (index == 0) ? Replace(m.left().node()) : ReplaceInt32(0);
519 CommonOperatorBuilder* MachineOperatorReducer::common()
const {
520 return jsgraph()->common();
524 MachineOperatorBuilder* MachineOperatorReducer::machine()
const {
525 return jsgraph()->machine();
529 Graph* MachineOperatorReducer::graph()
const {
return jsgraph()->graph(); }
#define DCHECK(condition)
uint32_t RotateRight32(uint32_t value, uint32_t shift)
bool SignedAddOverflow32(int32_t lhs, int32_t rhs, int32_t *val)
bool SignedSubOverflow32(int32_t lhs, int32_t rhs, int32_t *val)
FloatMatcher< float, IrOpcode::kFloat32Constant > Float32Matcher
IntMatcher< int64_t, IrOpcode::kInt64Constant > Int64Matcher
BinopMatcher< Uint32Matcher, Uint32Matcher > Uint32BinopMatcher
BinopMatcher< Int32Matcher, Int32Matcher > Int32BinopMatcher
FloatMatcher< double, IrOpcode::kFloat64Constant > Float64Matcher
BinopMatcher< Float64Matcher, Float64Matcher > Float64BinopMatcher
IntMatcher< int32_t, IrOpcode::kInt32Constant > Int32Matcher
IntMatcher< uint32_t, IrOpcode::kInt32Constant > Uint32Matcher
int WhichPowerOf2(uint32_t x)
unsigned int FastD2UI(double x)
double modulo(double x, double y)
int32_t DoubleToInt32(double x)
float DoubleToFloat32(double x)
double FastUI2D(unsigned x)
const uint32_t kMaxUInt32
Debugger support for the V8 JavaScript engine.