mirror of
https://gitee.com/openharmony/arkcompiler_runtime_core
synced 2024-11-23 06:40:32 +00:00
Optimize function code structure in runtime_core
Signed-off-by: ah <liangahui@h-partners.com>
This commit is contained in:
parent
b5d0c45d2d
commit
acfa8d38c6
@ -28,6 +28,36 @@ constexpr size_t BIN_BASE = 2;
|
||||
|
||||
constexpr size_t MAX_DWORD = 65536;
|
||||
|
||||
inline bool IsHexNumber(const std::string_view &token)
|
||||
{
|
||||
for (auto i : token) {
|
||||
if (!((i >= '0' && i <= '9') || (i >= 'A' && i <= 'F') || (i >= 'a' && i <= 'f'))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool IsBinaryNumber(const std::string_view &token)
|
||||
{
|
||||
for (auto i : token) {
|
||||
if (!(i == '0' || i == '1')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool IsOctalNumber(const std::string_view &token)
|
||||
{
|
||||
for (auto i : token) {
|
||||
if (!(i >= '0' && i <= '7')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool ValidateInteger(const std::string_view &p)
|
||||
{
|
||||
constexpr size_t GENERAL_SHIFT = 2;
|
||||
@ -45,40 +75,17 @@ inline bool ValidateInteger(const std::string_view &p)
|
||||
if (token[0] == '0' && token.size() > 1 && token.find('.') == std::string::npos) {
|
||||
if (token[1] == 'x') {
|
||||
token.remove_prefix(GENERAL_SHIFT);
|
||||
|
||||
for (auto i : token) {
|
||||
if (!((i >= '0' && i <= '9') || (i >= 'A' && i <= 'F') || (i >= 'a' && i <= 'f'))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return IsHexNumber(token);
|
||||
}
|
||||
|
||||
if (token[1] == 'b') {
|
||||
token.remove_prefix(GENERAL_SHIFT);
|
||||
if (token.empty()) {
|
||||
return false;
|
||||
}
|
||||
for (auto i : token) {
|
||||
if (!(i == '0' || i == '1')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return (!token.empty() && IsBinaryNumber(token));
|
||||
}
|
||||
|
||||
if (token[1] >= '0' && token[1] <= '9' && token.find('e') == std::string::npos) {
|
||||
token.remove_prefix(1);
|
||||
|
||||
for (auto i : token) {
|
||||
if (!(i >= '0' && i <= '7')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return IsOctalNumber(token);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,18 +185,8 @@ void RegAccAlloc::SetNeedLda(compiler::Inst *inst, bool need)
|
||||
inst->SetSrcReg(AccReadIndex(inst), reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the accumulator usage between instructions.
|
||||
* Eliminate unnecessary register allocations by applying
|
||||
* a special value (ACC_REG_ID) to the destination and
|
||||
* source registers.
|
||||
* This special value is a marker for the code generator
|
||||
* not to produce lda/sta instructions.
|
||||
*/
|
||||
bool RegAccAlloc::RunImpl()
|
||||
void RegAccAlloc::InitializeSourceRegisters()
|
||||
{
|
||||
GetGraph()->InitDefaultLocations();
|
||||
// Initialize all source register of all instructions.
|
||||
for (auto block : GetGraph()->GetBlocksRPO()) {
|
||||
for (auto inst : block->Insts()) {
|
||||
if (inst->IsSaveState() || inst->IsCatchPhi()) {
|
||||
@ -207,14 +197,16 @@ bool RegAccAlloc::RunImpl()
|
||||
}
|
||||
for (size_t i = 0; i < inst->GetInputsCount(); ++i) {
|
||||
inst->SetSrcReg(i, compiler::INVALID_REG);
|
||||
}
|
||||
if (inst->IsConst()) {
|
||||
inst->SetDstReg(compiler::INVALID_REG);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mark Phi instructions if they can be optimized for acc.
|
||||
void RegAccAlloc::MarkAccForPhiInstructions()
|
||||
{
|
||||
for (auto block : GetGraph()->GetBlocksRPO()) {
|
||||
for (auto phi : block->PhiInsts()) {
|
||||
if (IsPhiAccReady(phi)) {
|
||||
@ -222,9 +214,10 @@ bool RegAccAlloc::RunImpl()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mark instructions if they can be optimized for acc.
|
||||
for (auto block : GetGraph()->GetBlocksRPO()) {
|
||||
void RegAccAlloc::MarkAccForInstructions(compiler::BasicBlock *block)
|
||||
{
|
||||
for (auto inst : block->AllInsts()) {
|
||||
if (inst->NoDest() || !IsAccWrite(inst)) {
|
||||
continue;
|
||||
@ -246,18 +239,29 @@ bool RegAccAlloc::RunImpl()
|
||||
|
||||
if (use_acc_dst_reg) {
|
||||
inst->SetDstReg(compiler::ACC_REG_ID);
|
||||
} else if (inst->IsConst()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!inst->IsConst()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
inst->ClearFlag(compiler::inst_flags::ACC_WRITE);
|
||||
|
||||
for (auto &user : inst->GetUsers()) {
|
||||
compiler::Inst *uinst = user.GetInst();
|
||||
|
||||
if (uinst->IsSaveState()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SetNeedLda(uinst, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegAccAlloc::UpdateInstructionsAfterMark(compiler::BasicBlock *block)
|
||||
{
|
||||
for (auto inst : block->Insts()) {
|
||||
if (inst->GetInputsCount() == 0) {
|
||||
continue;
|
||||
@ -268,8 +272,10 @@ bool RegAccAlloc::RunImpl()
|
||||
}
|
||||
|
||||
compiler::Inst *input = inst->GetInput(AccReadIndex(inst)).GetInst();
|
||||
if (!IsAccWriteBetween(input, inst)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsAccWriteBetween(input, inst)) {
|
||||
input->SetDstReg(compiler::INVALID_REG);
|
||||
SetNeedLda(inst, true);
|
||||
|
||||
@ -281,7 +287,27 @@ bool RegAccAlloc::RunImpl()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the accumulator usage between instructions.
|
||||
* Eliminate unnecessary register allocations by applying
|
||||
* a special value (ACC_REG_ID) to the destination and
|
||||
* source registers.
|
||||
* This special value is a marker for the code generator
|
||||
* not to produce lda/sta instructions.
|
||||
*/
|
||||
bool RegAccAlloc::RunImpl()
|
||||
{
|
||||
GetGraph()->InitDefaultLocations();
|
||||
// Initialize all source register of all instructions.
|
||||
InitializeSourceRegisters();
|
||||
// Mark Phi instructions if they can be optimized for acc.
|
||||
MarkAccForPhiInstructions();
|
||||
// Mark instructions if they can be optimized for acc.
|
||||
for (auto block : GetGraph()->GetBlocksRPO()) {
|
||||
MarkAccForInstructions(block);
|
||||
UpdateInstructionsAfterMark(block);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
@ -51,6 +51,11 @@ private:
|
||||
bool IsPhiAccReady(compiler::Inst *phi) const;
|
||||
void SetNeedLda(compiler::Inst *inst, bool need);
|
||||
|
||||
void InitializeSourceRegisters();
|
||||
void MarkAccForPhiInstructions();
|
||||
void MarkAccForInstructions(compiler::BasicBlock *block);
|
||||
void UpdateInstructionsAfterMark(compiler::BasicBlock *block);
|
||||
|
||||
compiler::Marker acc_marker_ {0};
|
||||
};
|
||||
|
||||
|
@ -85,35 +85,13 @@ public:
|
||||
inst_compare_map_.erase(inst1);
|
||||
return false;
|
||||
}
|
||||
if (inst1->GetOpcode() != Opcode::Phi) {
|
||||
auto inst1_begin = inst1->GetInputs().begin();
|
||||
auto inst1_end = inst1->GetInputs().end();
|
||||
auto inst2_begin = inst2->GetInputs().begin();
|
||||
auto eq_lambda = [this](Input input1, Input input2) { return Compare(input1.GetInst(), input2.GetInst()); };
|
||||
if (!std::equal(inst1_begin, inst1_end, inst2_begin, eq_lambda)) {
|
||||
|
||||
bool result = (inst1->GetOpcode() != Opcode::Phi) ?
|
||||
CompareNonPhiInputs(inst1, inst2) : ComparePhiInputs(inst1, inst2);
|
||||
if (!result) {
|
||||
inst_compare_map_.erase(inst1);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (inst1->GetInputsCount() != inst2->GetInputsCount()) {
|
||||
inst_compare_map_.erase(inst1);
|
||||
return false;
|
||||
}
|
||||
for (size_t index1 = 0; index1 < inst1->GetInputsCount(); index1++) {
|
||||
auto input1 = inst1->GetInput(index1).GetInst();
|
||||
auto bb1 = inst1->CastToPhi()->GetPhiInputBb(index1);
|
||||
if (bb_map_.count(bb1) == 0) {
|
||||
inst_compare_map_.erase(inst1);
|
||||
return false;
|
||||
}
|
||||
auto bb2 = bb_map_.at(bb1);
|
||||
auto input2 = inst2->CastToPhi()->GetPhiInput(bb2);
|
||||
if (!Compare(input1, input2)) {
|
||||
inst_compare_map_.erase(inst1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage
|
||||
#define CAST(Opc) CastTo##Opc()
|
||||
@ -218,7 +196,68 @@ public:
|
||||
// CHECK(LoadType, GetTypeId)
|
||||
#undef CHECK
|
||||
#undef CAST
|
||||
|
||||
if (inst1->GetOpcode() == Opcode::Constant) {
|
||||
if (!CompareConstantInst(inst1, inst2)) {
|
||||
inst_compare_map_.erase(inst1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (inst1->GetOpcode() == Opcode::Cmp && IsFloatType(inst1->GetInput(0).GetInst()->GetType())) {
|
||||
auto cmp1 = static_cast<CmpInst *>(inst1);
|
||||
auto cmp2 = static_cast<CmpInst *>(inst2);
|
||||
if (cmp1->IsFcmpg() != cmp2->IsFcmpg()) {
|
||||
inst_compare_map_.erase(inst1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CompareInputTypes(inst1, inst2) || !CompareSaveStateInst(inst1, inst2)) {
|
||||
inst_compare_map_.erase(inst1);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
std::unordered_map<Inst *, Inst *> inst_compare_map_;
|
||||
std::unordered_map<BasicBlock *, BasicBlock *> bb_map_;
|
||||
|
||||
bool CompareNonPhiInputs(Inst *inst1, Inst *inst2)
|
||||
{
|
||||
auto inst1_begin = inst1->GetInputs().begin();
|
||||
auto inst1_end = inst1->GetInputs().end();
|
||||
auto inst2_begin = inst2->GetInputs().begin();
|
||||
auto eq_lambda = [this](Input input1, Input input2) {
|
||||
return Compare(input1.GetInst(), input2.GetInst());
|
||||
};
|
||||
return std::equal(inst1_begin, inst1_end, inst2_begin, eq_lambda);
|
||||
}
|
||||
|
||||
bool ComparePhiInputs(Inst *inst1, Inst *inst2)
|
||||
{
|
||||
if (inst1->GetInputsCount() != inst2->GetInputsCount()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t index1 = 0; index1 < inst1->GetInputsCount(); index1++) {
|
||||
auto input1 = inst1->GetInput(index1).GetInst();
|
||||
auto bb1 = inst1->CastToPhi()->GetPhiInputBb(index1);
|
||||
if (bb_map_.count(bb1) == 0) {
|
||||
return false;
|
||||
}
|
||||
auto bb2 = bb_map_.at(bb1);
|
||||
auto input2 = inst2->CastToPhi()->GetPhiInput(bb2);
|
||||
if (!Compare(input1, input2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompareConstantInst(Inst *inst1, Inst *inst2)
|
||||
{
|
||||
auto c1 = inst1->CastToConstant();
|
||||
auto c2 = inst2->CastToConstant();
|
||||
bool same = false;
|
||||
@ -231,30 +270,28 @@ public:
|
||||
same = c1->GetRawValue() == c2->GetRawValue();
|
||||
break;
|
||||
}
|
||||
if (!same) {
|
||||
inst_compare_map_.erase(inst1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (inst1->GetOpcode() == Opcode::Cmp && IsFloatType(inst1->GetInput(0).GetInst()->GetType())) {
|
||||
auto cmp1 = static_cast<CmpInst *>(inst1);
|
||||
auto cmp2 = static_cast<CmpInst *>(inst2);
|
||||
if (cmp1->IsFcmpg() != cmp2->IsFcmpg()) {
|
||||
inst_compare_map_.erase(inst1);
|
||||
return false;
|
||||
}
|
||||
return same;
|
||||
}
|
||||
|
||||
bool CompareInputTypes(Inst *inst1, Inst *inst2)
|
||||
{
|
||||
for (size_t i = 0; i < inst2->GetInputsCount(); i++) {
|
||||
if (inst1->GetInputType(i) != inst2->GetInputType(i)) {
|
||||
inst_compare_map_.erase(inst1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (inst1->IsSaveState()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompareSaveStateInst(Inst *inst1, Inst *inst2)
|
||||
{
|
||||
if (!inst1->IsSaveState()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto *sv_st1 = static_cast<SaveStateInst *>(inst1);
|
||||
auto *sv_st2 = static_cast<SaveStateInst *>(inst2);
|
||||
if (sv_st1->GetImmediatesCount() != sv_st2->GetImmediatesCount()) {
|
||||
inst_compare_map_.erase(inst1);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -269,7 +306,6 @@ public:
|
||||
std::sort(regs1.begin(), regs1.end());
|
||||
std::sort(regs2.begin(), regs2.end());
|
||||
if (regs1 != regs2) {
|
||||
inst_compare_map_.erase(inst1);
|
||||
return false;
|
||||
}
|
||||
if (sv_st1->GetImmediatesCount() != 0) {
|
||||
@ -278,17 +314,11 @@ public:
|
||||
};
|
||||
if (!std::equal(sv_st1->GetImmediates()->begin(), sv_st1->GetImmediates()->end(),
|
||||
sv_st2->GetImmediates()->begin(), eq_lambda)) {
|
||||
inst_compare_map_.erase(inst1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<Inst *, Inst *> inst_compare_map_;
|
||||
std::unordered_map<BasicBlock *, BasicBlock *> bb_map_;
|
||||
};
|
||||
} // namespace panda::compiler
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user