• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2024 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 "module_constant_analyzer.h"
17 #include "bytecode_optimizer/constant_propagation/constant_value.h"
18 
19 namespace panda::bytecodeopt {
20 
ModuleConstantAnalyzer(compiler::Graph * graph,const std::unordered_set<uint32_t> & const_local_export_slots,ModuleConstantAnalysisResult & analysis_result,const BytecodeOptIrInterface * iface)21 ModuleConstantAnalyzer::ModuleConstantAnalyzer(compiler::Graph *graph,
22                                                const std::unordered_set<uint32_t> &const_local_export_slots,
23                                                ModuleConstantAnalysisResult &analysis_result,
24                                                const BytecodeOptIrInterface *iface)
25     : Analysis(graph),
26       const_local_export_slots_(const_local_export_slots),
27       analysis_result_(analysis_result),
28       ir_interface_(iface)
29 {
30 }
31 
RunImpl()32 bool ModuleConstantAnalyzer::RunImpl()
33 {
34     VisitGraph();
35     return true;
36 }
37 
VisitIntrinsic(compiler::GraphVisitor * visitor,compiler::Inst * inst)38 void ModuleConstantAnalyzer::VisitIntrinsic(compiler::GraphVisitor *visitor, compiler::Inst *inst)
39 {
40     constexpr int STMODULEVAR_VALUE_INPUT_INDEX = 0;
41     constexpr int STMODULEVAR_SLOT_NUMBER_IMM_INDEX = 0;
42     auto module_constant_analyzer = static_cast<ModuleConstantAnalyzer *>(visitor);
43     auto intrinsic_inst = inst->CastToIntrinsic();
44     auto id = intrinsic_inst->GetIntrinsicId();
45     switch (id) {
46         case RuntimeInterface::IntrinsicId::STMODULEVAR_IMM8:
47         case RuntimeInterface::IntrinsicId::WIDE_STMODULEVAR_PREF_IMM16: {
48             int module_var_slot = intrinsic_inst->GetImms()[STMODULEVAR_SLOT_NUMBER_IMM_INDEX];
49             if (!module_constant_analyzer->IsConstModuleVar(module_var_slot)) {
50                 break;
51             }
52             auto input_inst = inst->GetDataFlowInput(STMODULEVAR_VALUE_INPUT_INDEX);
53             auto input_const_value = module_constant_analyzer->GetInstConstValue(input_inst);
54             if (input_const_value != nullptr) {
55                 module_constant_analyzer->RecordModuleConstValue(module_var_slot, input_const_value);
56             }
57             break;
58         }
59         default:
60             break;
61     }
62 }
63 
GetInstConstValue(Inst * inst)64 ConstantValue *ModuleConstantAnalyzer::GetInstConstValue(Inst *inst)
65 {
66     switch (inst->GetOpcode()) {
67         case Opcode::Constant:
68             return GetConstantInstConstValue(inst->CastToConstant());
69         case Opcode::Intrinsic:
70             return GetIntrinsicInstConstValue(inst->CastToIntrinsic());
71         case Opcode::LoadString:
72             return GetLoadStringInstConstValue(inst->CastToLoadString());
73         case Opcode::CastValueToAnyType:
74             // According to inst_builder.cpp:
75             // 1. the fldai bytecode generates Constant(double) -> CastValueToAnyType,
76             // 1. the lda.str bytecode generates LoadString -> CastValueToAnyType,
77             // We handle such case here. 0 stands for the DataFlowInput corresponding to the Constant/LoadString
78             if (inst->GetDataFlowInput(0)->IsConst() ||
79                 inst->GetDataFlowInput(0)->GetOpcode() == compiler::Opcode::LoadString) {
80                 return GetInstConstValue(inst->GetDataFlowInput(0));
81             }
82             return nullptr;
83         default:
84             return nullptr;
85     }
86 }
87 
GetConstantInstConstValue(compiler::ConstantInst * const_inst)88 ConstantValue *ModuleConstantAnalyzer::GetConstantInstConstValue(compiler::ConstantInst *const_inst)
89 {
90     switch (const_inst->GetType()) {
91         case compiler::DataType::INT32: {
92             auto val = static_cast<int32_t>(const_inst->GetInt32Value());
93             return GetGraph()->GetAllocator()->New<ConstantValue>(val);
94         }
95         case compiler::DataType::INT64: {
96             auto val = static_cast<int64_t>(const_inst->GetRawValue());
97             return GetGraph()->GetAllocator()->New<ConstantValue>(val);
98         }
99         case compiler::DataType::FLOAT64: {
100             auto val = const_inst->GetDoubleValue();
101             return GetGraph()->GetAllocator()->New<ConstantValue>(val);
102         }
103         default:
104             UNREACHABLE();
105     }
106 }
107 
GetIntrinsicInstConstValue(compiler::IntrinsicInst * intrinsic_inst)108 ConstantValue *ModuleConstantAnalyzer::GetIntrinsicInstConstValue(compiler::IntrinsicInst *intrinsic_inst)
109 {
110     switch (intrinsic_inst->GetIntrinsicId()) {
111         case RuntimeInterface::IntrinsicId::LDTRUE:
112         case RuntimeInterface::IntrinsicId::LDFALSE: {
113             bool is_true = intrinsic_inst->GetIntrinsicId() == RuntimeInterface::IntrinsicId::LDTRUE;
114             return GetGraph()->GetAllocator()->New<ConstantValue>(is_true);
115         }
116         default:
117             return nullptr;
118     }
119 }
120 
GetLoadStringInstConstValue(compiler::LoadFromPool * inst)121 ConstantValue *ModuleConstantAnalyzer::GetLoadStringInstConstValue(compiler::LoadFromPool *inst)
122 {
123     return GetGraph()->GetAllocator()->New<ConstantValue>(
124         ir_interface_->GetStringIdByOffset(inst->GetTypeId()));
125 }
126 
IsConstModuleVar(uint32_t slot)127 bool ModuleConstantAnalyzer::IsConstModuleVar(uint32_t slot)
128 {
129     return const_local_export_slots_.count(slot) == 1;
130 }
131 
RecordModuleConstValue(uint32_t slot,ConstantValue * value)132 void ModuleConstantAnalyzer::RecordModuleConstValue(uint32_t slot, ConstantValue *value)
133 {
134     analysis_result_.emplace(slot, value);
135 }
136 
137 }  // namespace panda::bytecodeopt