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