diff --git a/compiler/intrinsics_type_resolving_ecmascript.cpp b/compiler/intrinsics_type_resolving_ecmascript.cpp index c3e6633fd5562a9785901107db9f2ce9fc9999bb..697f338c46d3efb426a562ada733cd25713a562c 100644 --- a/compiler/intrinsics_type_resolving_ecmascript.cpp +++ b/compiler/intrinsics_type_resolving_ecmascript.cpp @@ -17,545 +17,83 @@ #include "runtime/include/coretypes/tagged_value.h" namespace panda::compiler { -template -static Inst *InsertOverflowInst(Inst *input1, Inst *input2, IntrinsicInst *intrinsics) -{ - auto current_block = intrinsics->GetBasicBlock(); - auto pc = intrinsics->GetPc(); - // Split current block - current_block->SplitBlockAfterInstruction(intrinsics, true); - auto graph = current_block->GetGraph(); - - // Create and insert Add/SubOverflow instruction - Inst *inst = nullptr; - // NOLINTNEXTLINE(readability-magic-numbers,readability-braces-around-statements) - if constexpr (opcode == Opcode::AddOverflow) { - inst = graph->CreateInstAddOverflow(DataType::INT32, pc); - inst->CastToAddOverflow()->SetCc(ConditionCode::CC_NE); - inst->CastToAddOverflow()->SetOperandsType(DataType::INT32); - // NOLINTNEXTLINE(readability-magic-numbers,readability-misleading-indentation) - } else { - // NOLINTNEXTLINE(readability-magic-numbers,readability-braces-around-statements) - static_assert(opcode == Opcode::SubOverflow); - inst = graph->CreateInstSubOverflow(DataType::INT32, pc); - inst->CastToSubOverflow()->SetCc(ConditionCode::CC_NE); - inst->CastToSubOverflow()->SetOperandsType(DataType::INT32); - } - inst->SetInput(0, input1); - inst->SetInput(1, input2); - current_block->AppendInst(inst); - - // Create block for deoptimization - auto deopt_block = graph->CreateEmptyBlock(current_block); - current_block->AddSucc(deopt_block); - // Create and insert Deoptimize inst - auto deopt = graph->CreateInstDeoptimize(DataType::NO_TYPE, pc); - deopt->SetDeoptimizeType(DeoptimizeType::ANY_TYPE_CHECK); - deopt->SetInput(0, intrinsics->GetSaveState()); - deopt_block->AppendInst(deopt); - - auto end_block = graph->HasEndBlock() ? graph->GetEndBlock() : graph->CreateEndBlock(); - deopt_block->AddSucc(end_block); - - return inst; -} - -static Inst *InsertAnyCastInst(Inst *input, IntrinsicInst *intrinsics, AnyBaseType type) -{ - auto current_block = intrinsics->GetBasicBlock(); - auto graph = current_block->GetGraph(); - auto cast_to_value_inst = graph->CreateInstCastAnyTypeValue(AnyBaseTypeToDataType(type), intrinsics->GetPc()); - cast_to_value_inst->SetAnyType(type); - cast_to_value_inst->SetInput(0, input); - current_block->InsertBefore(cast_to_value_inst, intrinsics); - return cast_to_value_inst; -} - -bool TypesResolving::InlineIncDyn(IntrinsicInst *intrinsics, AnyBaseType type) -{ - ASSERT(type != AnyBaseType::UNDEFINED_TYPE); - if (type != AnyBaseType::ECMASCRIPT_INT_TYPE && type != AnyBaseType::ECMASCRIPT_DOUBLE_TYPE) { - return false; - } - auto pc = intrinsics->GetPc(); - auto current_block = intrinsics->GetBasicBlock(); - // Create and insert CastAnyTypeValueType inst - auto cast_to_value_inst = InsertAnyCastInst(intrinsics->GetInput(0).GetInst(), intrinsics, type); - - // Create and insert CastValueToAnyType inst - auto *cast_to_any_inst = GetGraph()->CreateInstCastValueToAnyType(DataType::ANY, pc); - cast_to_any_inst->SetAnyType(type); - current_block->InsertAfter(cast_to_any_inst, intrinsics); - Inst *add = nullptr; - if (type == AnyBaseType::ECMASCRIPT_INT_TYPE) { - auto constant = GetGraph()->FindOrCreateConstant(1); - add = InsertOverflowInst(cast_to_value_inst, constant, intrinsics); - } else { - ASSERT(type == AnyBaseType::ECMASCRIPT_DOUBLE_TYPE); - auto constant = GetGraph()->FindOrCreateConstant(1.0); - - // Create and insert Add instruction - add = GetGraph()->CreateInstAdd(DataType::FLOAT64, pc); - add->SetInput(0, cast_to_value_inst); - add->SetInput(1, constant); - current_block->InsertBefore(add, intrinsics); - } - cast_to_any_inst->SetInput(0, add); - intrinsics->ReplaceUsers(cast_to_any_inst); - intrinsics->SetInlined(false); - intrinsics->ClearFlag(compiler::inst_flags::NO_DCE); - return true; -} - -bool TypesResolving::InlineAddDyn(IntrinsicInst *intrinsics, AnyBaseType type1, AnyBaseType type2) -{ - ASSERT(type1 != AnyBaseType::UNDEFINED_TYPE); - ASSERT(type2 != AnyBaseType::UNDEFINED_TYPE); - if (type1 != AnyBaseType::ECMASCRIPT_INT_TYPE && type1 != AnyBaseType::ECMASCRIPT_DOUBLE_TYPE) { - return false; - } - if (type2 != AnyBaseType::ECMASCRIPT_INT_TYPE && type2 != AnyBaseType::ECMASCRIPT_DOUBLE_TYPE) { - return false; - } - auto pc = intrinsics->GetPc(); - auto current_block = intrinsics->GetBasicBlock(); - // Create and insert CastAnyTypeValueType inst - auto cast_to_value_inst1 = InsertAnyCastInst(intrinsics->GetInput(0).GetInst(), intrinsics, type1); - auto cast_to_value_inst2 = InsertAnyCastInst(intrinsics->GetInput(1).GetInst(), intrinsics, type2); - - // Create and insert CastValueToAnyType inst - auto *cast_to_any_inst = GetGraph()->CreateInstCastValueToAnyType(DataType::ANY, pc); - current_block->InsertAfter(cast_to_any_inst, intrinsics); - Inst *add = nullptr; - AnyBaseType type = AnyBaseType::ECMASCRIPT_INT_TYPE; - if (type1 == AnyBaseType::ECMASCRIPT_INT_TYPE && type2 == AnyBaseType::ECMASCRIPT_INT_TYPE) { - add = InsertOverflowInst(cast_to_value_inst1, cast_to_value_inst2, intrinsics); - } else { - Inst *input0 = cast_to_value_inst1; - Inst *input1 = cast_to_value_inst2; - if (type1 == AnyBaseType::ECMASCRIPT_INT_TYPE) { - auto cast = GetGraph()->CreateInstCast(DataType::FLOAT64, pc); - cast->SetInput(0, input0); - input0 = cast; - cast->SetOperandsType(DataType::INT32); - current_block->InsertBefore(cast, intrinsics); - } - if (type2 == AnyBaseType::ECMASCRIPT_INT_TYPE) { - auto cast = GetGraph()->CreateInstCast(DataType::FLOAT64, pc); - cast->SetInput(0, input1); - input1 = cast; - cast->SetOperandsType(DataType::INT32); - current_block->InsertBefore(cast, intrinsics); - } - // Create and insert Add instruction - add = GetGraph()->CreateInstAdd(DataType::FLOAT64, pc); - add->SetInput(0, input0); - add->SetInput(1, input1); - current_block->InsertBefore(add, intrinsics); - type = AnyBaseType::ECMASCRIPT_DOUBLE_TYPE; - } - cast_to_any_inst->SetAnyType(type); - cast_to_any_inst->SetInput(0, add); - intrinsics->ReplaceUsers(cast_to_any_inst); - intrinsics->SetInlined(false); - intrinsics->ClearFlag(compiler::inst_flags::NO_DCE); - return true; -} - -bool TypesResolving::InlineDecDyn(IntrinsicInst *intrinsics, AnyBaseType type) -{ - ASSERT(type != AnyBaseType::UNDEFINED_TYPE); - if (type != AnyBaseType::ECMASCRIPT_INT_TYPE && type != AnyBaseType::ECMASCRIPT_DOUBLE_TYPE) { - return false; - } - auto pc = intrinsics->GetPc(); - auto current_block = intrinsics->GetBasicBlock(); - // Create and insert CastAnyTypeValueType inst - auto cast_to_value_inst = InsertAnyCastInst(intrinsics->GetInput(0).GetInst(), intrinsics, type); - - // Create and insert CastValueToAnyType inst - auto *cast_to_any_inst = GetGraph()->CreateInstCastValueToAnyType(DataType::ANY, pc); - cast_to_any_inst->SetAnyType(type); - current_block->InsertAfter(cast_to_any_inst, intrinsics); - Inst *sub = nullptr; - if (type == AnyBaseType::ECMASCRIPT_INT_TYPE) { - auto constant = GetGraph()->FindOrCreateConstant(1); - sub = InsertOverflowInst(cast_to_value_inst, constant, intrinsics); - } else { - ASSERT(type == AnyBaseType::ECMASCRIPT_DOUBLE_TYPE); - auto constant = GetGraph()->FindOrCreateConstant(1.0); - - // Create and insert Sub instruction - sub = GetGraph()->CreateInstSub(DataType::FLOAT64, pc); - sub->SetInput(0, cast_to_value_inst); - sub->SetInput(1, constant); - current_block->InsertBefore(sub, intrinsics); - } - cast_to_any_inst->SetInput(0, sub); - intrinsics->ReplaceUsers(cast_to_any_inst); - intrinsics->SetInlined(false); - intrinsics->ClearFlag(compiler::inst_flags::NO_DCE); - return true; -} - -bool TypesResolving::InlineSubDyn(IntrinsicInst *intrinsics, AnyBaseType type1, AnyBaseType type2) -{ - ASSERT(type1 != AnyBaseType::UNDEFINED_TYPE); - ASSERT(type2 != AnyBaseType::UNDEFINED_TYPE); - if (type1 != AnyBaseType::ECMASCRIPT_INT_TYPE && type1 != AnyBaseType::ECMASCRIPT_DOUBLE_TYPE) { - return false; - } - if (type2 != AnyBaseType::ECMASCRIPT_INT_TYPE && type2 != AnyBaseType::ECMASCRIPT_DOUBLE_TYPE) { - return false; - } - auto pc = intrinsics->GetPc(); - auto current_block = intrinsics->GetBasicBlock(); - // Create and insert CastAnyTypeValueType inst - auto cast_to_value_inst1 = InsertAnyCastInst(intrinsics->GetInput(0).GetInst(), intrinsics, type1); - auto cast_to_value_inst2 = InsertAnyCastInst(intrinsics->GetInput(1).GetInst(), intrinsics, type2); - - // Create and insert CastValueToAnyType inst - auto *cast_to_any_inst = GetGraph()->CreateInstCastValueToAnyType(DataType::ANY, pc); - current_block->InsertAfter(cast_to_any_inst, intrinsics); - Inst *sub = nullptr; - AnyBaseType type = AnyBaseType::ECMASCRIPT_INT_TYPE; - if (type1 == AnyBaseType::ECMASCRIPT_INT_TYPE && type2 == AnyBaseType::ECMASCRIPT_INT_TYPE) { - sub = InsertOverflowInst(cast_to_value_inst1, cast_to_value_inst2, intrinsics); - } else { - Inst *input0 = cast_to_value_inst1; - Inst *input1 = cast_to_value_inst2; - if (type1 == AnyBaseType::ECMASCRIPT_INT_TYPE) { - auto cast = GetGraph()->CreateInstCast(DataType::FLOAT64, pc); - cast->SetInput(0, input0); - input0 = cast; - cast->SetOperandsType(DataType::INT32); - current_block->InsertBefore(cast, intrinsics); - } - if (type2 == AnyBaseType::ECMASCRIPT_INT_TYPE) { - auto cast = GetGraph()->CreateInstCast(DataType::FLOAT64, pc); - cast->SetInput(0, input1); - input1 = cast; - cast->SetOperandsType(DataType::INT32); - current_block->InsertBefore(cast, intrinsics); - } - // Create and insert Sub instruction - sub = GetGraph()->CreateInstSub(DataType::FLOAT64, pc); - sub->SetInput(0, input0); - sub->SetInput(1, input1); - current_block->InsertBefore(sub, intrinsics); - type = AnyBaseType::ECMASCRIPT_DOUBLE_TYPE; - } - cast_to_any_inst->SetAnyType(type); - cast_to_any_inst->SetInput(0, sub); - intrinsics->ReplaceUsers(cast_to_any_inst); - intrinsics->SetInlined(false); - intrinsics->ClearFlag(compiler::inst_flags::NO_DCE); - return true; -} - -bool TypesResolving::InlineMulDyn(IntrinsicInst *intrinsics, AnyBaseType type1, AnyBaseType type2) -{ - ASSERT(type1 != AnyBaseType::UNDEFINED_TYPE); - ASSERT(type2 != AnyBaseType::UNDEFINED_TYPE); - if (type1 != AnyBaseType::ECMASCRIPT_DOUBLE_TYPE || type2 != AnyBaseType::ECMASCRIPT_DOUBLE_TYPE) { - return false; - } - auto pc = intrinsics->GetPc(); - auto current_block = intrinsics->GetBasicBlock(); - // Create and insert CastAnyTypeValueType inst - auto cast_to_value_inst1 = InsertAnyCastInst(intrinsics->GetInput(0).GetInst(), intrinsics, type1); - auto cast_to_value_inst2 = InsertAnyCastInst(intrinsics->GetInput(1).GetInst(), intrinsics, type2); - - // Create and insert CastValueToAnyType inst - auto *cast_to_any_inst = GetGraph()->CreateInstCastValueToAnyType(DataType::ANY, pc); - current_block->InsertAfter(cast_to_any_inst, intrinsics); - // Create and insert Mul instruction - Inst *add = GetGraph()->CreateInstMul(DataType::FLOAT64, pc); - add->SetInput(0, cast_to_value_inst1); - add->SetInput(1, cast_to_value_inst2); - current_block->InsertBefore(add, intrinsics); - cast_to_any_inst->SetAnyType(AnyBaseType::ECMASCRIPT_DOUBLE_TYPE); - cast_to_any_inst->SetInput(0, add); - intrinsics->ReplaceUsers(cast_to_any_inst); - intrinsics->SetInlined(false); - intrinsics->ClearFlag(compiler::inst_flags::NO_DCE); - return true; -} - -bool TypesResolving::InlineAndDyn(IntrinsicInst *intrinsics, AnyBaseType type1, AnyBaseType type2) -{ - ASSERT(type1 != AnyBaseType::UNDEFINED_TYPE); - ASSERT(type2 != AnyBaseType::UNDEFINED_TYPE); - if (type1 != AnyBaseType::ECMASCRIPT_INT_TYPE || type2 != AnyBaseType::ECMASCRIPT_INT_TYPE) { - return false; - } - auto pc = intrinsics->GetPc(); - auto current_block = intrinsics->GetBasicBlock(); - // Create and insert CastAnyTypeValueType inst - auto cast_to_value_inst1 = InsertAnyCastInst(intrinsics->GetInput(0).GetInst(), intrinsics, type1); - auto cast_to_value_inst2 = InsertAnyCastInst(intrinsics->GetInput(1).GetInst(), intrinsics, type2); - - // Create and insert CastValueToAnyType inst - auto *cast_to_any_inst = GetGraph()->CreateInstCastValueToAnyType(DataType::ANY, pc); - current_block->InsertAfter(cast_to_any_inst, intrinsics); - auto and_inst = GetGraph()->CreateInstAnd(DataType::INT32, pc); - and_inst->SetInput(0, cast_to_value_inst1); - and_inst->SetInput(1, cast_to_value_inst2); - current_block->InsertBefore(and_inst, intrinsics); - - cast_to_any_inst->SetAnyType(AnyBaseType::ECMASCRIPT_INT_TYPE); - cast_to_any_inst->SetInput(0, and_inst); - intrinsics->ReplaceUsers(cast_to_any_inst); - intrinsics->SetInlined(false); - intrinsics->ClearFlag(compiler::inst_flags::NO_DCE); - return true; -} - -bool TypesResolving::InlineShlDyn(IntrinsicInst *intrinsics, AnyBaseType type1, AnyBaseType type2) -{ - ASSERT(type1 != AnyBaseType::UNDEFINED_TYPE); - ASSERT(type2 != AnyBaseType::UNDEFINED_TYPE); - if (type1 != AnyBaseType::ECMASCRIPT_INT_TYPE || type2 != AnyBaseType::ECMASCRIPT_INT_TYPE) { - return false; - } - auto pc = intrinsics->GetPc(); - auto current_block = intrinsics->GetBasicBlock(); - // Create and insert CastAnyTypeValueType inst - auto cast_to_value_inst1 = InsertAnyCastInst(intrinsics->GetInput(0).GetInst(), intrinsics, type1); - auto cast_to_value_inst2 = InsertAnyCastInst(intrinsics->GetInput(1).GetInst(), intrinsics, type2); - - // Create and insert CastValueToAnyType inst - auto *cast_to_any_inst = GetGraph()->CreateInstCastValueToAnyType(DataType::ANY, pc); - current_block->InsertAfter(cast_to_any_inst, intrinsics); - auto shl_inst = GetGraph()->CreateInstShl(DataType::INT32, pc); - shl_inst->SetInput(0, cast_to_value_inst1); - shl_inst->SetInput(1, cast_to_value_inst2); - current_block->InsertBefore(shl_inst, intrinsics); - - cast_to_any_inst->SetAnyType(AnyBaseType::ECMASCRIPT_INT_TYPE); - cast_to_any_inst->SetInput(0, shl_inst); - intrinsics->ReplaceUsers(cast_to_any_inst); - intrinsics->SetInlined(false); - intrinsics->ClearFlag(compiler::inst_flags::NO_DCE); - return true; -} - -bool TypesResolving::InlineShrDyn(IntrinsicInst *intrinsics, AnyBaseType type1, AnyBaseType type2) -{ - ASSERT(type1 != AnyBaseType::UNDEFINED_TYPE); - ASSERT(type2 != AnyBaseType::UNDEFINED_TYPE); - if (type1 != AnyBaseType::ECMASCRIPT_INT_TYPE || type2 != AnyBaseType::ECMASCRIPT_INT_TYPE) { - return false; - } - auto pc = intrinsics->GetPc(); - auto current_block = intrinsics->GetBasicBlock(); - // Create and insert CastAnyTypeValueType inst - auto cast_to_value_inst1 = InsertAnyCastInst(intrinsics->GetInput(0).GetInst(), intrinsics, type1); - auto cast_to_value_inst2 = InsertAnyCastInst(intrinsics->GetInput(1).GetInst(), intrinsics, type2); - - // Create and insert CastValueToAnyType inst - auto *cast_to_any_inst = GetGraph()->CreateInstCastValueToAnyType(DataType::ANY, pc); - current_block->InsertAfter(cast_to_any_inst, intrinsics); - auto shr_inst = GetGraph()->CreateInstShr(DataType::INT32, pc); - shr_inst->SetInput(0, cast_to_value_inst1); - shr_inst->SetInput(1, cast_to_value_inst2); - current_block->InsertBefore(shr_inst, intrinsics); - - cast_to_any_inst->SetAnyType(AnyBaseType::ECMASCRIPT_INT_TYPE); - cast_to_any_inst->SetInput(0, shr_inst); - intrinsics->ReplaceUsers(cast_to_any_inst); - intrinsics->SetInlined(false); - intrinsics->ClearFlag(compiler::inst_flags::NO_DCE); - return true; -} - -bool TypesResolving::InlineCompareDyn(IntrinsicInst *intrinsics, AnyBaseType type1, AnyBaseType type2, ConditionCode cc) -{ - ASSERT(type1 != AnyBaseType::UNDEFINED_TYPE); - ASSERT(type2 != AnyBaseType::UNDEFINED_TYPE); - if (type1 != AnyBaseType::ECMASCRIPT_INT_TYPE || type2 != AnyBaseType::ECMASCRIPT_INT_TYPE) { - return false; - } - auto pc = intrinsics->GetPc(); - auto current_block = intrinsics->GetBasicBlock(); - // Create and insert CastAnyTypeValueType inst - auto cast_to_value_inst1 = InsertAnyCastInst(intrinsics->GetInput(0).GetInst(), intrinsics, type1); - auto cast_to_value_inst2 = InsertAnyCastInst(intrinsics->GetInput(1).GetInst(), intrinsics, type2); - - // Create and insert CastValueToAnyType inst - auto *cast_to_any_inst = GetGraph()->CreateInstCastValueToAnyType(DataType::ANY, pc); - current_block->InsertAfter(cast_to_any_inst, intrinsics); - auto less_inst = GetGraph()->CreateInstCompare(DataType::BOOL, pc); - less_inst->SetInput(0, cast_to_value_inst1); - less_inst->SetInput(1, cast_to_value_inst2); - less_inst->SetCc(cc); - less_inst->SetOperandsType(DataType::INT32); - current_block->InsertBefore(less_inst, intrinsics); - - cast_to_any_inst->SetAnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE); - cast_to_any_inst->SetInput(0, less_inst); - intrinsics->ReplaceUsers(cast_to_any_inst); - intrinsics->SetInlined(false); - intrinsics->ClearFlag(compiler::inst_flags::NO_DCE); - return true; -} - -bool TypesResolving::InlineNotDyn(IntrinsicInst *intrinsics, AnyBaseType type) -{ - ASSERT(type != AnyBaseType::UNDEFINED_TYPE); - if (type != AnyBaseType::ECMASCRIPT_INT_TYPE) { - return false; - } - auto pc = intrinsics->GetPc(); - auto current_block = intrinsics->GetBasicBlock(); - // Create and insert CastAnyTypeValueType inst - auto cast_to_value_inst = InsertAnyCastInst(intrinsics->GetInput(0).GetInst(), intrinsics, type); - - // Create and insert CastValueToAnyType inst - auto *cast_to_any_inst = GetGraph()->CreateInstCastValueToAnyType(DataType::ANY, pc); - current_block->InsertAfter(cast_to_any_inst, intrinsics); - auto not_inst = GetGraph()->CreateInstNot(DataType::INT32, pc); - not_inst->SetInput(0, cast_to_value_inst); - current_block->InsertBefore(not_inst, intrinsics); - - cast_to_any_inst->SetAnyType(AnyBaseType::ECMASCRIPT_INT_TYPE); - cast_to_any_inst->SetInput(0, not_inst); - intrinsics->ReplaceUsers(cast_to_any_inst); - intrinsics->SetInlined(false); - intrinsics->ClearFlag(compiler::inst_flags::NO_DCE); - return true; -} - -bool TypesResolving::InlineNegDyn(IntrinsicInst *intrinsics, AnyBaseType type) +bool TypesResolving::InlineToNumberDyn(IntrinsicInst *intrinsic, AnyBaseType type) { ASSERT(type != AnyBaseType::UNDEFINED_TYPE); if (type != AnyBaseType::ECMASCRIPT_INT_TYPE && type != AnyBaseType::ECMASCRIPT_DOUBLE_TYPE) { return false; } - auto pc = intrinsics->GetPc(); - auto current_block = intrinsics->GetBasicBlock(); - // Create and insert CastAnyTypeValueType inst - auto cast_to_value_inst = InsertAnyCastInst(intrinsics->GetInput(0).GetInst(), intrinsics, type); - - Inst *input = cast_to_value_inst; - if (type == AnyBaseType::ECMASCRIPT_INT_TYPE) { - auto cast = GetGraph()->CreateInstCast(DataType::FLOAT64, pc); - cast->SetInput(0, input); - input = cast; - cast->SetOperandsType(DataType::INT32); - current_block->InsertBefore(cast, intrinsics); - } - - // Create and insert CastValueToAnyType inst - auto *cast_to_any_inst = GetGraph()->CreateInstCastValueToAnyType(DataType::ANY, pc); - current_block->InsertAfter(cast_to_any_inst, intrinsics); - auto not_inst = GetGraph()->CreateInstNeg(DataType::FLOAT64, pc); - not_inst->SetInput(0, input); - current_block->InsertBefore(not_inst, intrinsics); - - cast_to_any_inst->SetAnyType(AnyBaseType::ECMASCRIPT_DOUBLE_TYPE); - cast_to_any_inst->SetInput(0, not_inst); - intrinsics->ReplaceUsers(cast_to_any_inst); - intrinsics->SetInlined(false); - intrinsics->ClearFlag(compiler::inst_flags::NO_DCE); + intrinsic->ReplaceUsers(intrinsic->GetInput(0).GetInst()); + intrinsic->SetInlined(false); + intrinsic->ClearFlag(compiler::inst_flags::NO_DCE); return true; } -bool TypesResolving::InlineToBooleanDyn(IntrinsicInst *intrinsics, AnyBaseType type) +template +bool InlineLdConstant(IntrinsicInst *intrinsic, AnyBaseType any_type, T value) { - ASSERT(type != AnyBaseType::UNDEFINED_TYPE); - if (type != AnyBaseType::ECMASCRIPT_INT_TYPE) { - return false; - } - auto pc = intrinsics->GetPc(); - auto current_block = intrinsics->GetBasicBlock(); - // Create and insert CastAnyTypeValueType inst - auto cast_to_value_inst = InsertAnyCastInst(intrinsics->GetInput(0).GetInst(), intrinsics, type); + auto current_block = intrinsic->GetBasicBlock(); + auto graph = current_block->GetGraph(); + auto cnst = graph->FindOrCreateConstant(value); - // Create and insert CastValueToAnyType inst - auto *cast_to_any_inst = GetGraph()->CreateInstCastValueToAnyType(DataType::ANY, pc); - auto *const_inst = GetGraph()->FindOrCreateConstant(0); - current_block->InsertAfter(cast_to_any_inst, intrinsics); - auto less_inst = GetGraph()->CreateInstCompare(DataType::BOOL, pc); - less_inst->SetInput(0, cast_to_value_inst); - less_inst->SetInput(1, const_inst); - less_inst->SetCc(CC_NE); - less_inst->SetOperandsType(DataType::INT32); - current_block->InsertBefore(less_inst, intrinsics); + auto cast_to_any_inst = graph->CreateInstCastValueToAnyType(DataType::ANY, intrinsic->GetPc()); + current_block->InsertAfter(cast_to_any_inst, intrinsic); + cast_to_any_inst->SetAnyType(any_type); + cast_to_any_inst->SetInput(0, cnst); - cast_to_any_inst->SetAnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE); - cast_to_any_inst->SetInput(0, less_inst); - intrinsics->ReplaceUsers(cast_to_any_inst); - intrinsics->SetInlined(false); - intrinsics->ClearFlag(compiler::inst_flags::NO_DCE); + intrinsic->ReplaceUsers(cast_to_any_inst); + intrinsic->SetInlined(false); + current_block->RemoveInst(intrinsic); return true; } -bool TypesResolving::InlineToNumberDyn(IntrinsicInst *intrinsics, AnyBaseType type) +bool InlineLdConstant(IntrinsicInst *intrinsic, DataType::Any value) { - ASSERT(type != AnyBaseType::UNDEFINED_TYPE); - if (type != AnyBaseType::ECMASCRIPT_INT_TYPE && type != AnyBaseType::ECMASCRIPT_DOUBLE_TYPE) { - return false; - } - intrinsics->ReplaceUsers(intrinsics->GetInput(0).GetInst()); - intrinsics->SetInlined(false); - intrinsics->ClearFlag(compiler::inst_flags::NO_DCE); - return true; -} - -template -bool InlineLdConstant(IntrinsicInst *intrinsics, AnyBaseType any_type, T value) -{ - auto current_block = intrinsics->GetBasicBlock(); + auto current_block = intrinsic->GetBasicBlock(); auto graph = current_block->GetGraph(); auto cnst = graph->FindOrCreateConstant(value); - auto cast_to_any_inst = graph->CreateInstCastValueToAnyType(DataType::ANY, intrinsics->GetPc()); - current_block->InsertAfter(cast_to_any_inst, intrinsics); - cast_to_any_inst->SetAnyType(any_type); - cast_to_any_inst->SetInput(0, cnst); + intrinsic->ReplaceUsers(cnst); - intrinsics->ReplaceUsers(cast_to_any_inst); - intrinsics->SetInlined(false); - current_block->RemoveInst(intrinsics); + intrinsic->SetInlined(false); + current_block->RemoveInst(intrinsic); return true; } using TaggedValue = panda::coretypes::TaggedValue; -bool TypesResolving::InlineLdTrue(IntrinsicInst *intrinsics) +bool TypesResolving::InlineLdTrue(IntrinsicInst *intrinsic) { - return InlineLdConstant(intrinsics, AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE, 1U); + return InlineLdConstant(intrinsic, AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE, 1U); } -bool TypesResolving::InlineLdFalse(IntrinsicInst *intrinsics) +bool TypesResolving::InlineLdFalse(IntrinsicInst *intrinsic) { - return InlineLdConstant(intrinsics, AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE, 0U); + return InlineLdConstant(intrinsic, AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE, 0U); } -bool TypesResolving::InlineLdHole(IntrinsicInst *intrinsics) +bool TypesResolving::InlineLdHole(IntrinsicInst *intrinsic) { - return InlineLdConstant(intrinsics, AnyBaseType::ECMASCRIPT_HOLE_TYPE, DataType::Any(TaggedValue::VALUE_HOLE)); + return InlineLdConstant(intrinsic, DataType::Any(TaggedValue::VALUE_HOLE)); } -bool TypesResolving::InlineLdNull(IntrinsicInst *intrinsics) +bool TypesResolving::InlineLdNull(IntrinsicInst *intrinsic) { - return InlineLdConstant(intrinsics, AnyBaseType::ECMASCRIPT_NULL_TYPE, DataType::Any(TaggedValue::VALUE_NULL)); + return InlineLdConstant(intrinsic, DataType::Any(TaggedValue::VALUE_NULL)); } -bool TypesResolving::InlineLdUndefined(IntrinsicInst *intrinsics) +bool TypesResolving::InlineLdUndefined(IntrinsicInst *intrinsic) { - return InlineLdConstant(intrinsics, AnyBaseType::ECMASCRIPT_UNDEFINED_TYPE, - DataType::Any(TaggedValue::VALUE_UNDEFINED)); + return InlineLdConstant(intrinsic, DataType::Any(TaggedValue::VALUE_UNDEFINED)); } -bool TypesResolving::InlineLdInfinity(IntrinsicInst *intrinsics) +bool TypesResolving::InlineLdInfinity(IntrinsicInst *intrinsic) { - return InlineLdConstant(intrinsics, AnyBaseType::ECMASCRIPT_DOUBLE_TYPE, TaggedValue::VALUE_INFINITY); + return InlineLdConstant(intrinsic, AnyBaseType::ECMASCRIPT_DOUBLE_TYPE, TaggedValue::VALUE_INFINITY); } -bool TypesResolving::InlineLdNan(IntrinsicInst *intrinsics) +bool TypesResolving::InlineLdNan(IntrinsicInst *intrinsic) { - return InlineLdConstant(intrinsics, AnyBaseType::ECMASCRIPT_DOUBLE_TYPE, TaggedValue::VALUE_NAN); + return InlineLdConstant(intrinsic, AnyBaseType::ECMASCRIPT_DOUBLE_TYPE, TaggedValue::VALUE_NAN); } } // namespace panda::compiler diff --git a/compiler/intrinsics_type_resolving_ecmascript.inl.h b/compiler/intrinsics_type_resolving_ecmascript.inl.h index 12e0edc264da020a075eef61494f2e442cf4a94a..7a786080c436e037c3ac9fbf4569af7477350011 100644 --- a/compiler/intrinsics_type_resolving_ecmascript.inl.h +++ b/compiler/intrinsics_type_resolving_ecmascript.inl.h @@ -16,25 +16,13 @@ #ifndef PLUGINS_ECMASCRIPT_COMPILER_INTRINSICS_TYPE_RESOLVING_ECMASCRIPT_INL_H #define PLUGINS_ECMASCRIPT_COMPILER_INTRINSICS_TYPE_RESOLVING_ECMASCRIPT_INL_H -bool InlineIncDyn(IntrinsicInst *intrinsics, AnyBaseType type); -bool InlineAddDyn(IntrinsicInst *intrinsics, AnyBaseType type1, AnyBaseType type2); -bool InlineDecDyn(IntrinsicInst *intrinsics, AnyBaseType type); -bool InlineSubDyn(IntrinsicInst *intrinsics, AnyBaseType type1, AnyBaseType type2); -bool InlineAndDyn(IntrinsicInst *intrinsics, AnyBaseType type1, AnyBaseType type2); -bool InlineMulDyn(IntrinsicInst *intrinsics, AnyBaseType type1, AnyBaseType type2); -bool InlineCompareDyn(IntrinsicInst *intrinsics, AnyBaseType type1, AnyBaseType type2, ConditionCode cc); -bool InlineShlDyn(IntrinsicInst *intrinsics, AnyBaseType type1, AnyBaseType type2); -bool InlineShrDyn(IntrinsicInst *intrinsics, AnyBaseType type1, AnyBaseType type2); -bool InlineNotDyn(IntrinsicInst *intrinsics, AnyBaseType type); -bool InlineNegDyn(IntrinsicInst *intrinsics, AnyBaseType type); -bool InlineToBooleanDyn(IntrinsicInst *intrinsics, AnyBaseType type); -bool InlineToNumberDyn(IntrinsicInst *intrinsics, AnyBaseType type); -bool InlineLdTrue(IntrinsicInst *intrinsics); -bool InlineLdFalse(IntrinsicInst *intrinsics); -bool InlineLdHole(IntrinsicInst *intrinsics); -bool InlineLdNull(IntrinsicInst *intrinsics); -bool InlineLdUndefined(IntrinsicInst *intrinsics); -bool InlineLdInfinity(IntrinsicInst *intrinsics); -bool InlineLdNan(IntrinsicInst *intrinsics); +bool InlineToNumberDyn(IntrinsicInst *intrinsic, AnyBaseType type); +bool InlineLdTrue(IntrinsicInst *intrinsic); +bool InlineLdFalse(IntrinsicInst *intrinsic); +bool InlineLdHole(IntrinsicInst *intrinsic); +bool InlineLdNull(IntrinsicInst *intrinsic); +bool InlineLdUndefined(IntrinsicInst *intrinsic); +bool InlineLdInfinity(IntrinsicInst *intrinsic); +bool InlineLdNan(IntrinsicInst *intrinsic); #endif // PLUGINS_ECMASCRIPT_COMPILER_INTRINSICS_TYPE_RESOLVING_ECMASCRIPT_INL_H \ No newline at end of file diff --git a/tests/compiler/types_resolving_ecma_tests.cpp b/tests/compiler/types_resolving_ecma_tests.cpp index d4f9b225b4c78239c28e5789e8896f7c5a866ea4..2b1a94d63f414625ed08f4d1fd9bc8f177127578 100644 --- a/tests/compiler/types_resolving_ecma_tests.cpp +++ b/tests/compiler/types_resolving_ecma_tests.cpp @@ -37,6 +37,8 @@ public: template Graph *ConstructGraphWithConst(AnyBaseType any_type, T cnst); + Graph *ConstructGraphWithConst(DataType::Any cnst); + template void TestLdConsts(TestArray tests); }; @@ -57,6 +59,20 @@ Graph *TypeResolvingTest::ConstructGraphWithConst(AnyBaseType any_type, T cnst) return graph; } +Graph *TypeResolvingTest::ConstructGraphWithConst(DataType::Any cnst) +{ + auto graph = CreateGraphDynWithDefaultRuntime(); + GRAPH(graph) + { + CONSTANT(0, cnst); + BASIC_BLOCK(2, -1) + { + INST(4, Opcode::Return).any().Inputs(0); + } + } + return graph; +} + template void TypeResolvingTest::TestLdConsts(TestArray tests) { @@ -65,7 +81,12 @@ void TypeResolvingTest::TestLdConsts(TestArray tests) ASSERT_TRUE(graph->template RunPass()); ASSERT_TRUE(graph->template RunPass()); GraphChecker(graph).Check(); - auto graph_opt = ConstructGraphWithConst(any_type, cnst); + Graph *graph_opt = nullptr; + if constexpr (std::is_same_v) { + graph_opt = ConstructGraphWithConst(cnst); + } else { + graph_opt = ConstructGraphWithConst(any_type, cnst); + } ASSERT_TRUE(GraphComparator().Compare(graph, graph_opt)); } } diff --git a/tests/compiler/vn_test_ecma.cpp b/tests/compiler/vn_test_ecma.cpp index 684ab8d9aabaaccda5f749a3103430d5d7eb74e0..d6da4a7e7ec9910dedf186c8d28332881eda9bb0 100644 --- a/tests/compiler/vn_test_ecma.cpp +++ b/tests/compiler/vn_test_ecma.cpp @@ -207,4 +207,42 @@ TEST_F(VNTest, CastAnyTypeVNFalse) EXPECT_TRUE(GraphComparator().Compare(graph, graph_opt)); } +TEST_F(VNTest, CastValueToAnyType) +{ + auto graph = CreateGraphDynWithDefaultRuntime(); + GRAPH(graph) + { + CONSTANT(0, 0); + BASIC_BLOCK(2, -1) + { + INST(1, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(0); + INST(2, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(0); + INST(3, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(0); + INST(4, Opcode::SaveState).Inputs(0).SrcVregs({0}); + INST(5, Opcode::CallStatic).s32().InputsAutoType(1, 2, 3, 4); + INST(6, Opcode::Return).s32().Inputs(5); + } + } + + ASSERT_TRUE(graph->RunPass()); + ASSERT_TRUE(graph->RunPass()); + GraphChecker(graph).Check(); + + auto graph_opt = CreateGraphDynWithDefaultRuntime(); + GRAPH(graph_opt) + { + CONSTANT(0, 0); + BASIC_BLOCK(2, -1) + { + INST(1, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(0); + INST(2, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(0); + INST(4, Opcode::SaveState).Inputs(0).SrcVregs({0}); + INST(5, Opcode::CallStatic).s32().InputsAutoType(1, 2, 1, 4); + INST(6, Opcode::Return).s32().Inputs(5); + } + } + + EXPECT_TRUE(GraphComparator().Compare(graph, graph_opt)); +} + } // namespace panda::compiler