• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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