1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/compiler/number_speculative_retype.h"
17 #include "ecmascript/compiler/circuit_builder-inl.h"
18 #include "ecmascript/compiler/gate_meta_data.h"
19 #include "ecmascript/compiler/number_gate_info.h"
20 #include "ecmascript/compiler/type.h"
21 #include <cstdint>
22
23 namespace panda::ecmascript::kungfu {
SetOutputType(GateRef gate,GateType gateType)24 GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, GateType gateType)
25 {
26 TypeInfo type = GetOutputTypeInfo(gate);
27 TypeInfo old = type;
28 if (gateType.IsIntType()) {
29 type = TypeInfo::INT32;
30 } else if (gateType.IsDoubleType()) {
31 type = TypeInfo::FLOAT64;
32 } else if (gateType.IsBooleanType()) {
33 type = TypeInfo::INT1;
34 } else {
35 type = TypeInfo::TAGGED;
36 }
37 SetOutputTypeInfo(gate, type);
38 return old == type ? Circuit::NullGate() : gate;
39 }
40
SetOutputType(GateRef gate,PGOSampleType pgoType)41 GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, PGOSampleType pgoType)
42 {
43 TypeInfo type = GetOutputTypeInfo(gate);
44 TypeInfo old = type;
45 if (pgoType.IsInt()) {
46 type = TypeInfo::INT32;
47 } else {
48 type = TypeInfo::FLOAT64;
49 }
50 SetOutputTypeInfo(gate, type);
51 return old == type ? Circuit::NullGate() : gate;
52 }
53
SetOutputType(GateRef gate,Representation rep)54 GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, Representation rep)
55 {
56 TypeInfo type = GetOutputTypeInfo(gate);
57 TypeInfo old = type;
58 if (rep == Representation::INT) {
59 type = TypeInfo::INT32;
60 } else if (rep == Representation::DOUBLE) {
61 type = TypeInfo::FLOAT64;
62 } else {
63 type = TypeInfo::TAGGED;
64 }
65 SetOutputTypeInfo(gate, type);
66 return old == type ? Circuit::NullGate() : gate;
67 }
68
SetOutputType(GateRef gate,TypeInfo type)69 GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, TypeInfo type)
70 {
71 TypeInfo old = GetOutputTypeInfo(gate);
72 SetOutputTypeInfo(gate, type);
73 return old == type ? Circuit::NullGate() : gate;
74 }
75
VisitGate(GateRef gate)76 GateRef NumberSpeculativeRetype::VisitGate(GateRef gate)
77 {
78 OpCode op = acc_.GetOpCode(gate);
79 switch (op) {
80 case OpCode::TYPED_BINARY_OP:
81 return VisitTypedBinaryOp(gate);
82 case OpCode::TYPED_UNARY_OP:
83 return VisitTypedUnaryOp(gate);
84 case OpCode::TYPED_CONDITION_JUMP:
85 return VisitTypedConditionJump(gate);
86 case OpCode::INDEX_CHECK:
87 return VisitIndexCheck(gate);
88 case OpCode::LOAD_ARRAY_LENGTH:
89 case OpCode::LOAD_TYPED_ARRAY_LENGTH:
90 return VisitLoadArrayLength(gate);
91 case OpCode::LOAD_ELEMENT:
92 return VisitLoadElement(gate);
93 case OpCode::STORE_ELEMENT:
94 return VisitStoreElement(gate);
95 case OpCode::STORE_PROPERTY:
96 return VisitStoreProperty(gate);
97 case OpCode::LOAD_PROPERTY:
98 return VisitLoadProperty(gate);
99 case OpCode::VALUE_SELECTOR:
100 return VisitPhi(gate);
101 case OpCode::CONSTANT:
102 return VisitConstant(gate);
103 case OpCode::TYPED_CALL_BUILTIN:
104 return VisitCallBuiltins(gate);
105 case OpCode::TYPE_CONVERT:
106 return VisitTypeConvert(gate);
107 case OpCode::FRAME_STATE:
108 return VisitFrameState(gate);
109 case OpCode::CALL_GETTER:
110 case OpCode::CALL_SETTER:
111 case OpCode::CONSTRUCT:
112 case OpCode::TYPEDCALL:
113 case OpCode::TYPEDFASTCALL:
114 case OpCode::OBJECT_TYPE_CHECK:
115 return VisitWithConstantValue(gate, PROPERTY_LOOKUP_RESULT_INDEX);
116 case OpCode::LOOP_EXIT_VALUE:
117 case OpCode::RANGE_GUARD:
118 return VisitIntermediateValue(gate);
119 case OpCode::JS_BYTECODE:
120 case OpCode::PRIMITIVE_TYPE_CHECK:
121 case OpCode::STABLE_ARRAY_CHECK:
122 case OpCode::TYPED_ARRAY_CHECK:
123 case OpCode::TYPED_CALLTARGETCHECK_OP:
124 case OpCode::TYPED_CALL_CHECK:
125 case OpCode::HEAP_ALLOC:
126 case OpCode::TYPED_NEW_ALLOCATE_THIS:
127 case OpCode::TYPED_SUPER_ALLOCATE_THIS:
128 case OpCode::GET_SUPER_CONSTRUCTOR:
129 case OpCode::ARG:
130 case OpCode::RETURN:
131 case OpCode::FRAME_ARGS:
132 case OpCode::SAVE_REGISTER:
133 case OpCode::RESTORE_REGISTER:
134 case OpCode::LOAD_CONST_OFFSET:
135 case OpCode::STORE_CONST_OFFSET:
136 case OpCode::LEX_VAR_IS_HOLE_CHECK:
137 return VisitOthers(gate);
138 default:
139 return Circuit::NullGate();
140 }
141 }
142
VisitTypedBinaryOp(GateRef gate)143 GateRef NumberSpeculativeRetype::VisitTypedBinaryOp(GateRef gate)
144 {
145 if (acc_.HasNumberType(gate)) {
146 return VisitNumberBinaryOp(gate);
147 } else {
148 [[maybe_unused]] GateRef left = acc_.GetValueIn(gate, 0);
149 [[maybe_unused]] GateRef right = acc_.GetValueIn(gate, 1);
150 ASSERT((acc_.IsConstantUndefined(left)) || (acc_.IsConstantUndefined(right)));
151 ASSERT(acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_STRICTEQ);
152 return VisitUndefinedStrictEq(gate);
153 }
154 }
155
VisitUndefinedStrictEq(GateRef gate)156 GateRef NumberSpeculativeRetype::VisitUndefinedStrictEq(GateRef gate)
157 {
158 if (IsRetype()) {
159 return SetOutputType(gate, GateType::BooleanType());
160 }
161 if (IsConvert()) {
162 GateRef left = acc_.GetValueIn(gate, 0);
163 GateRef right = acc_.GetValueIn(gate, 1);
164 acc_.ReplaceValueIn(gate, ConvertToTagged(left), 0);
165 acc_.ReplaceValueIn(gate, ConvertToTagged(right), 1);
166 }
167 return Circuit::NullGate();
168 }
169
VisitConstant(GateRef gate)170 GateRef NumberSpeculativeRetype::VisitConstant(GateRef gate)
171 {
172 if (IsRetype()) {
173 if (acc_.GetGateType(gate).IsNJSValueType()) {
174 auto machineType = acc_.GetMachineType(gate);
175 switch (machineType) {
176 case MachineType::I1:
177 SetOutputTypeInfo(gate, TypeInfo::INT1);
178 break;
179 case MachineType::I32:
180 SetOutputTypeInfo(gate, TypeInfo::INT32);
181 break;
182 case MachineType::F64:
183 SetOutputTypeInfo(gate, TypeInfo::FLOAT64);
184 break;
185 default:
186 SetOutputTypeInfo(gate, TypeInfo::NONE);
187 break;
188 }
189 } else {
190 return SetOutputType(gate, GateType::AnyType());
191 }
192 }
193 return Circuit::NullGate();
194 }
195
VisitIntermediateValue(GateRef gate)196 GateRef NumberSpeculativeRetype::VisitIntermediateValue(GateRef gate)
197 {
198 GateRef value = acc_.GetValueIn(gate, 0);
199 TypeInfo valueInfo = GetOutputTypeInfo(value);
200 if (IsRetype()) {
201 TypeInfo oldType = GetOutputTypeInfo(gate);
202 SetOutputTypeInfo(gate, valueInfo);
203 return oldType == valueInfo ? Circuit::NullGate() : gate;
204 }
205 return Circuit::NullGate();
206 }
207
GetOuputForPhi(GateRef gate,bool ignoreConstant)208 TypeInfo NumberSpeculativeRetype::GetOuputForPhi(GateRef gate, bool ignoreConstant)
209 {
210 size_t valueNum = acc_.GetNumValueIn(gate);
211 bool hasConstantInput = false;
212 TypeInfo tempType = TypeInfo::NONE;
213 for (size_t i = 0; i < valueNum; ++i) {
214 GateRef input = acc_.GetValueIn(gate, i);
215 TypeInfo inputInfo = GetOutputTypeInfo(input);
216 if (inputInfo == TypeInfo::NONE) {
217 continue;
218 }
219 if (ignoreConstant && acc_.IsConstantNumber(input)) {
220 hasConstantInput = true;
221 continue;
222 }
223 // use less general input as phi output
224 if (tempType == TypeInfo::NONE) {
225 tempType = inputInfo;
226 } else if (tempType != inputInfo) {
227 tempType = TypeInfo::TAGGED;
228 break;
229 }
230 }
231
232 if (hasConstantInput && ignoreConstant && tempType == TypeInfo::NONE) {
233 return GetOuputForPhi(gate, false);
234 }
235 return tempType;
236 }
237
VisitPhi(GateRef gate)238 GateRef NumberSpeculativeRetype::VisitPhi(GateRef gate)
239 {
240 if (IsRetype()) {
241 auto tempType = GetOuputForPhi(gate, true);
242 TypeInfo typeInfo = GetOutputTypeInfo(gate);
243 if (typeInfo != tempType) {
244 SetOutputTypeInfo(gate, tempType);
245 return gate;
246 }
247 return Circuit::NullGate();
248 }
249 ASSERT(IsConvert());
250 size_t valueNum = acc_.GetNumValueIn(gate);
251 auto merge = acc_.GetState(gate);
252 auto dependSelector = acc_.GetDependSelectorFromMerge(merge);
253 TypeInfo output = GetOutputTypeInfo(gate);
254 for (size_t i = 0; i < valueNum; ++i) {
255 GateRef input = acc_.GetValueIn(gate, i);
256 if (output == TypeInfo::TAGGED || output == TypeInfo::NONE) {
257 input = ConvertToTagged(input);
258 } else {
259 auto state = acc_.GetState(merge, i);
260 auto depend = acc_.GetDep(dependSelector, i);
261 Environment env(state, depend, {}, circuit_, &builder_);
262 input = ConvertTaggedToNJSValue(input, output);
263 acc_.ReplaceStateIn(merge, builder_.GetState(), i);
264 acc_.ReplaceDependIn(dependSelector, builder_.GetDepend(), i);
265 }
266 acc_.ReplaceValueIn(gate, input, i);
267 }
268 return Circuit::NullGate();
269 }
270
ConvertTaggedToNJSValue(GateRef gate,TypeInfo output)271 GateRef NumberSpeculativeRetype::ConvertTaggedToNJSValue(GateRef gate, TypeInfo output)
272 {
273 TypeInfo curOutput = GetOutputTypeInfo(gate);
274 if (curOutput != TypeInfo::TAGGED) {
275 return gate;
276 }
277 switch (output) {
278 case TypeInfo::INT1:
279 return CheckAndConvertToBool(gate, GateType::BooleanType());
280 case TypeInfo::INT32:
281 return CheckAndConvertToInt32(gate, GateType::NumberType());
282 case TypeInfo::FLOAT64:
283 return CheckAndConvertToFloat64(gate, GateType::NumberType());
284 default:
285 LOG_COMPILER(FATAL) << "this branch is unreachable";
286 UNREACHABLE();
287 return Circuit::NullGate();
288 }
289 }
290
VisitNumberBinaryOp(GateRef gate)291 GateRef NumberSpeculativeRetype::VisitNumberBinaryOp(GateRef gate)
292 {
293 TypedBinOp op = acc_.GetTypedBinaryOp(gate);
294 switch (op) {
295 case TypedBinOp::TYPED_ADD:
296 case TypedBinOp::TYPED_SUB:
297 case TypedBinOp::TYPED_MUL:
298 case TypedBinOp::TYPED_DIV: {
299 return VisitNumberCalculate(gate);
300 }
301 case TypedBinOp::TYPED_LESS:
302 case TypedBinOp::TYPED_LESSEQ:
303 case TypedBinOp::TYPED_GREATER:
304 case TypedBinOp::TYPED_GREATEREQ:
305 case TypedBinOp::TYPED_EQ:
306 case TypedBinOp::TYPED_NOTEQ:
307 case TypedBinOp::TYPED_STRICTEQ: {
308 return VisitNumberCompare(gate);
309 }
310 case TypedBinOp::TYPED_SHL:
311 case TypedBinOp::TYPED_SHR:
312 case TypedBinOp::TYPED_ASHR:
313 case TypedBinOp::TYPED_AND:
314 case TypedBinOp::TYPED_OR:
315 case TypedBinOp::TYPED_XOR: {
316 return VisitNumberShiftAndLogical(gate);
317 }
318 case TypedBinOp::TYPED_MOD: {
319 return VisitNumberMod(gate);
320 }
321 default:
322 return VisitNumberRelated(gate);
323 }
324 }
325
VisitTypedUnaryOp(GateRef gate)326 GateRef NumberSpeculativeRetype::VisitTypedUnaryOp(GateRef gate)
327 {
328 Environment env(gate, circuit_, &builder_);
329 TypedUnOp Op = acc_.GetTypedUnAccessor(gate).GetTypedUnOp();
330 switch (Op) {
331 case TypedUnOp::TYPED_INC:
332 case TypedUnOp::TYPED_DEC:
333 case TypedUnOp::TYPED_NEG:
334 return VisitNumberMonocular(gate);
335 case TypedUnOp::TYPED_NOT:
336 return VisitNumberNot(gate);
337 case TypedUnOp::TYPED_ISFALSE:
338 case TypedUnOp::TYPED_ISTRUE:
339 return VisitIsTrueOrFalse(gate);
340 default:
341 return VisitNumberRelated(gate);
342 }
343 }
344
VisitTypedConditionJump(GateRef gate)345 GateRef NumberSpeculativeRetype::VisitTypedConditionJump(GateRef gate)
346 {
347 Environment env(gate, circuit_, &builder_);
348 TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
349 auto type = accessor.GetTypeValue();
350 if (type.IsBooleanType()) {
351 return VisitBooleanJump(gate);
352 } else {
353 UNREACHABLE();
354 return Circuit::NullGate();
355 }
356 }
357
VisitNumberCalculate(GateRef gate)358 GateRef NumberSpeculativeRetype::VisitNumberCalculate(GateRef gate)
359 {
360 if (IsRetype()) {
361 PGOSampleType sampleType = acc_.GetTypedBinaryType(gate);
362 if (sampleType.IsNumber()) {
363 return SetOutputType(gate, sampleType);
364 } else {
365 GateType gateType = acc_.GetGateType(gate);
366 GateType resType = gateType.IsIntType() ? GateType::IntType() : GateType::DoubleType();
367 return SetOutputType(gate, resType);
368 }
369 } else if (IsConvert()) {
370 Environment env(gate, circuit_, &builder_);
371 ConvertForBinaryOp(gate);
372 }
373 return Circuit::NullGate();
374 }
375
VisitNumberCompare(GateRef gate)376 GateRef NumberSpeculativeRetype::VisitNumberCompare(GateRef gate)
377 {
378 if (IsRetype()) {
379 return SetOutputType(gate, GateType::BooleanType());
380 }
381 if (IsConvert()) {
382 Environment env(gate, circuit_, &builder_);
383 ConvertForCompareOp(gate);
384 }
385 return Circuit::NullGate();
386 }
387
VisitNumberShiftAndLogical(GateRef gate)388 GateRef NumberSpeculativeRetype::VisitNumberShiftAndLogical(GateRef gate)
389 {
390 if (IsRetype()) {
391 return SetOutputType(gate, GateType::IntType());
392 }
393 if (IsConvert()) {
394 Environment env(gate, circuit_, &builder_);
395 GateType leftType = acc_.GetLeftType(gate);
396 GateType rightType = acc_.GetRightType(gate);
397 PGOSampleType sampleType = acc_.GetTypedBinaryType(gate);
398 if (sampleType.IsNumber()) {
399 if (sampleType.IsInt()) {
400 leftType = GateType::IntType();
401 rightType = GateType::IntType();
402 } else {
403 leftType = GateType::NumberType();
404 rightType = GateType::NumberType();
405 }
406 }
407 ConvertForShiftAndLogicalOperator(gate, leftType, rightType);
408 }
409 return Circuit::NullGate();
410 }
411
VisitNumberMonocular(GateRef gate)412 GateRef NumberSpeculativeRetype::VisitNumberMonocular(GateRef gate)
413 {
414 TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
415 GateType type = accessor.GetTypeValue();
416 ASSERT(type.IsNumberType());
417 if (type.IsIntType()) {
418 return VisitIntMonocular(gate);
419 } else {
420 return VisitDoubleMonocular(gate);
421 }
422 }
423
VisitIntMonocular(GateRef gate)424 GateRef NumberSpeculativeRetype::VisitIntMonocular(GateRef gate)
425 {
426 if (IsRetype()) {
427 return SetOutputType(gate, GateType::IntType());
428 }
429
430 if (IsConvert()) {
431 GateRef value = acc_.GetValueIn(gate, 0);
432 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(value, GateType::IntType()), 0);
433 acc_.ReplaceStateIn(gate, builder_.GetState());
434 acc_.ReplaceDependIn(gate, builder_.GetDepend());
435 }
436 return Circuit::NullGate();
437 }
438
VisitDoubleMonocular(GateRef gate)439 GateRef NumberSpeculativeRetype::VisitDoubleMonocular(GateRef gate)
440 {
441 if (IsRetype()) {
442 return SetOutputType(gate, GateType::DoubleType());
443 }
444
445 if (IsConvert()) {
446 TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
447 GateRef value = acc_.GetValueIn(gate, 0);
448 acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(value, accessor.GetTypeValue()), 0);
449 acc_.ReplaceStateIn(gate, builder_.GetState());
450 acc_.ReplaceDependIn(gate, builder_.GetDepend());
451 }
452 return Circuit::NullGate();
453 }
454
VisitIsTrueOrFalse(GateRef gate)455 GateRef NumberSpeculativeRetype::VisitIsTrueOrFalse(GateRef gate)
456 {
457 TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
458 GateType valueType = accessor.GetTypeValue();
459 ASSERT(valueType.IsNumberType() || valueType.IsBooleanType());
460 if (IsRetype()) {
461 return SetOutputType(gate, GateType::BooleanType());
462 }
463 if (IsConvert()) {
464 Environment env(gate, circuit_, &builder_);
465 GateRef value = acc_.GetValueIn(gate, 0);
466 auto input = CheckAndConvertToBool(value, valueType);
467 ResizeAndSetTypeInfo(input, TypeInfo::INT1);
468 acc_.ReplaceValueIn(gate, input, 0);
469 acc_.ReplaceStateIn(gate, builder_.GetState());
470 acc_.ReplaceDependIn(gate, builder_.GetDepend());
471 }
472 return Circuit::NullGate();
473 }
474
VisitNumberNot(GateRef gate)475 GateRef NumberSpeculativeRetype::VisitNumberNot(GateRef gate)
476 {
477 TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
478 GateType valueType = accessor.GetTypeValue();
479 ASSERT(valueType.IsNumberType());
480 if (IsRetype()) {
481 return SetOutputType(gate, GateType::IntType());
482 }
483 if (IsConvert()) {
484 Environment env(gate, circuit_, &builder_);
485 GateRef value = acc_.GetValueIn(gate, 0);
486 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(value, valueType), 0);
487 acc_.ReplaceStateIn(gate, builder_.GetState());
488 acc_.ReplaceDependIn(gate, builder_.GetDepend());
489 }
490 return Circuit::NullGate();
491 }
492
VisitBooleanJump(GateRef gate)493 GateRef NumberSpeculativeRetype::VisitBooleanJump(GateRef gate)
494 {
495 if (IsRetype()) {
496 return SetOutputType(gate, GateType::AnyType());
497 }
498 if (IsConvert()) {
499 Environment env(gate, circuit_, &builder_);
500 GateRef value = acc_.GetValueIn(gate, 0);
501 GateRef input = Circuit::NullGate();
502 if (GetOutputTypeInfo(value) == TypeInfo::TAGGED) {
503 // use TaggedIsTrue
504 input = builder_.ConvertTaggedBooleanToBool(value);
505 } else {
506 input = CheckAndConvertToBool(value, GateType::BooleanType());
507 }
508 ResizeAndSetTypeInfo(input, TypeInfo::INT1);
509 acc_.ReplaceValueIn(gate, input, 0);
510 acc_.ReplaceStateIn(gate, builder_.GetState());
511 acc_.ReplaceDependIn(gate, builder_.GetDepend());
512 }
513 return Circuit::NullGate();
514 }
515
VisitNumberRelated(GateRef gate)516 GateRef NumberSpeculativeRetype::VisitNumberRelated(GateRef gate)
517 {
518 if (IsRetype()) {
519 return SetOutputType(gate, GateType::NumberType());
520 }
521 if (IsConvert()) {
522 Environment env(gate, circuit_, &builder_);
523 size_t valueNum = acc_.GetNumValueIn(gate);
524 for (size_t i = 0; i < valueNum; ++i) {
525 GateRef input = acc_.GetValueIn(gate, i);
526 GateType inputType = acc_.GetGateType(input);
527 if (inputType.IsNumberType() || inputType.IsBooleanType()) {
528 acc_.ReplaceValueIn(gate, CheckAndConvertToTagged(input, inputType), i);
529 }
530 }
531 acc_.ReplaceStateIn(gate, builder_.GetState());
532 acc_.ReplaceDependIn(gate, builder_.GetDepend());
533 }
534 return Circuit::NullGate();
535 }
536
VisitCallBuiltins(GateRef gate)537 GateRef NumberSpeculativeRetype::VisitCallBuiltins(GateRef gate)
538 {
539 auto valuesIn = acc_.GetNumValueIn(gate);
540 auto idGate = acc_.GetValueIn(gate, valuesIn - 1);
541 auto id = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(idGate));
542 if (id != BUILTINS_STUB_ID(SQRT)) {
543 return VisitOthers(gate);
544 }
545
546 if (IsRetype()) {
547 // Sqrt output is double
548 return SetOutputType(gate, GateType::DoubleType());
549 }
550 if (IsConvert()) {
551 Environment env(gate, circuit_, &builder_);
552 acc_.ReplaceValueIn(gate, ConvertToTagged(idGate), valuesIn - 1);
553 for (size_t i = 0; i < valuesIn - 1; ++i) {
554 GateRef input = acc_.GetValueIn(gate, i);
555 acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(input, GateType::NumberType()), i);
556 }
557 acc_.ReplaceStateIn(gate, builder_.GetState());
558 acc_.ReplaceDependIn(gate, builder_.GetDepend());
559 }
560 return Circuit::NullGate();
561 }
562
VisitFrameState(GateRef gate)563 GateRef NumberSpeculativeRetype::VisitFrameState(GateRef gate)
564 {
565 if (IsRetype()) {
566 return SetOutputType(gate, GateType::AnyType());
567 }
568 return Circuit::NullGate();
569 }
570
VisitOthers(GateRef gate)571 GateRef NumberSpeculativeRetype::VisitOthers(GateRef gate)
572 {
573 if (IsRetype()) {
574 return SetOutputType(gate, GateType::AnyType());
575 }
576 if (IsConvert()) {
577 size_t valueNum = acc_.GetNumValueIn(gate);
578 for (size_t i = 0; i < valueNum; ++i) {
579 GateRef input = acc_.GetValueIn(gate, i);
580 acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
581 }
582 }
583 return Circuit::NullGate();
584 }
585
VisitWithConstantValue(GateRef gate,size_t ignoreIndex)586 GateRef NumberSpeculativeRetype::VisitWithConstantValue(GateRef gate, size_t ignoreIndex)
587 {
588 if (IsRetype()) {
589 return SetOutputType(gate, GateType::AnyType());
590 }
591 if (IsConvert()) {
592 size_t valueNum = acc_.GetNumValueIn(gate);
593 for (size_t i = 0; i < valueNum; ++i) {
594 if (i == ignoreIndex) {
595 continue;
596 }
597 GateRef input = acc_.GetValueIn(gate, i);
598 acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
599 }
600 }
601 return Circuit::NullGate();
602 }
603
CheckAndConvertToBool(GateRef gate,GateType gateType)604 GateRef NumberSpeculativeRetype::CheckAndConvertToBool(GateRef gate, GateType gateType)
605 {
606 TypeInfo output = GetOutputTypeInfo(gate);
607 switch (output) {
608 case TypeInfo::INT1:
609 return gate;
610 case TypeInfo::INT32:
611 return builder_.ConvertInt32ToBool(gate);
612 case TypeInfo::UINT32:
613 return builder_.ConvertUInt32ToBool(gate);
614 case TypeInfo::FLOAT64:
615 return builder_.ConvertFloat64ToBool(gate);
616 case TypeInfo::TAGGED: {
617 if (gateType.IsBooleanType()) {
618 return builder_.CheckTaggedBooleanAndConvertToBool(gate);
619 } else {
620 ASSERT(gateType.IsNumberType());
621 return builder_.CheckTaggedNumberAndConvertToBool(gate);
622 }
623 }
624 default: {
625 UNREACHABLE();
626 return Circuit::NullGate();
627 }
628 }
629 }
630
ConvertForBinaryOp(GateRef gate)631 void NumberSpeculativeRetype::ConvertForBinaryOp(GateRef gate)
632 {
633 PGOSampleType sampleType = acc_.GetTypedBinaryType(gate);
634 if (sampleType.IsNumber()) {
635 if (sampleType.IsInt()) {
636 GateType leftType = GateType::IntType();
637 GateType rightType = GateType::IntType();
638 ConvertForIntOperator(gate, leftType, rightType);
639 } else {
640 GateType leftType = GateType::NumberType();
641 GateType rightType = GateType::NumberType();
642 if (sampleType.IsIntOverFlow()) {
643 leftType = GateType::IntType();
644 rightType = GateType::IntType();
645 } else if (sampleType.IsDouble()) {
646 leftType = GateType::DoubleType();
647 rightType = GateType::DoubleType();
648 }
649 ConvertForDoubleOperator(gate, leftType, rightType);
650 }
651 } else {
652 GateType gateType = acc_.GetGateType(gate);
653 GateType leftType = acc_.GetLeftType(gate);
654 GateType rightType = acc_.GetRightType(gate);
655 if (gateType.IsIntType()) {
656 ConvertForIntOperator(gate, leftType, rightType);
657 } else {
658 ConvertForDoubleOperator(gate, leftType, rightType);
659 }
660 }
661 }
662
ConvertForCompareOp(GateRef gate)663 void NumberSpeculativeRetype::ConvertForCompareOp(GateRef gate)
664 {
665 PGOSampleType sampleType = acc_.GetTypedBinaryType(gate);
666 if (sampleType.IsNumber()) {
667 if (sampleType.IsInt()) {
668 GateType leftType = GateType::IntType();
669 GateType rightType = GateType::IntType();
670 ConvertForIntOperator(gate, leftType, rightType);
671 } else {
672 GateType leftType = GateType::NumberType();
673 GateType rightType = GateType::NumberType();
674 ConvertForDoubleOperator(gate, leftType, rightType);
675 }
676 } else {
677 GateType leftType = acc_.GetLeftType(gate);
678 GateType rightType = acc_.GetRightType(gate);
679 if (leftType.IsIntType() && rightType.IsIntType()) {
680 ConvertForIntOperator(gate, leftType, rightType);
681 } else {
682 ConvertForDoubleOperator(gate, leftType, rightType);
683 }
684 }
685 }
686
ConvertForIntOperator(GateRef gate,GateType leftType,GateType rightType)687 void NumberSpeculativeRetype::ConvertForIntOperator(GateRef gate, GateType leftType, GateType rightType)
688 {
689 GateRef left = acc_.GetValueIn(gate, 0);
690 GateRef right = acc_.GetValueIn(gate, 1);
691
692 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(left, leftType), 0);
693 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(right, rightType), 1);
694
695 acc_.ReplaceStateIn(gate, builder_.GetState());
696 acc_.ReplaceDependIn(gate, builder_.GetDepend());
697 }
698
ConvertForShiftAndLogicalOperator(GateRef gate,GateType leftType,GateType rightType)699 void NumberSpeculativeRetype::ConvertForShiftAndLogicalOperator(GateRef gate, GateType leftType, GateType rightType)
700 {
701 GateRef left = acc_.GetValueIn(gate, 0);
702 GateRef right = acc_.GetValueIn(gate, 1);
703 GateRef cLeft = CheckAndConvertToInt32(left, leftType, ConvertSupport::ENABLE, OpType::SHIFT_AND_LOGICAL);
704 GateRef cRight = CheckAndConvertToInt32(right, rightType, ConvertSupport::ENABLE, OpType::SHIFT_AND_LOGICAL);
705
706 acc_.ReplaceValueIn(gate, cLeft, 0);
707 acc_.ReplaceValueIn(gate, cRight, 1);
708
709 acc_.ReplaceStateIn(gate, builder_.GetState());
710 acc_.ReplaceDependIn(gate, builder_.GetDepend());
711 }
712
ConvertForDoubleOperator(GateRef gate,GateType leftType,GateType rightType)713 void NumberSpeculativeRetype::ConvertForDoubleOperator(GateRef gate, GateType leftType, GateType rightType)
714 {
715 GateRef left = acc_.GetValueIn(gate, 0);
716 GateRef right = acc_.GetValueIn(gate, 1);
717
718 acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(left, leftType), 0);
719 acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(right, rightType), 1);
720
721 acc_.ReplaceStateIn(gate, builder_.GetState());
722 acc_.ReplaceDependIn(gate, builder_.GetDepend());
723 }
724
TryConvertConstant(GateRef gate,bool needInt32)725 GateRef NumberSpeculativeRetype::TryConvertConstant(GateRef gate, bool needInt32)
726 {
727 if (acc_.GetOpCode(gate) != OpCode::CONSTANT) {
728 return Circuit::NullGate();
729 }
730
731 if (acc_.GetGateType(gate).IsNJSValueType()) {
732 MachineType mType = acc_.GetMachineType(gate);
733 if(mType == MachineType::I32) {
734 int32_t rawValue = acc_.GetInt32FromConstant(gate);
735 double value = static_cast<double>(rawValue);
736 return needInt32 ? builder_.Int32(rawValue) : builder_.Double(value);
737 } else if(mType == MachineType::F64 && !needInt32) {
738 double rawValue = acc_.GetFloat64FromConstant(gate);
739 return builder_.Double(rawValue);
740 } else {
741 return Circuit::NullGate();
742 }
743 }
744
745 JSTaggedValue value(acc_.GetConstantValue(gate));
746 if(value.IsInt()) {
747 int32_t rawValue = value.GetInt();
748 double doubleValue = static_cast<double>(rawValue);
749 return needInt32 ? builder_.Int32(rawValue) : builder_.Double(doubleValue);
750 } else if(value.IsDouble() && !needInt32) {
751 double rawValue = value.GetDouble();
752 return builder_.Double(rawValue);
753 }
754 return Circuit::NullGate();
755 }
756
CheckAndConvertToInt32(GateRef gate,GateType gateType,ConvertSupport support,OpType type)757 GateRef NumberSpeculativeRetype::CheckAndConvertToInt32(GateRef gate, GateType gateType, ConvertSupport support,
758 OpType type)
759 {
760 auto result = TryConvertConstant(gate, true);
761 if (result != Circuit::NullGate()) {
762 acc_.DeleteGateIfNoUse(gate);
763 ResizeAndSetTypeInfo(result, TypeInfo::INT32);
764 return result;
765 }
766 TypeInfo output = GetOutputTypeInfo(gate);
767 switch (output) {
768 case TypeInfo::INT1:
769 result = builder_.ConvertBoolToInt32(gate, support);
770 break;
771 case TypeInfo::INT32:
772 return gate;
773 case TypeInfo::UINT32: {
774 if (type != OpType::SHIFT_AND_LOGICAL) {
775 result = builder_.CheckUInt32AndConvertToInt32(gate);
776 } else {
777 result = gate;
778 }
779 break;
780 }
781 case TypeInfo::FLOAT64:
782 result = builder_.ConvertFloat64ToInt32(gate);
783 break;
784 case TypeInfo::TAGGED: {
785 if (gateType.IsIntType()) {
786 result = builder_.CheckTaggedIntAndConvertToInt32(gate);
787 } else if (gateType.IsDoubleType()) {
788 result = builder_.CheckTaggedDoubleAndConvertToInt32(gate);
789 } else {
790 result = builder_.CheckTaggedNumberAndConvertToInt32(gate);
791 }
792 break;
793 }
794 default: {
795 LOG_ECMA(FATAL) << "this branch is unreachable";
796 UNREACHABLE();
797 return Circuit::NullGate();
798 }
799 }
800 ResizeAndSetTypeInfo(result, TypeInfo::INT32);
801 return result;
802 }
803
CheckAndConvertToFloat64(GateRef gate,GateType gateType,ConvertSupport support)804 GateRef NumberSpeculativeRetype::CheckAndConvertToFloat64(GateRef gate, GateType gateType, ConvertSupport support)
805 {
806 auto result = TryConvertConstant(gate, false);
807 if (result != Circuit::NullGate()) {
808 acc_.DeleteGateIfNoUse(gate);
809 ResizeAndSetTypeInfo(result, TypeInfo::FLOAT64);
810 return result;
811 }
812 TypeInfo output = GetOutputTypeInfo(gate);
813 switch (output) {
814 case TypeInfo::INT1:
815 result = builder_.ConvertBoolToFloat64(gate, support);
816 break;
817 case TypeInfo::INT32:
818 result = builder_.ConvertInt32ToFloat64(gate);
819 break;
820 case TypeInfo::UINT32:
821 result = builder_.ConvertUInt32ToFloat64(gate);
822 break;
823 case TypeInfo::FLOAT64:
824 return gate;
825 case TypeInfo::TAGGED: {
826 if (gateType.IsIntType()) {
827 result = builder_.CheckTaggedIntAndConvertToFloat64(gate);
828 } else if (gateType.IsDoubleType()) {
829 result = builder_.CheckTaggedDoubleAndConvertToFloat64(gate);
830 } else {
831 result = builder_.CheckTaggedNumberAndConvertToFloat64(gate);
832 }
833 break;
834 }
835 default: {
836 LOG_ECMA(FATAL) << "this branch is unreachable";
837 UNREACHABLE();
838 return Circuit::NullGate();
839 }
840 }
841 ResizeAndSetTypeInfo(result, TypeInfo::FLOAT64);
842 return result;
843 }
844
CheckAndConvertToTagged(GateRef gate,GateType gateType)845 GateRef NumberSpeculativeRetype::CheckAndConvertToTagged(GateRef gate, GateType gateType)
846 {
847 TypeInfo output = GetOutputTypeInfo(gate);
848 switch (output) {
849 case TypeInfo::INT1:
850 return builder_.ConvertBoolToTaggedBoolean(gate);
851 case TypeInfo::INT32:
852 return builder_.ConvertInt32ToTaggedInt(gate);
853 case TypeInfo::UINT32:
854 return builder_.ConvertUInt32ToTaggedNumber(gate);
855 case TypeInfo::FLOAT64:
856 return builder_.ConvertFloat64ToTaggedDouble(gate);
857 case TypeInfo::TAGGED: {
858 ASSERT(gateType.IsNumberType() || gateType.IsBooleanType());
859 builder_.TryPrimitiveTypeCheck(gateType, gate);
860 return gate;
861 }
862 default:
863 LOG_ECMA(FATAL) << "this branch is unreachable";
864 UNREACHABLE();
865 return Circuit::NullGate();
866 }
867 }
868
ConvertToTagged(GateRef gate)869 GateRef NumberSpeculativeRetype::ConvertToTagged(GateRef gate)
870 {
871 TypeInfo output = GetOutputTypeInfo(gate);
872 switch (output) {
873 case TypeInfo::INT1:
874 return builder_.ConvertBoolToTaggedBoolean(gate);
875 case TypeInfo::INT32:
876 return builder_.ConvertInt32ToTaggedInt(gate);
877 case TypeInfo::UINT32:
878 return builder_.ConvertUInt32ToTaggedNumber(gate);
879 case TypeInfo::FLOAT64:
880 return builder_.ConvertFloat64ToTaggedDouble(gate);
881 case TypeInfo::NONE:
882 case TypeInfo::TAGGED: {
883 return gate;
884 }
885 default:
886 LOG_ECMA(FATAL) << "this branch is unreachable";
887 UNREACHABLE();
888 return Circuit::NullGate();
889 }
890 }
891
VisitIndexCheck(GateRef gate)892 GateRef NumberSpeculativeRetype::VisitIndexCheck(GateRef gate)
893 {
894 if (IsRetype()) {
895 return SetOutputType(gate, GateType::IntType());
896 }
897
898 if (IsConvert()) {
899 Environment env(gate, circuit_, &builder_);
900 GateRef receiver = acc_.GetValueIn(gate, 0);
901 GateRef index = acc_.GetValueIn(gate, 1);
902 GateType receiverType = acc_.GetGateType(receiver);
903 GateType indexType = acc_.GetGateType(index);
904 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(receiver, receiverType), 0);
905 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(index, indexType), 1);
906
907 acc_.ReplaceStateIn(gate, builder_.GetState());
908 acc_.ReplaceDependIn(gate, builder_.GetDepend());
909 }
910
911 return Circuit::NullGate();
912 }
913
VisitLoadArrayLength(GateRef gate)914 GateRef NumberSpeculativeRetype::VisitLoadArrayLength(GateRef gate)
915 {
916 if (IsRetype()) {
917 return SetOutputType(gate, GateType::IntType());
918 }
919
920 return Circuit::NullGate();
921 }
922
VisitLoadElement(GateRef gate)923 GateRef NumberSpeculativeRetype::VisitLoadElement(GateRef gate)
924 {
925 if (IsRetype()) {
926 auto op = acc_.GetTypedLoadOp(gate);
927 switch (op) {
928 case TypedLoadOp::INT8ARRAY_LOAD_ELEMENT:
929 case TypedLoadOp::UINT8ARRAY_LOAD_ELEMENT:
930 case TypedLoadOp::UINT8CLAMPEDARRAY_LOAD_ELEMENT:
931 case TypedLoadOp::INT16ARRAY_LOAD_ELEMENT:
932 case TypedLoadOp::UINT16ARRAY_LOAD_ELEMENT:
933 case TypedLoadOp::INT32ARRAY_LOAD_ELEMENT:
934 return SetOutputType(gate, GateType::IntType());
935 case TypedLoadOp::UINT32ARRAY_LOAD_ELEMENT:
936 return SetOutputType(gate, TypeInfo::UINT32);
937 case TypedLoadOp::FLOAT32ARRAY_LOAD_ELEMENT:
938 case TypedLoadOp::FLOAT64ARRAY_LOAD_ELEMENT:
939 return SetOutputType(gate, GateType::DoubleType());
940 default:
941 return SetOutputType(gate, GateType::AnyType());
942 }
943 }
944
945 if (IsConvert()) {
946 Environment env(gate, circuit_, &builder_);
947 GateRef index = acc_.GetValueIn(gate, 1);
948 GateType indexType = acc_.GetGateType(index);
949 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(index, indexType), 1);
950 acc_.ReplaceStateIn(gate, builder_.GetState());
951 acc_.ReplaceDependIn(gate, builder_.GetDepend());
952 }
953
954 return Circuit::NullGate();
955 }
956
VisitStoreElement(GateRef gate)957 GateRef NumberSpeculativeRetype::VisitStoreElement(GateRef gate)
958 {
959 if (IsRetype()) {
960 return SetOutputType(gate, GateType::AnyType());
961 }
962
963 if (IsConvert()) {
964 Environment env(gate, circuit_, &builder_);
965 GateRef index = acc_.GetValueIn(gate, 1);
966 GateType indexType = acc_.GetGateType(index);
967 GateRef value = acc_.GetValueIn(gate, 2);
968 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(index, indexType), 1);
969 auto op = acc_.GetTypedStoreOp(gate);
970 switch (op) {
971 case TypedStoreOp::INT8ARRAY_STORE_ELEMENT:
972 case TypedStoreOp::UINT8ARRAY_STORE_ELEMENT:
973 case TypedStoreOp::UINT8CLAMPEDARRAY_STORE_ELEMENT:
974 case TypedStoreOp::INT16ARRAY_STORE_ELEMENT:
975 case TypedStoreOp::UINT16ARRAY_STORE_ELEMENT:
976 case TypedStoreOp::INT32ARRAY_STORE_ELEMENT:
977 case TypedStoreOp::UINT32ARRAY_STORE_ELEMENT:
978 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(value, GateType::NumberType()), 2); // 2: value idx
979 break;
980 case TypedStoreOp::FLOAT32ARRAY_STORE_ELEMENT:
981 case TypedStoreOp::FLOAT64ARRAY_STORE_ELEMENT:
982 acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(value, GateType::NumberType()), 2); // 2: value idx
983 break;
984 default:
985 acc_.ReplaceValueIn(gate, ConvertToTagged(value), 2); // 2: value idx
986 break;
987 }
988 acc_.ReplaceStateIn(gate, builder_.GetState());
989 acc_.ReplaceDependIn(gate, builder_.GetDepend());
990 }
991
992 return Circuit::NullGate();
993 }
994
VisitStoreProperty(GateRef gate)995 GateRef NumberSpeculativeRetype::VisitStoreProperty(GateRef gate)
996 {
997 if (IsRetype()) {
998 return SetOutputType(gate, GateType::AnyType());
999 }
1000 ASSERT(IsConvert());
1001 GateRef value = acc_.GetValueIn(gate, 2); // 2: value
1002
1003 Environment env(gate, circuit_, &builder_);
1004 GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1005 PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1006 if (plr.GetRepresentation() == Representation::DOUBLE) {
1007 acc_.SetMetaData(gate, circuit_->StorePropertyNoBarrier());
1008 acc_.ReplaceValueIn(
1009 gate, CheckAndConvertToFloat64(value, acc_.GetGateType(value), ConvertSupport::DISABLE), 2); // 2: value
1010 } else if (plr.GetRepresentation() == Representation::INT) {
1011 acc_.SetMetaData(gate, circuit_->StorePropertyNoBarrier());
1012 acc_.ReplaceValueIn(
1013 gate, CheckAndConvertToInt32(value, acc_.GetGateType(value), ConvertSupport::DISABLE), 2); // 2: value
1014 } else {
1015 TypeInfo valueType = GetOutputTypeInfo(value);
1016 if (valueType == TypeInfo::INT1 || valueType == TypeInfo::INT32 || valueType == TypeInfo::FLOAT64) {
1017 acc_.SetMetaData(gate, circuit_->StorePropertyNoBarrier());
1018 }
1019 acc_.ReplaceValueIn(gate, ConvertToTagged(value), 2); // 2: value
1020 }
1021
1022 GateRef receiver = acc_.GetValueIn(gate, 0); // receiver
1023 acc_.ReplaceValueIn(gate, ConvertToTagged(receiver), 0);
1024 acc_.ReplaceStateIn(gate, builder_.GetState());
1025 acc_.ReplaceDependIn(gate, builder_.GetDepend());
1026 return Circuit::NullGate();
1027 }
1028
VisitLoadProperty(GateRef gate)1029 GateRef NumberSpeculativeRetype::VisitLoadProperty(GateRef gate)
1030 {
1031 if (IsRetype()) {
1032 GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1033 PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1034 return SetOutputType(gate, plr.GetRepresentation());
1035 }
1036
1037 ASSERT(IsConvert());
1038
1039 return VisitWithConstantValue(gate, PROPERTY_LOOKUP_RESULT_INDEX); // ignoreIndex
1040 }
1041
VisitTypeConvert(GateRef gate)1042 GateRef NumberSpeculativeRetype::VisitTypeConvert(GateRef gate)
1043 {
1044 GateRef input = acc_.GetValueIn(gate, 0);
1045 TypeInfo inputInfo = GetOutputTypeInfo(input);
1046 if (IsRetype()) {
1047 if (inputInfo == TypeInfo::TAGGED) {
1048 if (acc_.IsConstantNumber(input)) {
1049 return Circuit::NullGate();
1050 }
1051 GateType gateType = acc_.GetGateType(gate);
1052 ASSERT(gateType.IsNumberType());
1053 GateType resType = gateType.IsIntType() ? GateType::IntType() : GateType::DoubleType();
1054 return SetOutputType(gate, resType);
1055 }
1056 TypeInfo oldType = GetOutputTypeInfo(gate);
1057 SetOutputTypeInfo(gate, inputInfo);
1058 return oldType == inputInfo ? Circuit::NullGate() : gate;
1059 }
1060 ASSERT(IsConvert());
1061 ASSERT(inputInfo != TypeInfo::INT1 && inputInfo != TypeInfo::NONE);
1062 Environment env(gate, circuit_, &builder_);
1063 if (inputInfo == TypeInfo::TAGGED && !acc_.IsConstantNumber(input)) {
1064 GateType gateType = acc_.GetGateType(gate);
1065 ASSERT(gateType.IsNumberType());
1066 if (gateType.IsIntType()) {
1067 input = CheckAndConvertToInt32(input, GateType::IntType());
1068 ResizeAndSetTypeInfo(input, TypeInfo::INT32);
1069 } else {
1070 input = CheckAndConvertToFloat64(input, acc_.GetGateType(input));
1071 ResizeAndSetTypeInfo(input, TypeInfo::FLOAT64);
1072 }
1073 }
1074 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), input);
1075 return Circuit::NullGate();
1076 }
1077
VisitNumberMod(GateRef gate)1078 GateRef NumberSpeculativeRetype::VisitNumberMod(GateRef gate)
1079 {
1080 if (IsRetype()) {
1081 PGOSampleType sampleType = acc_.GetTypedBinaryType(gate);
1082 if (sampleType.IsNumber()) {
1083 return SetOutputType(gate, sampleType);
1084 } else {
1085 GateType gateType = acc_.GetGateType(gate);
1086 GateType resType = gateType.IsIntType() ? GateType::IntType() : GateType::DoubleType();
1087 return SetOutputType(gate, resType);
1088 }
1089 } else if (IsConvert()) {
1090 Environment env(gate, circuit_, &builder_);
1091 ConvertForBinaryOp(gate);
1092 }
1093
1094 return Circuit::NullGate();
1095 }
1096
Run()1097 void NumberSpeculativeRetype::Run()
1098 {
1099 // visit gate in RPO, propagate use infos and
1100 // reset the machine type of number operator gate and related phi,
1101 // if some tagged phi is used as native value, change it to native phi.
1102 state_ = State::Retype;
1103 VisitGraph();
1104 state_ = State::Convert;
1105 VisitGraph();
1106 }
1107
1108 } // namespace panda::ecmascript::kungfu
1109