mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 16:13:49 +00:00
!2567 guard eliminating pass
Merge pull request !2567 from ChunyangWang/guard_eliminating_pass
This commit is contained in:
commit
ff92bd132a
@ -63,6 +63,7 @@ source_set("libark_jsoptimizer_set") {
|
||||
"frame_states.cpp",
|
||||
"gate.cpp",
|
||||
"gate_accessor.cpp",
|
||||
"guard_eliminating.cpp",
|
||||
"ic_stub_builder.cpp",
|
||||
"interpreter_stub.cpp",
|
||||
"llvm_codegen.cpp",
|
||||
|
@ -550,13 +550,13 @@ GateRef CircuitBuilder::BothAreString(GateRef x, GateRef y)
|
||||
}
|
||||
|
||||
template<TypedBinOp Op>
|
||||
GateRef CircuitBuilder::TypedBinaryOp(GateRef x, GateRef y, GateType xType, GateType yType)
|
||||
GateRef CircuitBuilder::TypedBinaryOp(GateRef x, GateRef y, GateType xType, GateType yType, GateType gateType)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto numberBinaryOp = TypedBinaryOperator(MachineType::I64, Op, xType, yType,
|
||||
{currentControl, currentDepend, x, y});
|
||||
{currentControl, currentDepend, x, y}, gateType);
|
||||
currentLabel->SetControl(numberBinaryOp);
|
||||
currentLabel->SetDepend(numberBinaryOp);
|
||||
return numberBinaryOp;
|
||||
@ -571,7 +571,7 @@ GateRef CircuitBuilder::NumberBinaryOp(GateRef x, GateRef y)
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto numberBinaryOp = TypedBinaryOperator(MachineType::I64, Op,
|
||||
GateType::NumberType(), GateType::NumberType(),
|
||||
{currentControl, currentDepend, x, y});
|
||||
{currentControl, currentDepend, x, y}, GateType::AnyType());
|
||||
currentLabel->SetControl(numberBinaryOp);
|
||||
currentLabel->SetDepend(numberBinaryOp);
|
||||
return numberBinaryOp;
|
||||
|
@ -154,7 +154,7 @@ GateRef CircuitBuilder::TypeCheck(GateType type, GateRef gate)
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::TypedBinaryOperator(MachineType type, TypedBinOp binOp, GateType typeLeft, GateType typeRight,
|
||||
std::vector<GateRef> inList)
|
||||
std::vector<GateRef> inList, GateType gateType)
|
||||
{
|
||||
// get BinaryOpCode from a constant gate
|
||||
auto bin = Int8(static_cast<int8_t>(binOp));
|
||||
@ -162,7 +162,7 @@ GateRef CircuitBuilder::TypedBinaryOperator(MachineType type, TypedBinOp binOp,
|
||||
// merge two expected types of valueIns
|
||||
uint64_t operandTypes = (static_cast<uint64_t>(typeLeft.Value()) << OPRAND_TYPE_BITS) |
|
||||
static_cast<uint64_t>(typeRight.Value());
|
||||
return GetCircuit()->NewGate(OpCode(OpCode::TYPED_BINARY_OP), type, operandTypes, inList, GateType::AnyType());
|
||||
return GetCircuit()->NewGate(OpCode(OpCode::TYPED_BINARY_OP), type, operandTypes, inList, gateType);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::TypeConvert(MachineType type, GateType typeFrom, GateType typeTo,
|
||||
|
@ -204,7 +204,7 @@ public:
|
||||
// low level interface
|
||||
GateRef TypeCheck(GateType type, GateRef gate);
|
||||
GateRef TypedBinaryOperator(MachineType type, TypedBinOp binOp, GateType typeLeft, GateType typeRight,
|
||||
std::vector<GateRef> inList);
|
||||
std::vector<GateRef> inList, GateType gateType);
|
||||
GateRef TypeConvert(MachineType type, GateType typeFrom, GateType typeTo, const std::vector<GateRef>& inList);
|
||||
GateRef TypedUnaryOperator(MachineType type, TypedUnaryOp unaryOp, GateType typleVal,
|
||||
const std::vector<GateRef>& inList);
|
||||
@ -376,7 +376,7 @@ public:
|
||||
|
||||
// middle ir: operations with any type
|
||||
template<TypedBinOp Op>
|
||||
inline GateRef TypedBinaryOp(GateRef x, GateRef y, GateType xType, GateType yType);
|
||||
inline GateRef TypedBinaryOp(GateRef x, GateRef y, GateType xType, GateType yType, GateType gateType);
|
||||
|
||||
// middle ir: Number operations
|
||||
template<TypedBinOp Op>
|
||||
|
@ -1459,4 +1459,9 @@ bool OpCode::IsConstant() const
|
||||
{
|
||||
return (op_ == OpCode::CONSTANT);
|
||||
}
|
||||
|
||||
bool OpCode::IsTypedOperator() const
|
||||
{
|
||||
return (op_ == OpCode::TYPED_BINARY_OP) || (op_ == OpCode::TYPE_CONVERT) || (op_ == OpCode::TYPED_UNARY_OP);
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -241,6 +241,7 @@ public:
|
||||
[[nodiscard]] bool IsLoopHead() const;
|
||||
[[nodiscard]] bool IsNop() const;
|
||||
[[nodiscard]] bool IsConstant() const;
|
||||
[[nodiscard]] bool IsTypedOperator() const;
|
||||
~OpCode() = default;
|
||||
|
||||
private:
|
||||
|
@ -221,6 +221,11 @@ bool GateAccessor::IsConstant(GateRef gate) const
|
||||
return GetOpCode(gate).IsConstant();
|
||||
}
|
||||
|
||||
bool GateAccessor::IsTypedOperator(GateRef gate) const
|
||||
{
|
||||
return GetOpCode(gate).IsTypedOperator();
|
||||
}
|
||||
|
||||
bool GateAccessor::IsSchedulable(GateRef gate) const
|
||||
{
|
||||
return GetOpCode(gate).IsSchedulable();
|
||||
@ -434,4 +439,16 @@ bool GateAccessor::IsValueIn(GateRef gate, size_t index) const
|
||||
size_t valueEndIndex = valueStartIndex + GetInValueCount(gate);
|
||||
return (index >= valueStartIndex && index < valueEndIndex);
|
||||
}
|
||||
|
||||
void GateAccessor::DeleteGuardAndFrameState(GateRef gate)
|
||||
{
|
||||
GateRef guard = GetDep(gate);
|
||||
if (GetOpCode(guard) == OpCode::GUARD) {
|
||||
GateRef dep = GetDep(guard);
|
||||
ReplaceDependIn(gate, dep);
|
||||
GateRef frameState = GetValueIn(guard, 1);
|
||||
DeleteGate(frameState);
|
||||
DeleteGate(guard);
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -347,6 +347,7 @@ public:
|
||||
bool IsLoopBack(GateRef gate) const;
|
||||
bool IsState(GateRef gate) const;
|
||||
bool IsConstant(GateRef gate) const;
|
||||
bool IsTypedOperator(GateRef gate) const;
|
||||
bool IsSchedulable(GateRef gate) const;
|
||||
MarkCode GetMark(GateRef gate) const;
|
||||
void SetMark(GateRef gate, MarkCode mark);
|
||||
@ -361,6 +362,7 @@ public:
|
||||
bool IsExceptionState(const UseIterator &useIt) const;
|
||||
bool IsDependIn(GateRef gate, size_t index) const;
|
||||
bool IsValueIn(GateRef gate, size_t index) const;
|
||||
void DeleteGuardAndFrameState(GateRef gate);
|
||||
|
||||
private:
|
||||
ConstUseIterator ConstUseBegin(GateRef gate) const
|
||||
|
101
ecmascript/compiler/guard_eliminating.cpp
Normal file
101
ecmascript/compiler/guard_eliminating.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stack>
|
||||
|
||||
#include "ecmascript/compiler/circuit_optimizer.h"
|
||||
#include "ecmascript/compiler/guard_eliminating.h"
|
||||
#include "ecmascript/compiler/scheduler.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
bool GuardEliminating::HasGuard(GateRef gate) const
|
||||
{
|
||||
if (acc_.IsTypedOperator(gate)) {
|
||||
auto guard = acc_.GetDep(gate);
|
||||
auto op = acc_.GetOpCode(guard);
|
||||
return op == OpCode::GUARD;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GuardEliminating::Run()
|
||||
{
|
||||
// eliminate duplicate typecheck
|
||||
GlobalValueNumbering(circuit_).Run();
|
||||
|
||||
// calculate dominator tree
|
||||
std::vector<GateRef> bbGatesList;
|
||||
std::unordered_map<GateRef, size_t> bbGatesAddrToIdx;
|
||||
std::vector<size_t> immDom;
|
||||
std::tie(bbGatesList, bbGatesAddrToIdx, immDom) = Scheduler::CalculateDominatorTree(circuit_);
|
||||
std::vector<std::vector<size_t>> domTree(immDom.size(), std::vector<size_t>(0));
|
||||
for (size_t idx = 1; idx < immDom.size(); ++idx) {
|
||||
domTree[immDom[idx]].emplace_back(idx);
|
||||
}
|
||||
|
||||
// dfs the dominator tree to eliminate guard
|
||||
// which is domined by another guard with same condition
|
||||
std::set<GateRef> conditionSet;
|
||||
struct DFSState {
|
||||
size_t curbb;
|
||||
size_t idx;
|
||||
};
|
||||
std::stack<DFSState> dfsStack;
|
||||
auto startGate = Circuit::GetCircuitRoot(OpCode(OpCode::STATE_ENTRY));
|
||||
DFSState startState = { bbGatesAddrToIdx[startGate], 0 };
|
||||
dfsStack.push(startState);
|
||||
while (!dfsStack.empty()) {
|
||||
auto &curState = dfsStack.top();
|
||||
auto &curbb = curState.curbb;
|
||||
auto &idx = curState.idx;
|
||||
if (idx == domTree[curbb].size()) {
|
||||
auto curGate = bbGatesList[curbb];
|
||||
if (HasGuard(curGate)) {
|
||||
auto guard = acc_.GetDep(curGate);
|
||||
auto condition = acc_.GetValueIn(guard, 0);
|
||||
conditionSet.erase(condition);
|
||||
}
|
||||
dfsStack.pop();
|
||||
continue;
|
||||
}
|
||||
auto succbb = domTree[curbb][idx];
|
||||
auto succGate = bbGatesList[succbb];
|
||||
if (HasGuard(succGate)) {
|
||||
auto guard = acc_.GetDep(succGate);
|
||||
auto condition = acc_.GetValueIn(guard, 0);
|
||||
if (conditionSet.count(condition) > 0) {
|
||||
acc_.DeleteGuardAndFrameState(succGate);
|
||||
} else {
|
||||
conditionSet.insert(condition);
|
||||
}
|
||||
}
|
||||
DFSState newState = { succbb, 0 };
|
||||
dfsStack.push(newState);
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (IsLogEnabled()) {
|
||||
LOG_COMPILER(INFO) << "";
|
||||
LOG_COMPILER(INFO) << "\033[34m"
|
||||
<< "===================="
|
||||
<< " After guard eliminating "
|
||||
<< "[" << GetMethodName() << "]"
|
||||
<< "===================="
|
||||
<< "\033[0m";
|
||||
circuit_->PrintAllGates(*bcBuilder_);
|
||||
LOG_COMPILER(INFO) << "\033[34m" << "========================= End ==========================" << "\033[0m";
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
50
ecmascript/compiler/guard_eliminating.h
Normal file
50
ecmascript/compiler/guard_eliminating.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_COMPILER_GUARD_ELIMINATING_H
|
||||
#define ECMASCRIPT_COMPILER_GUARD_ELIMINATING_H
|
||||
|
||||
#include "ecmascript/compiler/gate_accessor.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class GuardEliminating {
|
||||
public:
|
||||
GuardEliminating(BytecodeCircuitBuilder *bcBuilder, Circuit *circuit, bool enableLog, const std::string& name)
|
||||
: bcBuilder_(bcBuilder), circuit_(circuit), acc_(circuit), enableLog_(enableLog), methodName_(name) {}
|
||||
|
||||
~GuardEliminating() = default;
|
||||
|
||||
void Run();
|
||||
|
||||
private:
|
||||
bool IsLogEnabled() const
|
||||
{
|
||||
return enableLog_;
|
||||
}
|
||||
|
||||
const std::string& GetMethodName() const
|
||||
{
|
||||
return methodName_;
|
||||
}
|
||||
|
||||
bool HasGuard(GateRef gate) const;
|
||||
BytecodeCircuitBuilder *bcBuilder_ {nullptr};
|
||||
Circuit *circuit_ {nullptr};
|
||||
GateAccessor acc_;
|
||||
bool enableLog_ {false};
|
||||
std::string methodName_;
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_GUARD_ELIMINATING_H
|
@ -19,6 +19,7 @@
|
||||
#include "ecmascript/compiler/async_function_lowering.h"
|
||||
#include "ecmascript/compiler/bytecode_circuit_builder.h"
|
||||
#include "ecmascript/compiler/common_stubs.h"
|
||||
#include "ecmascript/compiler/guard_eliminating.h"
|
||||
#include "ecmascript/compiler/llvm_codegen.h"
|
||||
#include "ecmascript/compiler/scheduler.h"
|
||||
#include "ecmascript/compiler/slowpath_lowering.h"
|
||||
@ -156,6 +157,16 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class GuardEliminatingPass {
|
||||
public:
|
||||
bool Run(PassData* data, BytecodeCircuitBuilder *builder)
|
||||
{
|
||||
bool enableLog = data->GetEnableMethodLog() && data->GetLog()->OutputCIR();
|
||||
GuardEliminating(builder, data->GetCircuit(), enableLog, data->GetMethodName()).Run();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class SchedulingPass {
|
||||
public:
|
||||
bool Run(PassData* data)
|
||||
|
@ -77,6 +77,7 @@ bool PassManager::Compile(const std::string &fileName, AOTFileGenerator &generat
|
||||
pipeline.RunPass<AsyncFunctionLoweringPass>(&builder, &cmpCfg);
|
||||
if (EnableTypeLowering()) {
|
||||
pipeline.RunPass<TSTypeLoweringPass>(&builder, &cmpCfg, tsManager);
|
||||
pipeline.RunPass<GuardEliminatingPass>(&builder);
|
||||
pipeline.RunPass<TypeLoweringPass>(&builder, &cmpCfg, tsManager);
|
||||
}
|
||||
pipeline.RunPass<SlowPathLoweringPass>(&builder, &cmpCfg, tsManager);
|
||||
|
@ -67,7 +67,7 @@ HWTEST_F_L0(LoweringRelateGateTests, TypedBinaryOperatorAddFramework)
|
||||
auto arg1 = builder.Arguments(1);
|
||||
auto nadd = builder.TypedBinaryOperator(MachineType::I64, TypedBinOp::TYPED_ADD,
|
||||
GateType::NumberType(), GateType::NumberType(),
|
||||
{entry, depend, arg0, arg1});
|
||||
{entry, depend, arg0, arg1}, GateType::NumberType());
|
||||
builder.Return(nadd, nadd, nadd);
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
CompilationConfig config("x86_64-unknown-linux-gnu", false);
|
||||
@ -87,7 +87,7 @@ HWTEST_F_L0(LoweringRelateGateTests, TypedBinaryOperatorLessFramework)
|
||||
auto arg1 = builder.Arguments(1);
|
||||
auto nless = builder.TypedBinaryOperator(MachineType::I64, TypedBinOp::TYPED_LESS,
|
||||
GateType::NumberType(), GateType::NumberType(),
|
||||
{entry, depend, arg0, arg1});
|
||||
{entry, depend, arg0, arg1}, GateType::BooleanType());
|
||||
builder.Return(nless, nless, nless);
|
||||
EXPECT_TRUE(Verifier::Run(&circuit));
|
||||
CompilationConfig config("x86_64-unknown-linux-gnu", false);
|
||||
|
@ -41,6 +41,29 @@ void TSTypeLowering::RunTSTypeLowering()
|
||||
}
|
||||
}
|
||||
|
||||
bool TSTypeLowering::IsTrustedType(GateRef gate) const
|
||||
{
|
||||
if (acc_.IsConstant(gate) || acc_.IsTypedOperator(gate)){
|
||||
return true;
|
||||
}
|
||||
auto op = acc_.GetOpCode(gate);
|
||||
if (op == OpCode::JS_BYTECODE) {
|
||||
auto pc = bcBuilder_->GetJSBytecode(gate);
|
||||
EcmaOpcode bc = bcBuilder_->PcToOpcode(pc);
|
||||
switch (bc) {
|
||||
case EcmaOpcode::ADD2_IMM8_V8:
|
||||
case EcmaOpcode::SUB2_IMM8_V8:
|
||||
case EcmaOpcode::MUL2_IMM8_V8:
|
||||
case EcmaOpcode::INC_IMM8:
|
||||
case EcmaOpcode::LESSEQ_IMM8_V8:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TSTypeLowering::Lower(GateRef gate)
|
||||
{
|
||||
auto pc = bcBuilder_->GetJSBytecode(gate);
|
||||
@ -129,18 +152,6 @@ void TSTypeLowering::DeleteGates(std::vector<GateRef> &unusedGate)
|
||||
}
|
||||
}
|
||||
|
||||
void TSTypeLowering::DeleteGuardAndFrameState(GateRef gate)
|
||||
{
|
||||
GateRef guard = acc_.GetDep(gate);
|
||||
if (acc_.GetOpCode(guard) == OpCode::GUARD) {
|
||||
GateRef dep = acc_.GetDep(guard);
|
||||
acc_.ReplaceDependIn(gate, dep);
|
||||
GateRef frameState = acc_.GetValueIn(guard, 1);
|
||||
acc_.DeleteGate(frameState);
|
||||
acc_.DeleteGate(guard);
|
||||
}
|
||||
}
|
||||
|
||||
void TSTypeLowering::ReplaceHIRGate(GateRef hir, GateRef outir, GateRef state, GateRef depend,
|
||||
std::vector<GateRef> &unusedGate)
|
||||
{
|
||||
@ -187,7 +198,7 @@ void TSTypeLowering::LowerTypedAdd(GateRef gate)
|
||||
SpeculateNumberCalculate<TypedBinOp::TYPED_ADD>(gate);
|
||||
return;
|
||||
} else {
|
||||
DeleteGuardAndFrameState(gate);
|
||||
acc_.DeleteGuardAndFrameState(gate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,7 +212,7 @@ void TSTypeLowering::LowerTypedSub(GateRef gate)
|
||||
SpeculateNumberCalculate<TypedBinOp::TYPED_SUB>(gate);
|
||||
return;
|
||||
} else {
|
||||
DeleteGuardAndFrameState(gate);
|
||||
acc_.DeleteGuardAndFrameState(gate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,7 +226,7 @@ void TSTypeLowering::LowerTypedMul(GateRef gate)
|
||||
SpeculateNumberCalculate<TypedBinOp::TYPED_MUL>(gate);
|
||||
return;
|
||||
} else {
|
||||
DeleteGuardAndFrameState(gate);
|
||||
acc_.DeleteGuardAndFrameState(gate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -229,7 +240,7 @@ void TSTypeLowering::LowerTypedMod(GateRef gate)
|
||||
SpeculateNumberCalculate<TypedBinOp::TYPED_MOD>(gate);
|
||||
return;
|
||||
} else {
|
||||
DeleteGuardAndFrameState(gate);
|
||||
acc_.DeleteGuardAndFrameState(gate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -243,7 +254,7 @@ void TSTypeLowering::LowerTypedLess(GateRef gate)
|
||||
SpeculateNumberCompare<TypedBinOp::TYPED_LESS>(gate);
|
||||
return;
|
||||
} else {
|
||||
DeleteGuardAndFrameState(gate);
|
||||
acc_.DeleteGuardAndFrameState(gate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,7 +268,7 @@ void TSTypeLowering::LowerTypedLessEq(GateRef gate)
|
||||
SpeculateNumberCompare<TypedBinOp::TYPED_LESSEQ>(gate);
|
||||
return;
|
||||
} else {
|
||||
DeleteGuardAndFrameState(gate);
|
||||
acc_.DeleteGuardAndFrameState(gate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -271,7 +282,7 @@ void TSTypeLowering::LowerTypedGreater(GateRef gate)
|
||||
SpeculateNumberCompare<TypedBinOp::TYPED_GREATER>(gate);
|
||||
return;
|
||||
} else {
|
||||
DeleteGuardAndFrameState(gate);
|
||||
acc_.DeleteGuardAndFrameState(gate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -285,7 +296,7 @@ void TSTypeLowering::LowerTypedGreaterEq(GateRef gate)
|
||||
SpeculateNumberCompare<TypedBinOp::TYPED_GREATEREQ>(gate);
|
||||
return;
|
||||
} else {
|
||||
DeleteGuardAndFrameState(gate);
|
||||
acc_.DeleteGuardAndFrameState(gate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -299,7 +310,7 @@ void TSTypeLowering::LowerTypedDiv(GateRef gate)
|
||||
SpeculateNumberCalculate<TypedBinOp::TYPED_DIV>(gate);
|
||||
return;
|
||||
} else {
|
||||
DeleteGuardAndFrameState(gate);
|
||||
acc_.DeleteGuardAndFrameState(gate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -313,7 +324,7 @@ void TSTypeLowering::LowerTypedEq(GateRef gate)
|
||||
SpeculateNumberCompare<TypedBinOp::TYPED_EQ>(gate);
|
||||
return;
|
||||
} else {
|
||||
DeleteGuardAndFrameState(gate);
|
||||
acc_.DeleteGuardAndFrameState(gate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -327,7 +338,7 @@ void TSTypeLowering::LowerTypedNotEq(GateRef gate)
|
||||
SpeculateNumberCompare<TypedBinOp::TYPED_NOTEQ>(gate);
|
||||
return;
|
||||
} else {
|
||||
DeleteGuardAndFrameState(gate);
|
||||
acc_.DeleteGuardAndFrameState(gate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -338,24 +349,28 @@ void TSTypeLowering::SpeculateNumberCalculate(GateRef gate)
|
||||
GateRef right = acc_.GetValueIn(gate, 1);
|
||||
GateType leftType = acc_.GetGateType(left);
|
||||
GateType rightType = acc_.GetGateType(right);
|
||||
GateType gateType = acc_.GetGateType(gate);
|
||||
GateRef check = Circuit::NullGate();
|
||||
if (acc_.IsConstant(left) && acc_.IsConstant(right)) {
|
||||
check = builder_.Boolean(true);
|
||||
} else if (acc_.IsConstant(left)) {
|
||||
if (IsTrustedType(left) && IsTrustedType(right)) {
|
||||
acc_.DeleteGuardAndFrameState(gate);
|
||||
} else if (IsTrustedType(left)) {
|
||||
check = builder_.TypeCheck(rightType, right);
|
||||
} else if (acc_.IsConstant(right)) {
|
||||
} else if (IsTrustedType(right)) {
|
||||
check = builder_.TypeCheck(leftType, left);
|
||||
} else {
|
||||
check = builder_.BoolAnd(builder_.TypeCheck(leftType, left), builder_.TypeCheck(rightType, right));
|
||||
}
|
||||
check = builder_.False();
|
||||
|
||||
// guard maybe not a GUARD
|
||||
GateRef guard = acc_.GetDep(gate);
|
||||
ASSERT(acc_.GetOpCode(guard) == OpCode::GUARD);
|
||||
acc_.ReplaceIn(guard, 1, check);
|
||||
if (check != Circuit::NullGate()) {
|
||||
acc_.ReplaceIn(guard, 1, check);
|
||||
}
|
||||
|
||||
// Replace the old NumberBinaryOp<Op> with TypedBinaryOp<Op>
|
||||
GateRef result = builder_.TypedBinaryOp<Op>(left, right, leftType, rightType);
|
||||
GateRef result = builder_.TypedBinaryOp<Op>(left, right, leftType, rightType, gateType);
|
||||
|
||||
acc_.SetDep(result, guard);
|
||||
std::vector<GateRef> removedGate{gate};
|
||||
ReplaceHIRGate(gate, result, builder_.GetState(), builder_.GetDepend(), removedGate);
|
||||
|
@ -46,7 +46,6 @@ private:
|
||||
|
||||
void Lower(GateRef gate);
|
||||
void DeleteGates(std::vector<GateRef> &unusedGate);
|
||||
void DeleteGuardAndFrameState(GateRef gate);
|
||||
void ReplaceHIRGate(GateRef hir, GateRef outir, GateRef state, GateRef depend,
|
||||
std::vector<GateRef> &unuseGate);
|
||||
void LowerTypedAdd(GateRef gate);
|
||||
@ -63,6 +62,9 @@ private:
|
||||
void LowerTypeToNumeric(GateRef gate);
|
||||
void LowerPrimitiveTypeToNumber(GateRef gate);
|
||||
|
||||
// TypeTrusted means the type of gate is already typecheck-passed, or the gate is constant and no need to check.
|
||||
bool IsTrustedType(GateRef gate) const;
|
||||
|
||||
template<TypedBinOp Op>
|
||||
void SpeculateNumberCalculate(GateRef gate);
|
||||
template<TypedBinOp Op>
|
||||
|
Loading…
Reference in New Issue
Block a user