• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "cg_stackmap_computation.h"
17 #include "live.h"
18 
19 namespace maplebe {
20 #define STACKMAP_DUMP (CG_DEBUG_FUNC(f))
21 
SetStackmapDerivedInfo()22 void StackmapComputation::SetStackmapDerivedInfo()
23 {
24     FOR_ALL_BB(bb, &cgFunc)
25     {
26         FOR_BB_INSNS(insn, bb)
27         {
28             if (!insn->IsMachineInstruction()) {
29                 continue;
30             }
31             const InsnDesc *md = insn->GetDesc();
32             uint32 opndNum = insn->GetOperandSize();
33             for (uint32 i = 0; i < opndNum; ++i) {
34                 const OpndDesc *regProp = md->GetOpndDes(i);
35                 DEBUG_ASSERT(regProp != nullptr, "pointer is null in StackmapComputation::SetStackMapDerivedInfo");
36                 bool isDef = regProp->IsRegDef();
37                 Operand &opnd = insn->GetOperand(i);
38                 if (isDef) {
39                     auto &regOpnd = static_cast<RegOperand &>(opnd);
40                     uint32 regNO = regOpnd.GetRegisterNumber();
41                     if (regOpnd.GetBaseRefOpnd() != nullptr) {
42                         // set the base reference of derived reference for stackmap
43                         derivedRef2Base[regNO] = regOpnd.GetBaseRefOpnd();
44                     }
45                 }
46             }
47         }
48     }
49 }
50 
GetSpillMem(uint32 vRegNO,bool isDest,Insn & insn,regno_t regNO,bool & isOutOfRange,uint32 bitSize)51 MemOperand *StackmapComputation::GetSpillMem(uint32 vRegNO, bool isDest, Insn &insn, regno_t regNO,
52                                              bool &isOutOfRange, uint32 bitSize)
53 {
54     MemOperand *memOpnd = regInfo->GetOrCreatSpillMem(vRegNO, bitSize);
55     return regInfo->AdjustMemOperandIfOffsetOutOfRange(memOpnd, std::make_pair(vRegNO, regNO), isDest, insn,
56                                                        isOutOfRange);
57 }
58 
SpillOperand(Insn & insn,regno_t regNO)59 void StackmapComputation::SpillOperand(Insn &insn, regno_t regNO)
60 {
61     bool isOutOfRange = false;
62     uint32 regSize = GetPrimTypeSize(PTY_ref) * k8BitSize;
63     PrimType spType = PTY_ref;
64 #if TARGX86_64
65     RegOperand &srcOpnd = cgFunc.GetOpndBuilder()->CreateVReg(regNO, regSize, cgFunc.GetRegTyFromPrimTy(spType));
66 #else
67     RegOperand &srcOpnd = cgFunc.GetOrCreateVirtualRegisterOperand(regNO);
68 #endif
69 
70     MemOperand *memOpnd = GetSpillMem(regNO, true, insn, kInvalidRegNO, isOutOfRange, regSize);
71     Insn *stInsn = regInfo->BuildStrInsn(regSize, spType, srcOpnd, *memOpnd);
72     insn.GetBB()->InsertInsnBefore(insn, *stInsn);
73 }
74 
LoadOperand(Insn & insn,regno_t regNO)75 void StackmapComputation::LoadOperand(Insn &insn, regno_t regNO)
76 {
77     bool isOutOfRange = false;
78     uint32 regSize = GetPrimTypeSize(PTY_ref) * k8BitSize;
79     PrimType spType = PTY_ref;
80 
81 #if TARGX86_64
82     RegOperand &resOpnd = cgFunc.GetOpndBuilder()->CreateVReg(regNO, regSize, cgFunc.GetRegTyFromPrimTy(spType));
83 #else
84     RegOperand &resOpnd = cgFunc.GetOrCreateVirtualRegisterOperand(regNO);
85 #endif
86 
87     Insn *nextInsn = insn.GetNext();
88     MemOperand *memOpnd = GetSpillMem(regNO, false, insn, kInvalidRegNO, isOutOfRange, regSize);
89     Insn *ldInsn = regInfo->BuildLdrInsn(regSize, spType, resOpnd, *memOpnd);
90     if (isOutOfRange && nextInsn != nullptr) {
91         insn.GetBB()->InsertInsnBefore(*nextInsn, *ldInsn);
92     } else if (isOutOfRange && nextInsn == nullptr) {
93         insn.GetBB()->AppendInsn(*ldInsn);
94     } else {
95         insn.GetBB()->InsertInsnAfter(insn, *ldInsn);
96     }
97 }
98 
RelocateStackmapInfo()99 void StackmapComputation::RelocateStackmapInfo()
100 {
101     const auto &referenceMapInsns = cgFunc.GetStackMapInsns();
102     for (auto *insn : referenceMapInsns) {
103         auto &deoptInfo = insn->GetStackMap()->GetDeoptInfo();
104         const auto &deoptBundleInfo = deoptInfo.GetDeoptBundleInfo();
105         for (const auto &item : deoptBundleInfo) {
106             const auto *opnd = item.second;
107             if (!opnd->IsRegister()) {
108                 continue;
109             }
110             regno_t regNO = (static_cast<const RegOperand *>(opnd))->GetRegisterNumber();
111             SpillOperand(*insn, regNO);
112             LoadOperand(*insn, regNO);
113         }
114 
115         for (auto regNO : insn->GetStackMapLiveIn()) {
116             if (!cgFunc.IsRegReference(regNO)) {
117                 continue;
118             }
119             auto itr = derivedRef2Base.find(regNO);
120             if (itr != derivedRef2Base.end()) {
121                 SpillOperand(*insn, itr->second->GetRegisterNumber());
122                 LoadOperand(*insn, itr->second->GetRegisterNumber());
123             }
124             SpillOperand(*insn, regNO);
125             LoadOperand(*insn, regNO);
126         }
127     }
128 }
129 
CollectReferenceMap()130 void StackmapComputation::CollectReferenceMap()
131 {
132     const auto &referenceMapInsns = cgFunc.GetStackMapInsns();
133     if (needDump) {
134         LogInfo::MapleLogger() << "===========reference map stack info================\n";
135     }
136 
137     int insnNum = 0;
138 
139     for (auto *insn : referenceMapInsns) {
140         insnNum++;
141         for (auto regNO : insn->GetStackMapLiveIn()) {
142             if (!cgFunc.IsRegReference(regNO)) {
143                 continue;
144             }
145 
146             auto itr = derivedRef2Base.find(regNO);
147             if (itr != derivedRef2Base.end()) {
148                 auto baseRegNum = (itr->second)->GetRegisterNumber();
149                 MemOperand *baseRegMemOpnd = cgFunc.GetOrCreatSpillMem(baseRegNum, k64BitSize);
150                 int64 baseRefMemoffset = baseRegMemOpnd->GetOffsetImmediate()->GetOffsetValue();
151                 insn->GetStackMap()->GetReferenceMap().ReocordStackRoots(baseRefMemoffset);
152                 if (needDump) {
153                     LogInfo::MapleLogger() << "--------insn num: " << insnNum
154                                            << " base regNO: " << baseRegNum << " offset: "
155                                            << baseRefMemoffset << std::endl;
156                 }
157             }
158             MemOperand *memOperand = cgFunc.GetOrCreatSpillMem(regNO, k64BitSize);
159             int64 offset = memOperand->GetOffsetImmediate()->GetOffsetValue();
160             insn->GetStackMap()->GetReferenceMap().ReocordStackRoots(offset);
161             if (itr == derivedRef2Base.end()) {
162                 insn->GetStackMap()->GetReferenceMap().ReocordStackRoots(offset);
163             }
164             if (needDump) {
165                 LogInfo::MapleLogger() << "--------insn num: " << insnNum << " regNO: " << regNO
166                                        << " offset: " << offset << std::endl;
167             }
168         }
169     }
170 
171     if (needDump) {
172         LogInfo::MapleLogger() << "===========reference map stack info end================\n";
173     }
174     if (needDump) {
175         LogInfo::MapleLogger() << "===========reference map info================\n";
176         for (auto *insn : referenceMapInsns) {
177             LogInfo::MapleLogger() << "  referenceMap insn: ";
178             insn->Dump();
179             insn->GetStackMap()->GetReferenceMap().Dump();
180         }
181     }
182 }
183 
SolveRegOpndDeoptInfo(const RegOperand & regOpnd,DeoptInfo & deoptInfo,int32 deoptVregNO) const184 void StackmapComputation::SolveRegOpndDeoptInfo(const RegOperand &regOpnd, DeoptInfo &deoptInfo,
185                                                 int32 deoptVregNO) const
186 {
187     if (!regOpnd.IsVirtualRegister()) {
188         // Get Register No
189         deoptInfo.RecordDeoptVreg2LocationInfo(deoptVregNO, LocationInfo({kInRegister, 0}));
190         return;
191     }
192     // process virtual RegOperand
193     regno_t vRegNO = regOpnd.GetRegisterNumber();
194     MemOperand *memOpnd = cgFunc.GetOrCreatSpillMem(vRegNO, regOpnd.GetSize());
195     SolveMemOpndDeoptInfo(*(static_cast<const MemOperand *>(memOpnd)), deoptInfo, deoptVregNO);
196 }
197 
SolveMemOpndDeoptInfo(const MemOperand & memOpnd,DeoptInfo & deoptInfo,int32 deoptVregNO) const198 void StackmapComputation::SolveMemOpndDeoptInfo(const MemOperand &memOpnd, DeoptInfo &deoptInfo,
199                                                 int32 deoptVregNO) const
200 {
201     int64 offset = memOpnd.GetOffsetImmediate()->GetOffsetValue();
202     deoptInfo.RecordDeoptVreg2LocationInfo(deoptVregNO, LocationInfo({kOnStack, offset}));
203 }
204 
CollectDeoptInfo()205 void StackmapComputation::CollectDeoptInfo()
206 {
207     const auto referenceMapInsns = cgFunc.GetStackMapInsns();
208     for (auto *insn : referenceMapInsns) {
209         auto &deoptInfo = insn->GetStackMap()->GetDeoptInfo();
210         const auto &deoptBundleInfo = deoptInfo.GetDeoptBundleInfo();
211         if (deoptBundleInfo.empty()) {
212             continue;
213         }
214         for (const auto &item : deoptBundleInfo) {
215             const auto *opnd = item.second;
216             if (opnd->IsRegister()) {
217                 SolveRegOpndDeoptInfo(*static_cast<const RegOperand *>(opnd), deoptInfo, item.first);
218                 continue;
219             }
220             if (opnd->IsImmediate()) {
221                 const auto *immOpnd = static_cast<const ImmOperand *>(opnd);
222                 deoptInfo.RecordDeoptVreg2LocationInfo(item.first, LocationInfo({kInConstValue, immOpnd->GetValue()}));
223                 continue;
224             }
225             if (opnd->IsMemoryAccessOperand()) {
226                 SolveMemOpndDeoptInfo(*(static_cast<const MemOperand *>(opnd)), deoptInfo, item.first);
227                 continue;
228             }
229             DEBUG_ASSERT(false, "can't reach here!");
230         }
231     }
232     if (needDump) {
233         LogInfo::MapleLogger() << "===========deopt info================\n";
234         for (auto *insn : referenceMapInsns) {
235             LogInfo::MapleLogger() << "---- deoptInfo insn: ";
236             insn->Dump();
237             insn->GetStackMap()->GetDeoptInfo().Dump();
238         }
239     }
240 }
241 
run()242 void StackmapComputation::run()
243 {
244     if (needDump) {
245         LogInfo::MapleLogger() << "===========StackmapComputation PhaseRun================\n";
246     }
247     SetStackmapDerivedInfo();
248     RelocateStackmapInfo();
249     CollectReferenceMap();
250     CollectDeoptInfo();
251 }
252 
PhaseRun(maplebe::CGFunc & f)253 bool CgStackmapComputation::PhaseRun(maplebe::CGFunc &f)
254 {
255     MemPool *phaseMp = GetPhaseMemPool();
256     LiveAnalysis *live = nullptr;
257     live = GET_ANALYSIS(CgLiveAnalysis, f);
258     StackmapComputation *stackmapComputation = nullptr;
259     stackmapComputation = GetPhaseAllocator()->New<StackmapComputation>(f, *phaseMp);
260     stackmapComputation->SetNeedDump(STACKMAP_DUMP);
261     stackmapComputation->run();
262 
263     if (live != nullptr) {
264         live->ClearInOutDataInfo();
265     }
266 
267     f.SetStackMapComputed();
268 
269     return true;
270 }
271 
GetAnalysisDependence(maple::AnalysisDep & aDep) const272 void CgStackmapComputation::GetAnalysisDependence(maple::AnalysisDep &aDep) const
273 {
274     aDep.AddRequired<CgLiveAnalysis>();
275 }
276 
277 MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(CgStackmapComputation, stackmapcomputation)
278 }  // namespace maplebe
279