Fix the bug that the Phi node is not generated

If the loop head is the first bb block, the variables used in the head cannot correctly generate Phi node

Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I6Y4JU
Signed-off-by: weng-xi <wengxi1@huawei.com>
Change-Id: I57927992e19ef9c53c598197609a17ba69b6f3ff
This commit is contained in:
weng-xi 2023-04-23 17:21:01 +08:00
parent 787e618f01
commit 3e37a79f72
8 changed files with 109 additions and 11 deletions

View File

@ -174,18 +174,35 @@ void BytecodeCircuitBuilder::CollectTryCatchBlockInfo(ExceptionInfo &byteCodeExc
});
}
void BytecodeCircuitBuilder::BuildEntryBlock()
{
BytecodeRegion &entryBlock = graph_[0];
BytecodeRegion &nextBlock = graph_[1];
entryBlock.succs.emplace_back(&nextBlock);
nextBlock.preds.emplace_back(&entryBlock);
entryBlock.bytecodeIterator_.Reset(this, INVALID_INDEX, INVALID_INDEX);
}
void BytecodeCircuitBuilder::BuildRegions(const ExceptionInfo &byteCodeException)
{
auto &items = regionsInfo_.GetBlockItems();
auto blockSize = items.size();
graph_.resize(blockSize);
// 1 : entry block. if the loop head is in the first bb block, the variables used in the head cannot correctly
// generate Phi nodes through the dominator-tree algorithm, resulting in an infinite loop. Therefore, an empty
// BB block is generated as an entry block
graph_.resize(blockSize + 1);
// build entry block
BuildEntryBlock();
// build basic block
size_t blockId = 0;
size_t blockId = 1;
for (const auto &item : items) {
auto &curBlock = GetBasicBlockById(blockId);
curBlock.id = blockId;
curBlock.start = item.GetStartBcIndex();
if (blockId != 0) {
if (blockId != 1) {
auto &prevBlock = graph_[blockId - 1];
prevBlock.end = curBlock.start - 1;
prevBlock.bytecodeIterator_.Reset(this, prevBlock.start, prevBlock.end);
@ -1106,6 +1123,12 @@ void BytecodeCircuitBuilder::BuildSubCircuit()
auto dependCur = bb.dependCurrent;
ASSERT(stateCur != Circuit::NullGate());
ASSERT(dependCur != Circuit::NullGate());
if (IsEntryBlock(bb.id)) {
auto &bbNext = graph_[bb.id + 1];
SetBlockPred(bb, bbNext, stateCur, dependCur);
bbNext.expandedPreds.push_back({bb.id, bb.end, false});
continue;
}
if (!bb.trys.empty()) {
dependCur = circuit_->NewGate(circuit_->GetException(),
MachineType::I64, {stateCur, dependCur}, GateType::AnyType());
@ -1449,8 +1472,12 @@ void BytecodeCircuitBuilder::PrintGraph(const char* title)
log += std::to_string(bb.preds[k]->id) + ", ";
}
LOG_COMPILER(INFO) << log;
LOG_COMPILER(INFO) << "\tBytecodePC: [" << std::to_string(bb.start) << ", "
<< std::to_string(bb.end) << ")";
if (IsEntryBlock(bb.id)) {
LOG_COMPILER(INFO) << "\tBytecodePC: Empty";
} else {
LOG_COMPILER(INFO) << "\tBytecodePC: [" << std::to_string(bb.start) << ", "
<< std::to_string(bb.end) << ")";
}
std::string log1("\tSucces: ");
for (size_t j = 0; j < bb.succs.size(); j++) {
@ -1501,6 +1528,10 @@ void BytecodeCircuitBuilder::PrintBytecodeInfo(BytecodeRegion& bb)
if (bb.isDead) {
return;
}
if (IsEntryBlock(bb.id)) {
LOG_COMPILER(INFO) << "\tBytecode[] = Empty";
return;
}
LOG_COMPILER(INFO) << "\tBytecode[] = ";
EnumerateBlock(bb, [&](const BytecodeInfo &bytecodeInfo) -> bool {
auto &iterator = bb.GetBytecodeIterator();

View File

@ -123,10 +123,10 @@ public:
const auto &it = std::upper_bound(blockItems_.begin(),
blockItems_.end(), bcIndex, findFunc);
if (it == blockItems_.end()) {
return blockItems_.size() - 1; // 1: last bb
return blockItems_.size();
}
// blockItems_[0]'s value is 0, bcIndex must be: bcIndex > blockItems_.begin()
return std::distance(blockItems_.begin(), it) - 1; // 1: -1 for bbIndx
return std::distance(blockItems_.begin(), it);
}
const std::vector<BytecodeSplitItem> &GetSplitItems() const
@ -334,6 +334,10 @@ public:
template <class Callback>
void EnumerateBlock(BytecodeRegion &bb, const Callback &cb)
{
// Entry block is a empry block
if (IsEntryBlock(bb.id)) {
return;
}
auto &iterator = bb.GetBytecodeIterator();
for (iterator.GotoStart(); !iterator.Done(); ++iterator) {
auto &bytecodeInfo = iterator.GetBytecodeInfo();
@ -430,6 +434,7 @@ public:
private:
void CollectTryCatchBlockInfo(ExceptionInfo &Exception);
void BuildCatchBlocks(const ExceptionInfo &Exception);
void BuildEntryBlock();
void BuildRegions(const ExceptionInfo &Exception);
void ComputeDominatorTree();
void BuildImmediateDominator(const std::vector<size_t> &immDom);
@ -477,9 +482,14 @@ private:
return bbId == 0;
}
inline bool IsFirstBasicBlock(const size_t bbId) const
{
return bbId == 1;
}
inline bool IsFirstBCEnvIn(const size_t bbId, const size_t bcIndex, const uint16_t reg) const
{
return (IsEntryBlock(bbId) && bcIndex == 0 && reg == GetNumberVRegs());
return (IsFirstBasicBlock(bbId) && bcIndex == 0 && reg == GetNumberVRegs());
}
TSManager *tsManager_;

View File

@ -735,4 +735,4 @@ public:
}
};
} // panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_BYTECODES_H
#endif // ECMASCRIPT_COMPILER_BYTECODES_H

View File

@ -99,8 +99,9 @@ void FrameStateBuilder::BuildPostOrderList(size_t size)
postOrderList_.clear();
std::deque<size_t> pendingList;
std::vector<bool> visited(size, false);
auto entryId = 0;
pendingList.emplace_back(entryId);
// entry block (bbid=0) is a empty block, need skip
auto firstBlockId = 1;
pendingList.emplace_back(firstBlockId);
while (!pendingList.empty()) {
size_t curBlockId = pendingList.back();

View File

@ -123,6 +123,7 @@ group("ark_aot_ts_test") {
"ldstlexvar",
"ldsuperbyname",
"logic_op",
"loop_phi",
"loop_with_variable_exchange",
"loops",
"mod",

View File

@ -0,0 +1,18 @@
# Copyright (c) 2023 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.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_test_action("loop_phi") {
deps = []
}

View File

@ -0,0 +1,14 @@
# Copyright (c) 2023 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.
1

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2023 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.
*/
declare function print(str:any):number;
function foo(l) {
while (l !== null) {
l = l.b;
}
return 1;
}
print(foo({a:1, b:null}));