• 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 "isel.h"
17 #include "factory.h"
18 #include "cg.h"
19 #include "standardize.h"
20 #include <map>
21 #include <utility>
22 
23 namespace maplebe {
24 /* register,                       imm ,                         memory,                        cond */
25 #define DEF_FAST_ISEL_MAPPING_INT(SIZE)                                                                               \
26     MOperator fastIselMapI##SIZE[Operand::OperandType::kOpdPhi][Operand::OperandType::kOpdPhi] = {                    \
27         {abstract::MOP_copy_rr_##SIZE, abstract::MOP_copy_ri_##SIZE, abstract::MOP_load_##SIZE, abstract::MOP_undef}, \
28         {abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef},                         \
29         {abstract::MOP_str_##SIZE, abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef},                    \
30         {abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef},                         \
31     }
32 #define DEF_FAST_ISEL_MAPPING_FLOAT(SIZE)                                                            \
33     MOperator fastIselMapF##SIZE[Operand::OperandType::kOpdPhi][Operand::OperandType::kOpdPhi] = {   \
34         {abstract::MOP_copy_ff_##SIZE, abstract::MOP_copy_fi_##SIZE, abstract::MOP_load_f_##SIZE,    \
35          abstract::MOP_undef},                                                                       \
36         {abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef},        \
37         {abstract::MOP_str_f_##SIZE, abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef}, \
38         {abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef},        \
39     }
40 
41 DEF_FAST_ISEL_MAPPING_INT(8);
42 DEF_FAST_ISEL_MAPPING_INT(16);
43 DEF_FAST_ISEL_MAPPING_INT(32);
44 DEF_FAST_ISEL_MAPPING_INT(64);
45 DEF_FAST_ISEL_MAPPING_FLOAT(8);
46 DEF_FAST_ISEL_MAPPING_FLOAT(16);
47 DEF_FAST_ISEL_MAPPING_FLOAT(32);
48 DEF_FAST_ISEL_MAPPING_FLOAT(64);
49 
50 #define DEF_SEL_MAPPING_TBL(SIZE)                                           \
51     MOperator SelMapping##SIZE(bool isInt, uint32 x, uint32 y)              \
52     {                                                                       \
53         return isInt ? fastIselMapI##SIZE[x][y] : fastIselMapF##SIZE[x][y]; \
54     }
55 #define USE_SELMAPPING_TBL(SIZE) \
56     {                            \
57         SIZE, SelMapping##SIZE   \
58     }
59 
60 DEF_SEL_MAPPING_TBL(8);
61 DEF_SEL_MAPPING_TBL(16);
62 DEF_SEL_MAPPING_TBL(32);
63 DEF_SEL_MAPPING_TBL(64);
64 
65 std::map<uint32, std::function<MOperator(bool, uint32, uint32)>> fastIselMappingTable = {
66     USE_SELMAPPING_TBL(8), USE_SELMAPPING_TBL(16), USE_SELMAPPING_TBL(32), USE_SELMAPPING_TBL(64)};
67 
GetFastIselMop(Operand::OperandType dTy,Operand::OperandType sTy,PrimType type)68 MOperator GetFastIselMop(Operand::OperandType dTy, Operand::OperandType sTy, PrimType type)
69 {
70     uint32 bitSize = GetPrimTypeBitSize(type);
71     bool isInteger = IsPrimitiveInteger(type);
72     auto tableDriven = fastIselMappingTable.find(bitSize);
73     if (tableDriven != fastIselMappingTable.end()) {
74         auto funcIt = tableDriven->second;
75         return funcIt(isInteger, dTy, sTy);
76     } else {
77         CHECK_FATAL(false, "unsupport type");
78     }
79     return abstract::MOP_undef;
80 }
81 
82 #define DEF_EXTEND_MAPPING_TBL(TYPE)                                                            \
83     [](bool isSigned)->MOperator {                                                              \
84         return isSigned ? abstract::MOP_sext_rr_##TYPE : abstract::MOP_zext_rr_##TYPE;          \
85     }
86 using fromToTy = std::pair<uint32, uint32>; /* std::pair<from, to> */
87 #define DEF_USE_EXTEND_MAPPING_TBL(FROMSIZE, TOSIZE)                                            \
88     {                                                                                           \
89         {k##FROMSIZE##BitSize, k##TOSIZE##BitSize}, DEF_EXTEND_MAPPING_TBL(TOSIZE##_##FROMSIZE) \
90     }
91 
92 std::map<fromToTy, std::function<MOperator(bool)>> fastCvtMappingTableI = {
93     DEF_USE_EXTEND_MAPPING_TBL(8, 16), /* Extend Mapping */
94     DEF_USE_EXTEND_MAPPING_TBL(8, 32),  DEF_USE_EXTEND_MAPPING_TBL(8, 64),  DEF_USE_EXTEND_MAPPING_TBL(16, 32),
95     DEF_USE_EXTEND_MAPPING_TBL(16, 64), DEF_USE_EXTEND_MAPPING_TBL(32, 64),
96 };
97 #undef DEF_USE_EXTEND_MAPPING_TBL
98 #undef DEF_EXTEND_MAPPING_TBL
99 
GetFastCvtMopI(uint32 fromSize,uint32 toSize,bool isSigned)100 static MOperator GetFastCvtMopI(uint32 fromSize, uint32 toSize, bool isSigned)
101 {
102     if (toSize < k8BitSize || toSize > k64BitSize) {
103         CHECK_FATAL(false, "unsupport type");
104     }
105     if (fromSize < k8BitSize || fromSize > k64BitSize) {
106         CHECK_FATAL(false, "unsupport type");
107     }
108     /* Extend: fromSize < toSize */
109     auto tableDriven = fastCvtMappingTableI.find({fromSize, toSize});
110     if (tableDriven == fastCvtMappingTableI.end()) {
111         CHECK_FATAL(false, "unsupport cvt");
112     }
113     MOperator mOp = tableDriven->second(isSigned);
114     if (mOp == abstract::MOP_undef) {
115         CHECK_FATAL(false, "unsupport cvt");
116     }
117     return mOp;
118 }
119 
120 /*
121  * fast get MOperator
122  * such as : and, or, shl ...
123  */
124 #define DEF_MOPERATOR_MAPPING_FUNC(TYPE)                                                           \
125     [](uint32 bitSize)->MOperator {                                                              \
126         /* 8-bits,                16-bits,                   32-bits,                   64-bits */ \
127         constexpr static std::array<MOperator, kBitIndexEnd> fastMapping_##TYPE = {                \
128             abstract::MOP_##TYPE##_8, abstract::MOP_##TYPE##_16, abstract::MOP_##TYPE##_32,        \
129             abstract::MOP_##TYPE##_64};                                                            \
130         return fastMapping_##TYPE[GetBitIndex(bitSize)];                                           \
131     }
132 
133 #define DEF_FLOAT_MOPERATOR_MAPPING_FUNC(TYPE)                                                     \
134     [](uint32 bitSize)->MOperator {                                                              \
135         /* 8-bits,                16-bits,                   32-bits,                   64-bits */ \
136         constexpr static std::array<MOperator, kBitIndexEnd> fastMapping_f_##TYPE = {              \
137             abstract::MOP_##TYPE##_f_8, abstract::MOP_##TYPE##_f_16, abstract::MOP_##TYPE##_f_32,  \
138             abstract::MOP_##TYPE##_f_64};                                                          \
139         return fastMapping_f_##TYPE[GetBitIndex(bitSize)];                                         \
140     }
141 
HandleDassign(StmtNode & stmt,MPISel & iSel)142 void HandleDassign(StmtNode &stmt, MPISel &iSel)
143 {
144     DEBUG_ASSERT(stmt.GetOpCode() == OP_dassign, "expect dassign");
145     auto &dassignNode = static_cast<DassignNode &>(stmt);
146     BaseNode *rhs = dassignNode.GetRHS();
147     DEBUG_ASSERT(rhs != nullptr, "get rhs of dassignNode failed");
148     Operand *opndRhs = iSel.HandleExpr(dassignNode, *rhs);
149     if (opndRhs == nullptr) {
150         return;
151     }
152     iSel.SelectDassign(dassignNode, *opndRhs);
153 }
154 
HandleDassignoff(StmtNode & stmt,MPISel & iSel)155 void HandleDassignoff(StmtNode &stmt, MPISel &iSel)
156 {
157     auto &dassignoffNode = static_cast<DassignoffNode &>(stmt);
158     BaseNode *rhs = dassignoffNode.GetRHS();
159     CHECK_FATAL(rhs->GetOpCode() == OP_constval, "dassignoffNode without constval");
160     Operand *opnd0 = iSel.HandleExpr(dassignoffNode, *rhs);
161     iSel.SelectDassignoff(dassignoffNode, *opnd0);
162 }
163 
HandleIassign(StmtNode & stmt,MPISel & iSel)164 void HandleIassign(StmtNode &stmt, MPISel &iSel)
165 {
166     DEBUG_ASSERT(stmt.GetOpCode() == OP_iassign, "expect iassign");
167     auto &iassignNode = static_cast<IassignNode &>(stmt);
168     BaseNode *rhs = iassignNode.GetRHS();
169     DEBUG_ASSERT(rhs != nullptr, "null ptr check");
170     Operand *opndRhs = iSel.HandleExpr(stmt, *rhs);
171     BaseNode *addr = iassignNode.Opnd(0);
172     DEBUG_ASSERT(addr != nullptr, "null ptr check");
173     Operand *opndAddr = iSel.HandleExpr(stmt, *addr);
174     if (opndRhs == nullptr || opndAddr == nullptr) {
175         return;
176     }
177     if (rhs->GetPrimType() != PTY_agg) {
178         iSel.SelectIassign(iassignNode, *opndAddr, *opndRhs);
179     } else {
180         iSel.SelectAggIassign(iassignNode, *opndAddr, *opndRhs);
181     }
182 }
183 
HandleRegassign(StmtNode & stmt,MPISel & iSel)184 void HandleRegassign(StmtNode &stmt, MPISel &iSel)
185 {
186     DEBUG_ASSERT(stmt.GetOpCode() == OP_regassign, "expect regAssign");
187     auto &regAssignNode = static_cast<RegassignNode &>(stmt);
188     BaseNode *operand = regAssignNode.Opnd(0);
189     DEBUG_ASSERT(operand != nullptr, "get operand of regassignNode failed");
190     Operand *opnd0 = iSel.HandleExpr(regAssignNode, *operand);
191     iSel.SelectRegassign(regAssignNode, *opnd0);
192 }
193 
HandleIassignoff(StmtNode & stmt,MPISel & iSel)194 void HandleIassignoff(StmtNode &stmt, MPISel &iSel)
195 {
196     auto &iassignoffNode = static_cast<IassignoffNode &>(stmt);
197     iSel.SelectIassignoff(iassignoffNode);
198 }
199 
HandleLabel(StmtNode & stmt,const MPISel & iSel)200 void HandleLabel(StmtNode &stmt, const MPISel &iSel)
201 {
202     CGFunc *cgFunc = iSel.GetCurFunc();
203     DEBUG_ASSERT(stmt.GetOpCode() == OP_label, "error");
204     auto &label = static_cast<LabelNode &>(stmt);
205     BB *newBB = cgFunc->StartNewBBImpl(false, label);
206     newBB->AddLabel(label.GetLabelIdx());
207     cgFunc->SetLab2BBMap(static_cast<int32>(newBB->GetLabIdx()), *newBB);
208     cgFunc->SetCurBB(*newBB);
209 }
210 
HandleGoto(StmtNode & stmt,MPISel & iSel)211 void HandleGoto(StmtNode &stmt, MPISel &iSel)
212 {
213     CGFunc *cgFunc = iSel.GetCurFunc();
214     cgFunc->UpdateFrequency(stmt);
215     auto &gotoNode = static_cast<GotoNode &>(stmt);
216     DEBUG_ASSERT(gotoNode.GetOpCode() == OP_goto, "expect goto");
217     cgFunc->SetCurBBKind(BB::kBBGoto);
218     iSel.SelectGoto(gotoNode);
219     cgFunc->SetCurBB(*cgFunc->StartNewBB(gotoNode));
220     DEBUG_ASSERT(&stmt == &gotoNode, "stmt must be same as gotoNoe");
221     if ((gotoNode.GetNext() != nullptr) && (gotoNode.GetNext()->GetOpCode() != OP_label)) {
222         DEBUG_ASSERT(cgFunc->GetCurBB()->GetPrev()->GetLastStmt() == &stmt, "check the relation between BB and stmt");
223     }
224 }
225 
HandleIntrinCall(StmtNode & stmt,MPISel & iSel)226 void HandleIntrinCall(StmtNode &stmt, MPISel &iSel)
227 {
228     auto &call = static_cast<IntrinsiccallNode &>(stmt);
229     iSel.SelectIntrinCall(call);
230 }
231 
HandleRangeGoto(StmtNode & stmt,MPISel & iSel)232 void HandleRangeGoto(StmtNode &stmt, MPISel &iSel)
233 {
234     CGFunc *cgFunc = iSel.GetCurFunc();
235     auto &rangeGotoNode = static_cast<RangeGotoNode &>(stmt);
236     DEBUG_ASSERT(rangeGotoNode.GetOpCode() == OP_rangegoto, "expect rangegoto");
237     BaseNode *srcNode = rangeGotoNode.Opnd(0);
238     Operand *srcOpnd = iSel.HandleExpr(rangeGotoNode, *srcNode);
239     cgFunc->SetCurBBKind(BB::kBBRangeGoto);
240     iSel.SelectRangeGoto(rangeGotoNode, *srcOpnd);
241 }
242 
HandleIgoto(StmtNode & stmt,MPISel & iSel)243 void HandleIgoto(StmtNode &stmt, MPISel &iSel)
244 {
245     CGFunc *cgFunc = iSel.GetCurFunc();
246     auto &igotoNode = static_cast<UnaryStmtNode &>(stmt);
247     BaseNode *targetNode = igotoNode.Opnd(0);
248     Operand *targetOpnd = iSel.HandleExpr(igotoNode, *targetNode);
249     iSel.SelectIgoto(*targetOpnd);
250     cgFunc->SetCurBBKind(BB::kBBIgoto);
251     cgFunc->SetCurBB(*cgFunc->StartNewBB(igotoNode));
252 }
253 
HandleReturn(StmtNode & stmt,MPISel & iSel)254 void HandleReturn(StmtNode &stmt, MPISel &iSel)
255 {
256     CGFunc *cgFunc = iSel.GetCurFunc();
257     auto &retNode = static_cast<NaryStmtNode &>(stmt);
258     DEBUG_ASSERT(retNode.NumOpnds() <= 1, "NYI return nodes number > 1");
259     if (retNode.NumOpnds() != 0) {
260         Operand *opnd = iSel.HandleExpr(retNode, *retNode.Opnd(0));
261         iSel.SelectReturn(retNode, *opnd);
262     }
263     iSel.SelectReturn();
264     /* return stmt will jump to the ret BB, so curBB is gotoBB */
265     cgFunc->SetCurBBKind(BB::kBBGoto);
266     cgFunc->SetCurBB(*cgFunc->StartNewBB(retNode));
267 }
268 
HandleComment(StmtNode & stmt,MPISel & iSel)269 void HandleComment(StmtNode &stmt, MPISel &iSel)
270 {
271     return;
272 }
273 
HandleIcall(StmtNode & stmt,MPISel & iSel)274 void HandleIcall(StmtNode &stmt, MPISel &iSel)
275 {
276     DEBUG_ASSERT(stmt.GetOpCode() == OP_icall || stmt.GetOpCode() == OP_icallproto, "error");
277     auto &iCallNode = static_cast<IcallNode &>(stmt);
278     Operand *opnd0 = iSel.HandleExpr(iCallNode, *iCallNode.Opnd(0));
279     iSel.SelectIcall(iCallNode, *opnd0);
280     iSel.SelectCallCommon(stmt, iSel);
281 }
282 
HandleCall(StmtNode & stmt,MPISel & iSel)283 void HandleCall(StmtNode &stmt, MPISel &iSel)
284 {
285     DEBUG_ASSERT(stmt.GetOpCode() == OP_call, "error");
286     auto &callNode = static_cast<CallNode &>(stmt);
287     iSel.SelectCall(callNode);
288     iSel.SelectCallCommon(stmt, iSel);
289 }
290 
HandleCondbr(StmtNode & stmt,MPISel & iSel)291 void HandleCondbr(StmtNode &stmt, MPISel &iSel)
292 {
293     CGFunc *cgFunc = iSel.GetCurFunc();
294     auto &condGotoNode = static_cast<CondGotoNode &>(stmt);
295     BaseNode *condNode = condGotoNode.Opnd(0);
296     DEBUG_ASSERT(condNode != nullptr, "expect first operand of cond br");
297     /* select cmpOp Insn and get the result "opnd0". However, the opnd0 is not used
298      * in most backend architectures */
299     Operand *opnd0 = iSel.HandleExpr(stmt, *condNode);
300     iSel.SelectCondGoto(condGotoNode, *condNode, *opnd0);
301     cgFunc->SetCurBB(*cgFunc->StartNewBB(condGotoNode));
302 }
303 
HandleAddrof(const BaseNode & parent,BaseNode & expr,MPISel & iSel)304 Operand *HandleAddrof(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
305 {
306     auto &addrofNode = static_cast<AddrofNode &>(expr);
307     return iSel.SelectAddrof(addrofNode, parent);
308 }
309 
HandleAddroffunc(const BaseNode & parent,BaseNode & expr,MPISel & iSel)310 Operand *HandleAddroffunc(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
311 {
312     auto &addrofNode = static_cast<AddroffuncNode &>(expr);
313     return iSel.SelectAddrofFunc(addrofNode, parent);
314 }
315 
HandleAddrofLabel(const BaseNode & parent,BaseNode & expr,MPISel & iSel)316 Operand *HandleAddrofLabel(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
317 {
318     auto &addrofLabelNode = static_cast<AddroflabelNode &>(expr);
319     return iSel.SelectAddrofLabel(addrofLabelNode, parent);
320 }
321 
HandleShift(const BaseNode & parent,BaseNode & expr,MPISel & iSel)322 Operand *HandleShift(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
323 {
324     return iSel.SelectShift(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
325                             *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
326 }
327 
HandleCvt(const BaseNode & parent,BaseNode & expr,MPISel & iSel)328 Operand *HandleCvt(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
329 {
330     return iSel.SelectCvt(parent, static_cast<TypeCvtNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)));
331 }
332 
HandleExtractBits(const BaseNode & parent,BaseNode & expr,MPISel & iSel)333 Operand *HandleExtractBits(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
334 {
335     return iSel.SelectExtractbits(parent, static_cast<ExtractbitsNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)));
336 }
337 
HandleDread(const BaseNode & parent,BaseNode & expr,MPISel & iSel)338 Operand *HandleDread(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
339 {
340     auto &dreadNode = static_cast<AddrofNode &>(expr);
341     return iSel.SelectDread(parent, dreadNode);
342 }
343 
HandleAdd(const BaseNode & parent,BaseNode & expr,MPISel & iSel)344 Operand *HandleAdd(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
345 {
346     return iSel.SelectAdd(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
347                           *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
348 }
349 
HandleBior(const BaseNode & parent,BaseNode & expr,MPISel & iSel)350 Operand *HandleBior(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
351 {
352     return iSel.SelectBior(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
353                            *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
354 }
355 
HandleBxor(const BaseNode & parent,BaseNode & expr,MPISel & iSel)356 Operand *HandleBxor(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
357 {
358     return iSel.SelectBxor(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
359                            *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
360 }
361 
HandleSub(const BaseNode & parent,BaseNode & expr,MPISel & iSel)362 Operand *HandleSub(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
363 {
364     return iSel.SelectSub(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
365                           *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
366 }
367 
HandleNeg(const BaseNode & parent,BaseNode & expr,MPISel & iSel)368 Operand *HandleNeg(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
369 {
370     return iSel.SelectNeg(static_cast<UnaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)), parent);
371 }
372 
HandleDiv(const BaseNode & parent,BaseNode & expr,MPISel & iSel)373 Operand *HandleDiv(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
374 {
375     return iSel.SelectDiv(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
376                           *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
377 }
378 
HandleRem(const BaseNode & parent,BaseNode & expr,MPISel & iSel)379 Operand *HandleRem(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
380 {
381     return iSel.SelectRem(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
382                           *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
383 }
384 
HandleBand(const BaseNode & parent,BaseNode & expr,MPISel & iSel)385 Operand *HandleBand(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
386 {
387     return iSel.SelectBand(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
388                            *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
389 }
390 
HandleMpy(const BaseNode & parent,BaseNode & expr,MPISel & iSel)391 Operand *HandleMpy(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
392 {
393     return iSel.SelectMpy(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
394                           *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
395 }
396 
HandleConstStr(const BaseNode & parent,BaseNode & expr,MPISel & iSel)397 Operand *HandleConstStr(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
398 {
399     auto &constStrNode = static_cast<ConststrNode &>(expr);
400     return iSel.SelectStrLiteral(constStrNode);
401 }
402 
HandleTrunc(const BaseNode & parent,BaseNode & expr,MPISel & iSel)403 Operand *HandleTrunc(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
404 {
405     return iSel.SelectCvt(parent, static_cast<TypeCvtNode&>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)));
406 }
407 
HandleConstVal(const BaseNode & parent,BaseNode & expr,MPISel & iSel)408 Operand *HandleConstVal(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
409 {
410     auto &constValNode = static_cast<ConstvalNode &>(expr);
411     MIRConst *mirConst = constValNode.GetConstVal();
412     DEBUG_ASSERT(mirConst != nullptr, "get constval of constvalnode failed");
413     if (mirConst->GetKind() == kConstInt) {
414         auto *mirIntConst = safe_cast<MIRIntConst>(mirConst);
415         return iSel.SelectIntConst(*mirIntConst, constValNode.GetPrimType());
416     } else if (mirConst->GetKind() == kConstDoubleConst) {
417         auto *mirDoubleConst = safe_cast<MIRDoubleConst>(mirConst);
418         return iSel.SelectFloatingConst(*mirDoubleConst, constValNode.GetPrimType());
419     } else if (mirConst->GetKind() == kConstFloatConst) {
420         auto *mirFloatConst = safe_cast<MIRFloatConst>(mirConst);
421         return iSel.SelectFloatingConst(*mirFloatConst, constValNode.GetPrimType());
422     } else {
423         CHECK_FATAL(false, "NIY");
424     }
425     return nullptr;
426 }
427 
HandleRegread(const BaseNode & parent,BaseNode & expr,MPISel & iSel)428 Operand *HandleRegread(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
429 {
430     (void)parent;
431     auto &regReadNode = static_cast<RegreadNode &>(expr);
432     /* handle return Val */
433     if (regReadNode.GetRegIdx() == -kSregRetval0 || regReadNode.GetRegIdx() == -kSregRetval1) {
434         return &iSel.ProcessReturnReg(regReadNode.GetPrimType(), -(regReadNode.GetRegIdx()));
435     }
436     return iSel.SelectRegread(regReadNode);
437 }
438 
HandleIread(const BaseNode & parent,BaseNode & expr,MPISel & iSel)439 Operand *HandleIread(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
440 {
441     auto &ireadNode = static_cast<IreadNode &>(expr);
442     return iSel.SelectIread(parent, ireadNode);
443 }
HandleIreadoff(const BaseNode & parent,BaseNode & expr,MPISel & iSel)444 Operand *HandleIreadoff(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
445 {
446     auto &ireadNode = static_cast<IreadoffNode &>(expr);
447     return iSel.SelectIreadoff(parent, ireadNode);
448 }
449 
HandleBnot(const BaseNode & parent,BaseNode & expr,MPISel & iSel)450 Operand *HandleBnot(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
451 {
452     return iSel.SelectBnot(static_cast<UnaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)), parent);
453 }
454 
HandleLnot(const BaseNode & parent,BaseNode & expr,MPISel & iSel)455 Operand *HandleLnot(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
456 {
457     return iSel.SelectLnot(static_cast<UnaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)), parent);
458 }
459 
HandleEval(const StmtNode & stmt,MPISel & iSel)460 void HandleEval(const StmtNode &stmt, MPISel &iSel)
461 {
462     (void)iSel.HandleExpr(stmt, *static_cast<const UnaryStmtNode &>(stmt).Opnd(0));
463 }
464 
HandleDepositBits(const BaseNode & parent,BaseNode & expr,MPISel & iSel)465 Operand *HandleDepositBits(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
466 {
467     return iSel.SelectDepositBits(static_cast<DepositbitsNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
468                                   *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
469 }
470 
HandleCmp(const BaseNode & parent,BaseNode & expr,MPISel & iSel)471 Operand *HandleCmp(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
472 {
473     // fix opnd type before select insn
474     PrimType targetPtyp = parent.GetPrimType();
475     if (kOpcodeInfo.IsCompare(parent.GetOpCode())) {
476         targetPtyp = static_cast<const CompareNode &>(parent).GetOpndType();
477     } else if (kOpcodeInfo.IsTypeCvt(parent.GetOpCode())) {
478         targetPtyp = static_cast<const TypeCvtNode &>(parent).FromType();
479     }
480     if ((IsPrimitiveInteger(targetPtyp) || IsPrimitiveFloat(targetPtyp)) && targetPtyp != expr.GetPrimType()) {
481         expr.SetPrimType(targetPtyp);
482     }
483     return iSel.SelectCmpOp(static_cast<CompareNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
484                             *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
485 }
486 
HandleAbs(const BaseNode & parent,BaseNode & expr,MPISel & iSel)487 Operand *HandleAbs(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
488 {
489     return iSel.SelectAbs(static_cast<UnaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)));
490 }
491 
HandleAlloca(const BaseNode & parent,BaseNode & expr,MPISel & iSel)492 Operand *HandleAlloca(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
493 {
494     return iSel.SelectAlloca(static_cast<UnaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)));
495 }
496 
HandleCGArrayElemAdd(const BaseNode & parent,BaseNode & expr,MPISel & iSel)497 Operand *HandleCGArrayElemAdd(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
498 {
499     return iSel.SelectCGArrayElemAdd(static_cast<BinaryNode &>(expr), parent);
500 }
501 
HandleAsm(StmtNode & stmt,MPISel & iSel)502 void HandleAsm(StmtNode &stmt, MPISel &iSel)
503 {
504     iSel.SelectAsm(static_cast<AsmNode &>(stmt));
505 }
506 
HandleSelect(const BaseNode & parent,BaseNode & expr,MPISel & iSel)507 Operand *HandleSelect(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
508 {
509     /* 0,1,2 represent the first opnd and the second opnd and the third opnd of expr */
510     Operand &trueOpnd = *iSel.HandleExpr(expr, *expr.Opnd(1));
511     Operand &falseOpnd = *iSel.HandleExpr(expr, *expr.Opnd(2));
512     Operand &condOpnd = *iSel.HandleExpr(expr, *expr.Opnd(0));
513     if (condOpnd.IsImmediate()) {
514         return (static_cast<ImmOperand &>(condOpnd).GetValue() == 0) ? &falseOpnd : &trueOpnd;
515     }
516     return iSel.SelectSelect(static_cast<TernaryNode &>(expr), condOpnd, trueOpnd, falseOpnd, parent);
517 }
518 
HandleMin(const BaseNode & parent,BaseNode & expr,MPISel & iSel)519 Operand *HandleMin(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
520 {
521     return iSel.SelectMin(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
522                           *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
523 }
524 
HandleMax(const BaseNode & parent,BaseNode & expr,MPISel & iSel)525 Operand *HandleMax(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
526 {
527     return iSel.SelectMax(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
528                           *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
529 }
HandleRetype(const BaseNode & parent,BaseNode & expr,MPISel & iSel)530 Operand *HandleRetype(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
531 {
532     return iSel.SelectRetype(static_cast<TypeCvtNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)));
533 }
534 
HandleIntrinOp(const BaseNode & parent,BaseNode & expr,MPISel & iSel)535 Operand *HandleIntrinOp(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
536 {
537     auto &intrinsicopNode = static_cast<IntrinsicopNode &>(expr);
538     switch (intrinsicopNode.GetIntrinsic()) {
539         case INTRN_C_rev16_2:
540         case INTRN_C_rev_4:
541         case INTRN_C_rev_8:
542             return iSel.SelectBswap(intrinsicopNode, *iSel.HandleExpr(expr, *expr.Opnd(0)), parent);
543         case INTRN_C_clz32:
544         case INTRN_C_clz64:
545             return iSel.SelectCclz(intrinsicopNode, *iSel.HandleExpr(expr, *expr.Opnd(0)), parent);
546         case INTRN_C_ctz32:
547         case INTRN_C_ctz64:
548             return iSel.SelectCctz(intrinsicopNode, *iSel.HandleExpr(expr, *expr.Opnd(0)), parent);
549         case INTRN_C_exp:
550             return iSel.SelectCexp(intrinsicopNode, *iSel.HandleExpr(expr, *expr.Opnd(0)), parent);
551         default:
552             DEBUG_ASSERT(false, "NIY, unsupported intrinsicop.");
553             return nullptr;
554     }
555 }
556 
HandleSqrt(const BaseNode & parent,BaseNode & expr,MPISel & iSel)557 Operand *HandleSqrt(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
558 {
559     return iSel.SelectSqrt(static_cast<UnaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)), parent);
560 }
561 
562 using HandleStmtFactory = FunctionFactory<Opcode, void, StmtNode &, MPISel &>;
563 using HandleExprFactory = FunctionFactory<Opcode, maplebe::Operand *, const BaseNode &, BaseNode &, MPISel &>;
564 namespace isel {
InitHandleStmtFactory()565 void InitHandleStmtFactory()
566 {
567     RegisterFactoryFunction<HandleStmtFactory>(OP_label, HandleLabel);
568     RegisterFactoryFunction<HandleStmtFactory>(OP_dassign, HandleDassign);
569     RegisterFactoryFunction<HandleStmtFactory>(OP_dassignoff, HandleDassignoff);
570     RegisterFactoryFunction<HandleStmtFactory>(OP_iassign, HandleIassign);
571     RegisterFactoryFunction<HandleStmtFactory>(OP_iassignoff, HandleIassignoff);
572     RegisterFactoryFunction<HandleStmtFactory>(OP_regassign, HandleRegassign);
573     RegisterFactoryFunction<HandleStmtFactory>(OP_return, HandleReturn);
574     RegisterFactoryFunction<HandleStmtFactory>(OP_comment, HandleComment);
575     RegisterFactoryFunction<HandleStmtFactory>(OP_call, HandleCall);
576     RegisterFactoryFunction<HandleStmtFactory>(OP_icall, HandleIcall);
577     RegisterFactoryFunction<HandleStmtFactory>(OP_icallproto, HandleIcall);
578     RegisterFactoryFunction<HandleStmtFactory>(OP_goto, HandleGoto);
579     RegisterFactoryFunction<HandleStmtFactory>(OP_intrinsiccall, HandleIntrinCall);
580     RegisterFactoryFunction<HandleStmtFactory>(OP_intrinsiccallassigned, HandleIntrinCall);
581     RegisterFactoryFunction<HandleStmtFactory>(OP_rangegoto, HandleRangeGoto);
582     RegisterFactoryFunction<HandleStmtFactory>(OP_igoto, HandleIgoto);
583     RegisterFactoryFunction<HandleStmtFactory>(OP_brfalse, HandleCondbr);
584     RegisterFactoryFunction<HandleStmtFactory>(OP_brtrue, HandleCondbr);
585     RegisterFactoryFunction<HandleStmtFactory>(OP_eval, HandleEval);
586     RegisterFactoryFunction<HandleStmtFactory>(OP_asm, HandleAsm);
587 }
InitHandleExprFactory()588 void InitHandleExprFactory()
589 {
590     RegisterFactoryFunction<HandleExprFactory>(OP_dread, HandleDread);
591     RegisterFactoryFunction<HandleExprFactory>(OP_add, HandleAdd);
592     RegisterFactoryFunction<HandleExprFactory>(OP_sub, HandleSub);
593     RegisterFactoryFunction<HandleExprFactory>(OP_neg, HandleNeg);
594     RegisterFactoryFunction<HandleExprFactory>(OP_mul, HandleMpy);
595     RegisterFactoryFunction<HandleExprFactory>(OP_constval, HandleConstVal);
596     RegisterFactoryFunction<HandleExprFactory>(OP_regread, HandleRegread);
597     RegisterFactoryFunction<HandleExprFactory>(OP_addrof, HandleAddrof);
598     RegisterFactoryFunction<HandleExprFactory>(OP_addroffunc, HandleAddroffunc);
599     RegisterFactoryFunction<HandleExprFactory>(OP_addroflabel, HandleAddrofLabel);
600     RegisterFactoryFunction<HandleExprFactory>(OP_shl, HandleShift);
601     RegisterFactoryFunction<HandleExprFactory>(OP_lshr, HandleShift);
602     RegisterFactoryFunction<HandleExprFactory>(OP_ashr, HandleShift);
603     RegisterFactoryFunction<HandleExprFactory>(OP_cvt, HandleCvt);
604     RegisterFactoryFunction<HandleExprFactory>(OP_zext, HandleExtractBits);
605     RegisterFactoryFunction<HandleExprFactory>(OP_sext, HandleExtractBits);
606     RegisterFactoryFunction<HandleExprFactory>(OP_extractbits, HandleExtractBits);
607     RegisterFactoryFunction<HandleExprFactory>(OP_depositbits, HandleDepositBits);
608     RegisterFactoryFunction<HandleExprFactory>(OP_band, HandleBand);
609     RegisterFactoryFunction<HandleExprFactory>(OP_bior, HandleBior);
610     RegisterFactoryFunction<HandleExprFactory>(OP_bxor, HandleBxor);
611     RegisterFactoryFunction<HandleExprFactory>(OP_iread, HandleIread);
612     RegisterFactoryFunction<HandleExprFactory>(OP_ireadoff, HandleIreadoff);
613     RegisterFactoryFunction<HandleExprFactory>(OP_bnot, HandleBnot);
614     RegisterFactoryFunction<HandleExprFactory>(OP_lnot, HandleLnot);
615     RegisterFactoryFunction<HandleExprFactory>(OP_div, HandleDiv);
616     RegisterFactoryFunction<HandleExprFactory>(OP_rem, HandleRem);
617     RegisterFactoryFunction<HandleExprFactory>(OP_conststr, HandleConstStr);
618     RegisterFactoryFunction<HandleExprFactory>(OP_le, HandleCmp);
619     RegisterFactoryFunction<HandleExprFactory>(OP_ge, HandleCmp);
620     RegisterFactoryFunction<HandleExprFactory>(OP_gt, HandleCmp);
621     RegisterFactoryFunction<HandleExprFactory>(OP_lt, HandleCmp);
622     RegisterFactoryFunction<HandleExprFactory>(OP_ne, HandleCmp);
623     RegisterFactoryFunction<HandleExprFactory>(OP_eq, HandleCmp);
624     RegisterFactoryFunction<HandleExprFactory>(OP_abs, HandleAbs);
625     RegisterFactoryFunction<HandleExprFactory>(OP_alloca, HandleAlloca);
626     RegisterFactoryFunction<HandleExprFactory>(OP_CG_array_elem_add, HandleCGArrayElemAdd);
627     RegisterFactoryFunction<HandleExprFactory>(OP_select, HandleSelect);
628     RegisterFactoryFunction<HandleExprFactory>(OP_min, HandleMin);
629     RegisterFactoryFunction<HandleExprFactory>(OP_max, HandleMax);
630     RegisterFactoryFunction<HandleExprFactory>(OP_retype, HandleRetype);
631     RegisterFactoryFunction<HandleExprFactory>(OP_trunc, HandleTrunc);
632     RegisterFactoryFunction<HandleExprFactory>(OP_intrinsicop, HandleIntrinOp);
633     RegisterFactoryFunction<HandleExprFactory>(OP_sqrt, HandleSqrt);
634 }
635 }  // namespace isel
636 
HandleExpr(const BaseNode & parent,BaseNode & expr)637 Operand *MPISel::HandleExpr(const BaseNode &parent, BaseNode &expr)
638 {
639     auto function = CreateProductFunction<HandleExprFactory>(expr.GetOpCode());
640     CHECK_FATAL(function != nullptr, "unsupported opCode in HandleExpr()");
641     Operand *opnd = function(parent, expr, *this);
642     return opnd;
643 }
644 
doMPIS()645 void MPISel::doMPIS()
646 {
647     isel::InitHandleStmtFactory();
648     isel::InitHandleExprFactory();
649     StmtNode *secondStmt = HandleFuncEntry();
650     for (StmtNode *stmt = secondStmt; stmt != nullptr; stmt = stmt->GetNext()) {
651         auto function = CreateProductFunction<HandleStmtFactory>(stmt->GetOpCode());
652         CHECK_FATAL(function != nullptr, "unsupported opCode or has been lowered before");
653         function(*stmt, *this);
654     }
655     HandleFuncExit();
656 }
657 
GetIntegerPrimTypeFromSize(bool isSigned,uint32 bitSize)658 PrimType MPISel::GetIntegerPrimTypeFromSize(bool isSigned, uint32 bitSize)
659 {
660     static constexpr std::array<PrimType, kBitIndexEnd> signedPrimType = {PTY_i8, PTY_i16, PTY_i32, PTY_i64};
661     static constexpr std::array<PrimType, kBitIndexEnd> unsignedPrimType = {PTY_u8, PTY_u16, PTY_u32, PTY_u64};
662     BitIndex index = GetBitIndex(bitSize);
663     return isSigned ? signedPrimType[index] : unsignedPrimType[index];
664 }
665 
SelectCallCommon(StmtNode & stmt,const MPISel & iSel)666 void MPISel::SelectCallCommon(StmtNode &stmt, const MPISel &iSel)
667 {
668     CGFunc *cgFunc = iSel.GetCurFunc();
669     if (cgFunc->GetCurBB()->GetKind() != BB::kBBFallthru) {
670         cgFunc->SetCurBB(*cgFunc->StartNewBB(stmt));
671     }
672     StmtNode *prevStmt = stmt.GetPrev();
673     if (prevStmt == nullptr || prevStmt->GetOpCode() != OP_catch) {
674         return;
675     }
676     if ((stmt.GetNext() != nullptr) && (stmt.GetNext()->GetOpCode() == OP_label)) {
677         cgFunc->SetCurBB(*cgFunc->StartNewBBImpl(true, stmt));
678     }
679 }
680 
SelectBasicOp(Operand & resOpnd,Operand & opnd0,Operand & opnd1,MOperator mOp,PrimType primType)681 void MPISel::SelectBasicOp(Operand &resOpnd, Operand &opnd0, Operand &opnd1, MOperator mOp, PrimType primType)
682 {
683     RegOperand &firstOpnd = SelectCopy2Reg(opnd0, primType);
684     RegOperand &secondOpnd = SelectCopy2Reg(opnd1, primType);
685     Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mOp, InsnDesc::GetAbstractId(mOp));
686     (void)insn.AddOpndChain(resOpnd).AddOpndChain(firstOpnd).AddOpndChain(secondOpnd);
687     cgFunc->GetCurBB()->AppendInsn(insn);
688 }
689 
GetFieldIdAndMirTypeFromMirNode(const BaseNode & node)690 std::pair<FieldID, MIRType *> MPISel::GetFieldIdAndMirTypeFromMirNode(const BaseNode &node)
691 {
692     FieldID fieldId = 0;
693     MIRType *mirType = nullptr;
694     if (node.GetOpCode() == maple::OP_iread) {
695         /* mirType stored in an addr. */
696         auto &iread = static_cast<const IreadNode &>(node);
697         fieldId = iread.GetFieldID();
698         MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(iread.GetTyIdx());
699         MIRPtrType *pointerType = static_cast<MIRPtrType *>(type);
700         DEBUG_ASSERT(pointerType != nullptr, "expect a pointer type at iread node");
701         mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(pointerType->GetPointedTyIdx());
702         if (mirType->GetKind() == kTypeArray) {
703             MIRArrayType *arrayType = static_cast<MIRArrayType *>(mirType);
704             mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(arrayType->GetElemTyIdx());
705         }
706     } else if (node.GetOpCode() == maple::OP_dassign) {
707         /* mirSymbol */
708         auto &dassign = static_cast<const DassignNode &>(node);
709         fieldId = dassign.GetFieldID();
710         MIRSymbol *symbol = cgFunc->GetFunction().GetLocalOrGlobalSymbol(dassign.GetStIdx());
711         mirType = symbol->GetType();
712     } else if (node.GetOpCode() == maple::OP_dread) {
713         /* mirSymbol */
714         auto &dread = static_cast<const AddrofNode &>(node);
715         fieldId = dread.GetFieldID();
716         MIRSymbol *symbol = cgFunc->GetFunction().GetLocalOrGlobalSymbol(dread.GetStIdx());
717         mirType = symbol->GetType();
718     } else if (node.GetOpCode() == maple::OP_iassign) {
719         auto &iassign = static_cast<const IassignNode &>(node);
720         fieldId = iassign.GetFieldID();
721         AddrofNode &addrofNode = static_cast<AddrofNode &>(iassign.GetAddrExprBase());
722         MIRType *iassignMirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(iassign.GetTyIdx());
723         MIRPtrType *pointerType = nullptr;
724         if (iassignMirType->GetPrimType() == PTY_agg) {
725             MIRSymbol *addrSym = cgFunc->GetMirModule().CurFunction()->GetLocalOrGlobalSymbol(addrofNode.GetStIdx());
726             MIRType *addrMirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(addrSym->GetTyIdx());
727             addrMirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(addrMirType->GetTypeIndex());
728             DEBUG_ASSERT(addrMirType->GetKind() == kTypePointer, "non-pointer");
729             pointerType = static_cast<MIRPtrType *>(addrMirType);
730         } else {
731             DEBUG_ASSERT(iassignMirType->GetKind() == kTypePointer, "non-pointer");
732             pointerType = static_cast<MIRPtrType *>(iassignMirType);
733         }
734         mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(pointerType->GetPointedTyIdx());
735     } else {
736         CHECK_FATAL(false, "unsupported OpCode");
737     }
738     return {fieldId, mirType};
739 }
740 
GetMirTypeInfoFormFieldIdAndMirType(FieldID fieldId,MIRType * mirType)741 MirTypeInfo MPISel::GetMirTypeInfoFormFieldIdAndMirType(FieldID fieldId, MIRType *mirType)
742 {
743     MirTypeInfo mirTypeInfo;
744     /* fixup primType and offset */
745     if (fieldId != 0) {
746         DEBUG_ASSERT((mirType->IsMIRStructType() || mirType->IsMIRUnionType()), "non-structure");
747         MIRStructType *structType = static_cast<MIRStructType *>(mirType);
748         mirType = structType->GetFieldType(fieldId);
749         mirTypeInfo.offset = static_cast<uint32>(cgFunc->GetBecommon().GetFieldOffset(*structType, fieldId).first);
750     }
751     mirTypeInfo.primType = mirType->GetPrimType();
752     // aggSize for AggType
753     if (mirTypeInfo.primType == maple::PTY_agg) {
754         mirTypeInfo.size = cgFunc->GetBecommon().GetTypeSize(mirType->GetTypeIndex());
755     }
756     return mirTypeInfo;
757 }
758 
GetMirTypeInfoFromMirNode(const BaseNode & node)759 MirTypeInfo MPISel::GetMirTypeInfoFromMirNode(const BaseNode &node)
760 {
761     auto [fieldId, mirType] = GetFieldIdAndMirTypeFromMirNode(node);
762     return GetMirTypeInfoFormFieldIdAndMirType(fieldId, mirType);
763 }
764 
SelectDassign(const DassignNode & stmt,Operand & opndRhs)765 void MPISel::SelectDassign(const DassignNode &stmt, Operand &opndRhs)
766 {
767     /* mirSymbol info */
768     MIRSymbol *symbol = cgFunc->GetFunction().GetLocalOrGlobalSymbol(stmt.GetStIdx());
769     MirTypeInfo symbolInfo = GetMirTypeInfoFromMirNode(stmt);
770     /* Get symbol location */
771     MemOperand &symbolMem = GetOrCreateMemOpndFromSymbol(*symbol, stmt.GetFieldID());
772     /* rhs mirType info */
773     PrimType rhsType = stmt.GetRHS()->GetPrimType();
774     /* Generate Insn */
775     if (rhsType == PTY_agg) {
776         /* Agg Type */
777         SelectAggDassign(symbolInfo, symbolMem, opndRhs);
778         return;
779     }
780     PrimType memType = symbolInfo.primType;
781     if (memType == PTY_agg) {
782         memType = PTY_a64;
783     }
784     SelectCopy(symbolMem, opndRhs, memType, rhsType);
785     if (rhsType == PTY_ref) {
786         cgFunc->AddReferenceStackSlot(symbolMem.GetOffsetImmediate()->GetOffsetValue());
787     }
788 
789     return;
790 }
791 
SelectDassignoff(DassignoffNode & stmt,Operand & opnd0)792 void MPISel::SelectDassignoff(DassignoffNode &stmt, Operand &opnd0)
793 {
794     MIRSymbol *symbol = cgFunc->GetFunction().GetLocalOrGlobalSymbol(stmt.stIdx);
795     PrimType primType = stmt.GetPrimType();
796     uint32 bitSize = GetPrimTypeBitSize(primType);
797     MemOperand &memOpnd = GetOrCreateMemOpndFromSymbol(*symbol, bitSize, stmt.offset);
798 
799     SelectCopy(memOpnd, opnd0, primType);
800 }
801 
SelectIassign(const IassignNode & stmt,Operand & opndAddr,Operand & opndRhs)802 void MPISel::SelectIassign(const IassignNode &stmt, Operand &opndAddr, Operand &opndRhs)
803 {
804     /* mirSymbol info */
805     MirTypeInfo symbolInfo = GetMirTypeInfoFromMirNode(stmt);
806     /* handle Lhs, generate (%Rxx) via Rxx*/
807     PrimType memType = symbolInfo.primType;
808     if (memType == PTY_agg) {
809         memType = PTY_a64;
810     }
811     RegOperand &lhsBaseOpnd = SelectCopy2Reg(opndAddr, stmt.Opnd(0)->GetPrimType());
812     MemOperand &lhsMemOpnd =
813         cgFunc->GetOpndBuilder()->CreateMem(lhsBaseOpnd, symbolInfo.offset, GetPrimTypeBitSize(memType));
814     /* handle Rhs, get R## from Rhs */
815     PrimType rhsType = stmt.GetRHS()->GetPrimType();
816     /* mov %R##, (%Rxx) */
817     SelectCopy(lhsMemOpnd, opndRhs, memType, rhsType);
818 }
819 
SelectIassignoff(const IassignoffNode & stmt)820 void MPISel::SelectIassignoff(const IassignoffNode &stmt)
821 {
822     Operand *addr = HandleExpr(stmt, *stmt.Opnd(0));
823     DEBUG_ASSERT(addr != nullptr, "null ptr check");
824     Operand *rhs = HandleExpr(stmt, *stmt.Opnd(1));
825     DEBUG_ASSERT(rhs != nullptr, "null ptr check");
826 
827     int32 offset = stmt.GetOffset();
828     PrimType primType = stmt.GetPrimType();
829     uint32 bitSize = GetPrimTypeBitSize(primType);
830     RegOperand &addrReg = SelectCopy2Reg(*addr, PTY_a64);
831     RegOperand &rhsReg = SelectCopy2Reg(*rhs, primType);
832 
833     MemOperand &memOpnd = cgFunc->GetOpndBuilder()->CreateMem(addrReg, offset, bitSize);
834     SelectCopy(memOpnd, rhsReg, primType);
835 }
836 
SelectIntConst(const MIRIntConst & intConst,PrimType primType)837 ImmOperand *MPISel::SelectIntConst(const MIRIntConst &intConst, PrimType primType)
838 {
839     return &cgFunc->GetOpndBuilder()->CreateImm(GetPrimTypeBitSize(primType), intConst.GetExtValue());
840 }
841 
SelectShift(const BinaryNode & node,Operand & opnd0,Operand & opnd1,const BaseNode & parent)842 Operand *MPISel::SelectShift(const BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent)
843 {
844     PrimType primType = node.GetPrimType();
845     RegOperand *resOpnd = nullptr;
846     Opcode opcode = node.GetOpCode();
847 
848     if (IsPrimitiveInteger(primType)) {
849         resOpnd =
850             &(cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType)));
851         RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, primType, node.Opnd(0)->GetPrimType());
852         SelectShift(*resOpnd, regOpnd0, opnd1, opcode, primType, node.Opnd(1)->GetPrimType());
853     } else {
854         CHECK_FATAL(false, "NIY vector cvt");
855     }
856     return resOpnd;
857 }
858 
SelectShift(Operand & resOpnd,Operand & opnd0,Operand & opnd1,Opcode shiftDirect,PrimType opnd0Type,PrimType opnd1Type)859 void MPISel::SelectShift(Operand &resOpnd, Operand &opnd0, Operand &opnd1, Opcode shiftDirect, PrimType opnd0Type,
860                          PrimType opnd1Type)
861 {
862     if (opnd1.IsIntImmediate() && static_cast<ImmOperand &>(opnd1).GetValue() == 0) {
863         SelectCopy(resOpnd, opnd0, opnd0Type);
864         return;
865     }
866 
867     uint32 dsize = GetPrimTypeBitSize(opnd0Type);
868     MOperator mOp = abstract::MOP_undef;
869     if (shiftDirect == OP_shl) {
870         const static auto fastShlMappingFunc = DEF_MOPERATOR_MAPPING_FUNC(shl);
871         mOp = fastShlMappingFunc(dsize);
872     } else if (shiftDirect == OP_ashr) {
873         const static auto fastAshrMappingFunc = DEF_MOPERATOR_MAPPING_FUNC(ashr);
874         mOp = fastAshrMappingFunc(dsize);
875     } else if (shiftDirect == OP_lshr) {
876         const static auto fastLshrMappingFunc = DEF_MOPERATOR_MAPPING_FUNC(lshr);
877         mOp = fastLshrMappingFunc(dsize);
878     } else {
879         CHECK_FATAL(false, "NIY, Not support shiftdirect case");
880     }
881     RegOperand &firstOpnd = SelectCopy2Reg(opnd0, opnd0Type);
882     RegOperand &secondOpnd = SelectCopy2Reg(opnd1, opnd1Type);
883     Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mOp, InsnDesc::GetAbstractId(mOp));
884     insn.AddOpndChain(resOpnd).AddOpndChain(firstOpnd).AddOpndChain(secondOpnd);
885     cgFunc->GetCurBB()->AppendInsn(insn);
886 }
887 
SelectRegassign(RegassignNode & stmt,Operand & opnd0)888 void MPISel::SelectRegassign(RegassignNode &stmt, Operand &opnd0)
889 {
890     PrimType rhsType = stmt.Opnd(0)->GetPrimType();
891     PregIdx pregIdx = stmt.GetRegIdx();
892     PrimType regType = stmt.GetPrimType();
893     RegOperand &regOpnd =
894         cgFunc->GetOpndBuilder()->CreateVReg(cgFunc->GetVirtualRegNOFromPseudoRegIdx(pregIdx),
895                                              GetPrimTypeBitSize(regType), cgFunc->GetRegTyFromPrimTy(regType));
896     SelectCopy(regOpnd, opnd0, regType, rhsType);
897     if (stmt.GetPrimType() == PTY_ref) {
898         regOpnd.SetIsReference(true);
899         cgFunc->AddReferenceReg(regOpnd.GetRegisterNumber());
900     }
901     if (pregIdx > 0) {
902         // special MIRPreg is not supported
903         cgFunc->SetPregIdx2Opnd(pregIdx, regOpnd);
904     }
905     const auto &derived2BaseRef = cgFunc->GetFunction().GetDerived2BaseRef();
906     auto itr = derived2BaseRef.find(pregIdx);
907     if (itr != derived2BaseRef.end()) {
908         auto *opnd = cgFunc->GetOpndFromPregIdx(itr->first);
909         CHECK_FATAL(opnd != nullptr, "pregIdx has not been assigned Operand");
910         auto &derivedRegOpnd = static_cast<RegOperand &>(*opnd);
911         opnd = cgFunc->GetOpndFromPregIdx(itr->second);
912         CHECK_FATAL(opnd != nullptr, "pregIdx has not been assigned Operand");
913         auto &baseRegOpnd = static_cast<RegOperand &>(*opnd);
914         derivedRegOpnd.SetBaseRefOpnd(baseRegOpnd);
915     }
916     if ((Globals::GetInstance()->GetOptimLevel() == CGOptions::kLevel0) && (pregIdx >= 0)) {
917         const SymbolAlloc *symLoc = cgFunc->GetMemlayout()->GetSpillLocOfPseduoRegister(pregIdx);
918         int64 offset = static_cast<int64>(cgFunc->GetBaseOffset(*symLoc));
919         MIRPreg *preg = cgFunc->GetFunction().GetPregTab()->PregFromPregIdx(pregIdx);
920         uint32 bitLen = GetPrimTypeSize(preg->GetPrimType()) * kBitsPerByte;
921         RegOperand &base = GetTargetBasicPointer(PTY_u64);
922         MemOperand *dest = &cgFunc->GetOpndBuilder()->CreateMem(base, offset, bitLen);
923         SelectCopy(*dest, regOpnd, preg->GetPrimType(), regType);
924     }
925 }
926 
SelectRegread(RegreadNode & expr)927 RegOperand *MPISel::SelectRegread(RegreadNode &expr)
928 {
929     PregIdx pregIdx = expr.GetRegIdx();
930     PrimType rhsType = expr.GetPrimType();
931     if (pregIdx < 0) {
932         return &SelectSpecialRegread(pregIdx, rhsType);
933     }
934 
935     RegOperand &reg = cgFunc->GetOpndBuilder()->CreateVReg(cgFunc->GetVirtualRegNOFromPseudoRegIdx(pregIdx),
936                                                            GetPrimTypeSize(rhsType) * kBitsPerByte,
937                                                            cgFunc->GetRegTyFromPrimTy(rhsType));
938     if (cgFunc->GetOpndFromPregIdx(pregIdx) == nullptr) {
939         cgFunc->SetPregIdx2Opnd(pregIdx, reg);
940     }
941     if (expr.GetPrimType() == maple::PTY_ref) {
942         reg.SetIsReference(true);
943         cgFunc->AddReferenceReg(reg.GetRegisterNumber());
944     }
945     if (Globals::GetInstance()->GetOptimLevel() == CGOptions::kLevel0) {
946         const SymbolAlloc *symLoc = cgFunc->GetMemlayout()->GetSpillLocOfPseduoRegister(pregIdx);
947         int64 offset = static_cast<int64>(cgFunc->GetBaseOffset(*symLoc));
948         MIRPreg *preg = cgFunc->GetFunction().GetPregTab()->PregFromPregIdx(pregIdx);
949         uint32 bitLen = GetPrimTypeSize(preg->GetPrimType()) * kBitsPerByte;
950         RegOperand &base = GetTargetBasicPointer(PTY_u64);
951         MemOperand *src = &cgFunc->GetOpndBuilder()->CreateMem(base, offset, bitLen);
952         SelectCopy(reg, *src, rhsType, preg->GetPrimType());
953     }
954     return &reg;
955 }
956 
SelectDread(const BaseNode & parent,const AddrofNode & expr)957 Operand *MPISel::SelectDread(const BaseNode &parent, const AddrofNode &expr)
958 {
959     /* get mirSymbol info*/
960     MIRSymbol *symbol = cgFunc->GetFunction().GetLocalOrGlobalSymbol(expr.GetStIdx());
961     MirTypeInfo symbolInfo = GetMirTypeInfoFromMirNode(expr);
962     PrimType symbolType = symbolInfo.primType;
963     /* Get symbol location */
964     MemOperand &symbolMem = GetOrCreateMemOpndFromSymbol(*symbol, expr.GetFieldID());
965     PrimType primType = expr.GetPrimType();
966     if (primType == PTY_ref) {
967         cgFunc->AddReferenceStackSlot(symbolMem.GetOffsetImmediate()->GetOffsetValue());
968     }
969 
970     /* for AggType, return it's location in stack. */
971     if (symbolType == maple::PTY_agg) {
972         CHECK_FATAL(primType == maple::PTY_agg, "NIY");
973         return &symbolMem;
974     }
975     /* for BasicType, load symbolVal to register. */
976     RegOperand &regOpnd =
977         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
978     if (primType == PTY_ref) {
979         regOpnd.SetIsReference(true);
980         cgFunc->AddReferenceReg(regOpnd.GetRegisterNumber());
981     }
982     /* Generate Insn */
983     SelectCopy(regOpnd, symbolMem, primType, symbolType);
984     return &regOpnd;
985 }
986 
SelectAdd(const BinaryNode & node,Operand & opnd0,Operand & opnd1,const BaseNode & parent)987 Operand *MPISel::SelectAdd(const BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent)
988 {
989     PrimType primType = node.GetPrimType();
990     RegOperand &resReg =
991         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
992     RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, primType, node.Opnd(0)->GetPrimType());
993     RegOperand &regOpnd1 = SelectCopy2Reg(opnd1, primType, node.Opnd(1)->GetPrimType());
994     SelectAdd(resReg, regOpnd0, regOpnd1, primType);
995     return &resReg;
996 }
997 
SelectBand(const BinaryNode & node,Operand & opnd0,Operand & opnd1,const BaseNode & parent)998 Operand *MPISel::SelectBand(const BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent)
999 {
1000     PrimType primType = node.GetPrimType();
1001     RegOperand &resReg =
1002         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
1003     RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, primType, node.Opnd(0)->GetPrimType());
1004     RegOperand &regOpnd1 = SelectCopy2Reg(opnd1, primType, node.Opnd(1)->GetPrimType());
1005     SelectBand(resReg, regOpnd0, regOpnd1, primType);
1006     return &resReg;
1007 }
1008 
SelectSub(const BinaryNode & node,Operand & opnd0,Operand & opnd1,const BaseNode & parent)1009 Operand *MPISel::SelectSub(const BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent)
1010 {
1011     PrimType primType = node.GetPrimType();
1012     RegOperand &resOpnd =
1013         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
1014     RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, primType, node.Opnd(0)->GetPrimType());
1015     RegOperand &regOpnd1 = SelectCopy2Reg(opnd1, primType, node.Opnd(1)->GetPrimType());
1016     SelectSub(resOpnd, regOpnd0, regOpnd1, primType);
1017     return &resOpnd;
1018 }
1019 
SelectExtractbits(RegOperand & resOpnd,RegOperand & opnd0,uint8 bitOffset,uint8 bitSize,PrimType primType)1020 void MPISel::SelectExtractbits(RegOperand &resOpnd, RegOperand &opnd0, uint8 bitOffset, uint8 bitSize,
1021                                PrimType primType)
1022 {
1023     uint32 primBitSize = GetPrimTypeBitSize(primType);
1024     bool isSigned = IsSignedInteger(primType);
1025     if (bitOffset == 0 && !isSigned) {
1026         /*
1027          * resOpnd = opnd0 & ((1 << bitSize) - 1)
1028          */
1029         ImmOperand &imm = cgFunc->GetOpndBuilder()->CreateImm(primBitSize, (static_cast<int64>(1) << bitSize) - 1);
1030         SelectBand(resOpnd, opnd0, imm, primType);
1031     } else {
1032         /*
1033          * tmpOpnd = opnd0 << (primBitSize - bitSize - bitOffset)
1034          * resOpnd = tmpOpnd >> (primBitSize - bitSize)
1035          * if signed : use sar; else use shr
1036          */
1037         RegOperand &tmpOpnd =
1038             cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
1039         ImmOperand &imm1Opnd = cgFunc->GetOpndBuilder()->CreateImm(primBitSize, primBitSize - bitSize - bitOffset);
1040         SelectShift(tmpOpnd, opnd0, imm1Opnd, OP_shl, primType, primType);
1041         Opcode opcode = isSigned ? OP_ashr : OP_lshr;
1042         ImmOperand &imm2Opnd = cgFunc->GetOpndBuilder()->CreateImm(primBitSize, primBitSize - bitSize);
1043         SelectShift(resOpnd, tmpOpnd, imm2Opnd, opcode, primType, primType);
1044     }
1045 }
1046 
SelectExtractbits(const BaseNode & parent,const ExtractbitsNode & node,Operand & opnd0)1047 Operand *MPISel::SelectExtractbits(const BaseNode &parent, const ExtractbitsNode &node, Operand &opnd0)
1048 {
1049     PrimType fromType = node.Opnd(0)->GetPrimType();
1050     PrimType toType = node.GetPrimType();
1051     uint8 bitSize = node.GetBitsSize();
1052     RegOperand &resOpnd =
1053         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(toType), cgFunc->GetRegTyFromPrimTy(toType));
1054     if (IsPrimitiveInteger(toType)) {
1055         // OP_extractbits or bitSize < 8-bit or bitSize is not pow of 2
1056         if (node.GetOpCode() == OP_extractbits || bitSize < k8BitSize || (bitSize & (bitSize - 1)) != 0) {
1057             SelectCopy(resOpnd, opnd0, toType, fromType);
1058             SelectExtractbits(resOpnd, resOpnd, node.GetBitsOffset(), bitSize, toType);
1059         } else {
1060             PrimType opndType = GetIntegerPrimTypeFromSize(node.GetOpCode() == OP_sext, bitSize);
1061             RegOperand &tmpRegOpnd = SelectCopy2Reg(opnd0, opndType, fromType);
1062             SelectIntCvt(resOpnd, tmpRegOpnd, toType, opndType);
1063         }
1064     } else {
1065         CHECK_FATAL(false, "NIY vector cvt");
1066     }
1067     return &resOpnd;
1068 }
1069 
SelectCvt(const BaseNode & parent,const TypeCvtNode & node,Operand & opnd0)1070 Operand *MPISel::SelectCvt(const BaseNode &parent, const TypeCvtNode &node, Operand &opnd0)
1071 {
1072     PrimType fromType = node.Opnd(0)->GetPrimType();
1073     PrimType toType = node.GetPrimType();
1074     if (fromType == toType) {
1075         return &opnd0;
1076     }
1077     RegOperand *resOpnd =
1078         &cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(toType), cgFunc->GetRegTyFromPrimTy(toType));
1079     if (IsPrimitiveInteger(toType) && IsPrimitiveInteger(fromType)) {
1080         SelectIntCvt(*resOpnd, opnd0, toType, fromType);
1081     } else if (IsPrimitiveFloat(toType) && IsPrimitiveInteger(fromType)) {
1082         SelectCvtInt2Float(*resOpnd, opnd0, toType, fromType);
1083     } else if (IsPrimitiveFloat(toType) && IsPrimitiveFloat(fromType)) {
1084         SelectFloatCvt(*resOpnd, opnd0, toType, fromType);
1085     } else if (IsPrimitiveInteger(toType) && IsPrimitiveFloat(fromType)) {
1086         SelectCvtFloat2Int(*resOpnd, opnd0, toType, fromType);
1087     } else {
1088         CHECK_FATAL(false, "NIY cvt");
1089     }
1090     return resOpnd;
1091 }
1092 
SelectCvtFloat2Int(RegOperand & resOpnd,Operand & opnd0,PrimType toType,PrimType fromType)1093 void MPISel::SelectCvtFloat2Int(RegOperand &resOpnd, Operand &opnd0, PrimType toType, PrimType fromType)
1094 {
1095     uint32 toSize = GetPrimTypeBitSize(toType);
1096     bool isSigned = !IsPrimitiveUnsigned(toType);
1097     PrimType newToType = toType;
1098     // cvt f64/32 -> u16 / u8 -> cvt f u32 + cvt u32 -> u8
1099     if (toSize < k32BitSize) {
1100         newToType = isSigned ? PTY_i32 : PTY_u32;
1101     }
1102     uint32 newToSize = GetPrimTypeBitSize(newToType);
1103     RegOperand &tmpFloatOpnd = cgFunc->GetOpndBuilder()->CreateVReg(newToSize, kRegTyFloat);
1104     SelectFloatCvt(tmpFloatOpnd, opnd0, newToType, fromType);
1105     MOperator mOp = abstract::MOP_undef;
1106     if (newToSize == k32BitSize) {
1107         mOp = isSigned ? abstract::MOP_cvt_rf_i32 : abstract::MOP_cvt_rf_u32;
1108     } else if (newToSize == k64BitSize) {
1109         mOp = isSigned ? abstract::MOP_cvt_rf_i64 : abstract::MOP_cvt_rf_u64;
1110     } else {
1111         CHECK_FATAL(false, "niy");
1112     }
1113     Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mOp, InsnDesc::GetAbstractId(mOp));
1114     if (toSize == newToSize) {
1115         (void)insn.AddOpndChain(resOpnd).AddOpndChain(tmpFloatOpnd);
1116     } else if (toSize < newToSize) {
1117         RegOperand &tmpIntOpnd = cgFunc->GetOpndBuilder()->CreateVReg(newToSize, kRegTyFloat);
1118         (void)insn.AddOpndChain(tmpIntOpnd).AddOpndChain(tmpFloatOpnd);
1119         SelectIntCvt(resOpnd, tmpIntOpnd, toType, newToType);
1120     }
1121     cgFunc->GetCurBB()->AppendInsn(insn);
1122 }
1123 
SelectCvtInt2Float(RegOperand & resOpnd,Operand & opnd0,PrimType toType,PrimType fromType)1124 void MPISel::SelectCvtInt2Float(RegOperand &resOpnd, Operand &opnd0, PrimType toType, PrimType fromType)
1125 {
1126     uint32 fromSize = GetPrimTypeBitSize(fromType);
1127     bool isSigned = !IsPrimitiveUnsigned(fromType);
1128     MOperator mOp = abstract::MOP_undef;
1129     PrimType newFromType = PTY_begin;
1130     if (fromSize == k32BitSize) {
1131         mOp = isSigned ? abstract::MOP_cvt_fr_i32 : abstract::MOP_cvt_fr_u32;
1132         newFromType = PTY_f64;
1133     } else if (fromSize == k64BitSize) {
1134         mOp = isSigned ? abstract::MOP_cvt_fr_i64 : abstract::MOP_cvt_fr_u64;
1135         newFromType = PTY_f64;
1136     } else {
1137         CHECK_FATAL(false, "niy");
1138     }
1139     RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, fromType);
1140     RegOperand &tmpFloatOpnd =
1141         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(newFromType), cgFunc->GetRegTyFromPrimTy(newFromType));
1142     Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mOp, InsnDesc::GetAbstractId(mOp));
1143     (void)insn.AddOpndChain(tmpFloatOpnd).AddOpndChain(regOpnd0);
1144     cgFunc->GetCurBB()->AppendInsn(insn);
1145     SelectFloatCvt(resOpnd, tmpFloatOpnd, toType, newFromType);
1146 }
1147 
SelectIntCvt(RegOperand & resOpnd,Operand & opnd0,PrimType toType,PrimType fromType)1148 void MPISel::SelectIntCvt(RegOperand &resOpnd, Operand &opnd0, PrimType toType, PrimType fromType)
1149 {
1150     uint32 fromSize = GetPrimTypeBitSize(fromType);
1151     uint32 toSize = GetPrimTypeBitSize(toType);
1152     /*
1153      * It is redundancy to insert "nop" casts (unsigned 32 -> singed 32) in abstract CG IR
1154      * The signedness of operands would be shown in the expression.
1155      */
1156     RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, fromType);
1157     if (toSize <= fromSize) {
1158         resOpnd = cgFunc->GetOpndBuilder()->CreateVReg(regOpnd0.GetRegisterNumber(), GetPrimTypeBitSize(toType),
1159                                                        cgFunc->GetRegTyFromPrimTy(toType));
1160         return;
1161     }
1162     bool isSigned = !IsPrimitiveUnsigned(fromType);
1163     MOperator mOp = GetFastCvtMopI(fromSize, toSize, isSigned);
1164     Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mOp, InsnDesc::GetAbstractId(mOp));
1165     (void)insn.AddOpndChain(resOpnd).AddOpndChain(regOpnd0);
1166     cgFunc->GetCurBB()->AppendInsn(insn);
1167     return;
1168 }
1169 
SelectFloatCvt(RegOperand & resOpnd,Operand & opnd0,PrimType toType,PrimType fromType)1170 void MPISel::SelectFloatCvt(RegOperand &resOpnd, Operand &opnd0, PrimType toType, PrimType fromType)
1171 {
1172     uint32 fromSize = GetPrimTypeBitSize(fromType);
1173     uint32 toSize = GetPrimTypeBitSize(toType);
1174     RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, fromType);
1175     if (fromSize == toSize) {
1176         resOpnd = regOpnd0;
1177         return;
1178     }
1179     MOperator mOp = abstract::MOP_undef;
1180     if (fromSize == k32BitSize && toSize == k64BitSize) {
1181         mOp = abstract::MOP_cvt_ff_64_32;
1182     } else if (fromSize == k64BitSize && toSize == k32BitSize) {
1183         mOp = abstract::MOP_cvt_ff_32_64;
1184     } else {
1185         CHECK_FATAL(false, "niy");
1186     }
1187     Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mOp, InsnDesc::GetAbstractId(mOp));
1188     (void)insn.AddOpndChain(resOpnd).AddOpndChain(regOpnd0);
1189     cgFunc->GetCurBB()->AppendInsn(insn);
1190     return;
1191 }
1192 
SelectSub(Operand & resOpnd,Operand & opnd0,Operand & opnd1,PrimType primType)1193 void MPISel::SelectSub(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType)
1194 {
1195     MOperator mOp = abstract::MOP_undef;
1196     if (IsPrimitiveInteger(primType)) {
1197         const static auto fastSubMappingFunc = DEF_MOPERATOR_MAPPING_FUNC(sub);
1198         mOp = fastSubMappingFunc(GetPrimTypeBitSize(primType));
1199     } else {
1200         const static auto fastSubFloatMappingFunc = DEF_FLOAT_MOPERATOR_MAPPING_FUNC(sub);
1201         mOp = fastSubFloatMappingFunc(GetPrimTypeBitSize(primType));
1202     }
1203     SelectBasicOp(resOpnd, opnd0, opnd1, mOp, primType);
1204 }
1205 
SelectBand(Operand & resOpnd,Operand & opnd0,Operand & opnd1,PrimType primType)1206 void MPISel::SelectBand(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType)
1207 {
1208     MOperator mOp = abstract::MOP_undef;
1209     if (IsPrimitiveInteger(primType)) {
1210         const static auto fastAndMappingFunc = DEF_MOPERATOR_MAPPING_FUNC(and);
1211         mOp = fastAndMappingFunc(GetPrimTypeBitSize(primType));
1212     } else {
1213         const static auto fastAndFloatMappingFunc = DEF_FLOAT_MOPERATOR_MAPPING_FUNC(and);
1214         mOp = fastAndFloatMappingFunc(GetPrimTypeBitSize(primType));
1215     }
1216     SelectBasicOp(resOpnd, opnd0, opnd1, mOp, primType);
1217 }
1218 
SelectAdd(Operand & resOpnd,Operand & opnd0,Operand & opnd1,PrimType primType)1219 void MPISel::SelectAdd(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType)
1220 {
1221     MOperator mOp = abstract::MOP_undef;
1222     if (IsPrimitiveInteger(primType)) {
1223         const static auto fastAddMappingFunc = DEF_MOPERATOR_MAPPING_FUNC(add);
1224         mOp = fastAddMappingFunc(GetPrimTypeBitSize(primType));
1225     } else {
1226         const static auto fastAddFloatMappingFunc = DEF_FLOAT_MOPERATOR_MAPPING_FUNC(add);
1227         mOp = fastAddFloatMappingFunc(GetPrimTypeBitSize(primType));
1228     }
1229     SelectBasicOp(resOpnd, opnd0, opnd1, mOp, primType);
1230 }
1231 
SelectNeg(const UnaryNode & node,Operand & opnd0,const BaseNode & parent)1232 Operand *MPISel::SelectNeg(const UnaryNode &node, Operand &opnd0, const BaseNode &parent)
1233 {
1234     PrimType dtype = node.GetPrimType();
1235 
1236     RegOperand *resOpnd = nullptr;
1237     if (!IsPrimitiveVector(dtype)) {
1238         resOpnd = &cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(dtype), cgFunc->GetRegTyFromPrimTy(dtype));
1239         RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, dtype, node.Opnd(0)->GetPrimType());
1240         SelectNeg(*resOpnd, regOpnd0, dtype);
1241     } else {
1242         /* vector operand */
1243         CHECK_FATAL(false, "NIY");
1244     }
1245     return resOpnd;
1246 }
1247 
SelectNeg(Operand & resOpnd,Operand & opnd0,PrimType primType)1248 void MPISel::SelectNeg(Operand &resOpnd, Operand &opnd0, PrimType primType)
1249 {
1250     MOperator mOp = abstract::MOP_undef;
1251     if (IsPrimitiveInteger(primType)) {
1252         const static auto fastNegMappingFunc = DEF_MOPERATOR_MAPPING_FUNC(neg);
1253         mOp = fastNegMappingFunc(GetPrimTypeBitSize(primType));
1254     } else {
1255         const static auto fastNegFloatMappingFunc = DEF_FLOAT_MOPERATOR_MAPPING_FUNC(neg);
1256         mOp = fastNegFloatMappingFunc(GetPrimTypeBitSize(primType));
1257     }
1258     Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mOp, InsnDesc::GetAbstractId(mOp));
1259     (void)insn.AddOpndChain(resOpnd).AddOpndChain(opnd0);
1260     cgFunc->GetCurBB()->AppendInsn(insn);
1261 }
1262 
SelectBior(const BinaryNode & node,Operand & opnd0,Operand & opnd1,const BaseNode & parent)1263 Operand *MPISel::SelectBior(const BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent)
1264 {
1265     PrimType primType = node.GetPrimType();
1266     RegOperand *resOpnd =
1267         &cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
1268     RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, primType, node.Opnd(0)->GetPrimType());
1269     RegOperand &regOpnd1 = SelectCopy2Reg(opnd1, primType, node.Opnd(1)->GetPrimType());
1270     SelectBior(*resOpnd, regOpnd0, regOpnd1, primType);
1271     return resOpnd;
1272 }
1273 
SelectBior(Operand & resOpnd,Operand & opnd0,Operand & opnd1,PrimType primType)1274 void MPISel::SelectBior(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType)
1275 {
1276     const static auto fastBiorMappingFunc = DEF_MOPERATOR_MAPPING_FUNC(or);
1277     MOperator mOp = fastBiorMappingFunc(GetPrimTypeBitSize(primType));
1278     SelectBasicOp(resOpnd, opnd0, opnd1, mOp, primType);
1279 }
1280 
SelectBxor(const BinaryNode & node,Operand & opnd0,Operand & opnd1,const BaseNode & parent)1281 Operand *MPISel::SelectBxor(const BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent)
1282 {
1283     PrimType primType = node.GetPrimType();
1284     RegOperand *resOpnd =
1285         &cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
1286     RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, primType, node.Opnd(0)->GetPrimType());
1287     RegOperand &regOpnd1 = SelectCopy2Reg(opnd1, primType, node.Opnd(1)->GetPrimType());
1288     SelectBxor(*resOpnd, regOpnd0, regOpnd1, primType);
1289     return resOpnd;
1290 }
1291 
SelectBxor(Operand & resOpnd,Operand & opnd0,Operand & opnd1,PrimType primType)1292 void MPISel::SelectBxor(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType)
1293 {
1294     const static auto fastBxorMappingFunc = DEF_MOPERATOR_MAPPING_FUNC(xor);
1295     MOperator mOp = fastBxorMappingFunc(GetPrimTypeBitSize(primType));
1296     SelectBasicOp(resOpnd, opnd0, opnd1, mOp, primType);
1297 }
1298 
GetOrCreateMemOpndFromIreadNode(const IreadNode & expr,PrimType primType,int offset)1299 MemOperand *MPISel::GetOrCreateMemOpndFromIreadNode(const IreadNode &expr, PrimType primType, int offset)
1300 {
1301     /* get rhs*/
1302     Operand *addrOpnd = HandleExpr(expr, *expr.Opnd(0));
1303     RegOperand &addrOnReg = SelectCopy2Reg(*addrOpnd, PTY_a64);
1304     /* Generate memOpnd */
1305     MemOperand &memOpnd = cgFunc->GetOpndBuilder()->CreateMem(addrOnReg, offset, GetPrimTypeBitSize(primType));
1306     return &memOpnd;
1307 }
1308 
SelectIread(const BaseNode & parent,const IreadNode & expr,int extraOffset)1309 Operand *MPISel::SelectIread(const BaseNode &parent, const IreadNode &expr, int extraOffset)
1310 {
1311     /* get lhs mirType info */
1312     MirTypeInfo lhsInfo = GetMirTypeInfoFromMirNode(expr);
1313     /* get memOpnd */
1314     MemOperand &memOpnd = *GetOrCreateMemOpndFromIreadNode(expr, lhsInfo.primType, lhsInfo.offset + extraOffset);
1315     /* for AggType, return addr it self. */
1316     if (lhsInfo.primType == PTY_agg) {
1317         return &memOpnd;
1318     }
1319     /* for BasicType, load val in addr to register. */
1320     PrimType primType = expr.GetPrimType();
1321     RegOperand &result =
1322         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
1323     SelectCopy(result, memOpnd, primType, lhsInfo.primType);
1324     return &result;
1325 }
1326 
SelectIreadoff(const BaseNode & parent,const IreadoffNode & ireadoff)1327 Operand *MPISel::SelectIreadoff(const BaseNode &parent, const IreadoffNode &ireadoff)
1328 {
1329     int32 offset = ireadoff.GetOffset();
1330     PrimType primType = ireadoff.GetPrimType();
1331     uint32 bitSize = GetPrimTypeBitSize(primType);
1332 
1333     Operand *addrOpnd = HandleExpr(ireadoff, *ireadoff.Opnd(0));
1334     RegOperand &addrOnReg = SelectCopy2Reg(*addrOpnd, PTY_a64);
1335     MemOperand &memOpnd = cgFunc->GetOpndBuilder()->CreateMem(addrOnReg, offset, bitSize);
1336     RegOperand &result = cgFunc->GetOpndBuilder()->CreateVReg(bitSize, cgFunc->GetRegTyFromPrimTy(primType));
1337     SelectCopy(result, memOpnd, primType);
1338     return &result;
1339 }
1340 
CreateDepositBitsImm1(uint32 primBitSize,uint8 bitOffset,uint8 bitSize)1341 static inline uint64 CreateDepositBitsImm1(uint32 primBitSize, uint8 bitOffset, uint8 bitSize)
1342 {
1343     /* $imm1 = 1(primBitSize - bitSize - bitOffset)0(bitSize)1(bitOffset) */
1344     uint64 val = UINT64_MAX;  // 0xFFFFFFFFFFFFFFFF
1345     if (bitSize + bitOffset >= primBitSize) {
1346         val = 0;
1347     } else {
1348         val <<= (bitSize + bitOffset);
1349     }
1350     val |= (static_cast<uint64>(1) << bitOffset) - 1;
1351     return val;
1352 }
1353 
SelectDepositBits(const DepositbitsNode & node,Operand & opnd0,Operand & opnd1,const BaseNode & parent)1354 Operand *MPISel::SelectDepositBits(const DepositbitsNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent)
1355 {
1356     uint8 bitOffset = node.GetBitsOffset();
1357     uint8 bitSize = node.GetBitsSize();
1358     PrimType primType = node.GetPrimType();
1359     uint32 primBitSize = GetPrimTypeBitSize(primType);
1360     DEBUG_ASSERT((primBitSize == k64BitSize) || (bitOffset < k32BitSize), "wrong bitSize");
1361     DEBUG_ASSERT(bitSize < k64BitSize, "wrong bitSize");
1362 
1363     RegOperand &resOpnd = cgFunc->GetOpndBuilder()->CreateVReg(primBitSize, cgFunc->GetRegTyFromPrimTy(primType));
1364     /*
1365      * resOpnd = (opnd0 and $imm1) or ((opnd1 << bitOffset) and (~$imm1));
1366      * $imm1 = 1(primBitSize - bitSize - bitOffset)0(bitSize)1(bitOffset)
1367      */
1368     uint64 imm1Val = CreateDepositBitsImm1(primBitSize, bitOffset, bitSize);
1369     ImmOperand &imm1Opnd = cgFunc->GetOpndBuilder()->CreateImm(primBitSize, static_cast<int64>(imm1Val));
1370     /* and */
1371     SelectBand(resOpnd, opnd0, imm1Opnd, primType);
1372     if (opnd1.IsIntImmediate()) {
1373         /* opnd1 is immediate, imm2 = (opnd1.val << bitOffset) & (~$imm1) */
1374         int64 imm2Val = (static_cast<ImmOperand &>(opnd1).GetValue() << bitOffset) & (~imm1Val);
1375         ImmOperand &imm2Opnd = cgFunc->GetOpndBuilder()->CreateImm(primBitSize, imm2Val);
1376         /* or */
1377         SelectBior(resOpnd, resOpnd, imm2Opnd, primType);
1378     } else {
1379         RegOperand &tmpOpnd = cgFunc->GetOpndBuilder()->CreateVReg(primBitSize, cgFunc->GetRegTyFromPrimTy(primType));
1380         SelectCopy(tmpOpnd, opnd1, primType, node.Opnd(1)->GetPrimType());
1381         /* shift -- (opnd1 << bitOffset) */
1382         ImmOperand &countOpnd = cgFunc->GetOpndBuilder()->CreateImm(primBitSize, bitOffset);
1383         SelectShift(tmpOpnd, tmpOpnd, countOpnd, OP_shl, primType, primType);
1384         /* and (~$imm1) */
1385         ImmOperand &nonImm1Opnd = cgFunc->GetOpndBuilder()->CreateImm(primBitSize, (~imm1Val));
1386         SelectBand(tmpOpnd, tmpOpnd, nonImm1Opnd, primType);
1387         /* or */
1388         SelectBior(resOpnd, resOpnd, tmpOpnd, primType);
1389     }
1390     return &resOpnd;
1391 }
1392 
SelectAbs(UnaryNode & node,Operand & opnd0)1393 Operand *MPISel::SelectAbs(UnaryNode &node, Operand &opnd0)
1394 {
1395     PrimType primType = node.GetPrimType();
1396     if (IsPrimitiveVector(primType)) {
1397         CHECK_FATAL(false, "NIY");
1398     } else if (IsPrimitiveFloat(primType)) {
1399         /*
1400          * fabs(x) = x AND 0x7fffffff ffffffff [set sign bit to 0]
1401          */
1402         const static uint64 kNaN = 0x7fffffffffffffffUL;
1403         const static double kNaNDouble = *(double*)(&kNaN);
1404         const static uint64 kNaNf = 0x7fffffffUL;
1405         const static double kNaNFloat = *(double*)(&kNaNf);
1406         CHECK_FATAL(primType == PTY_f64 || primType == PTY_f32, "niy");
1407 
1408         double mask = primType == PTY_f64 ? kNaNDouble : kNaNFloat;
1409         MIRDoubleConst *c = cgFunc->GetMemoryPool()->New<MIRDoubleConst>(mask,
1410                             *GlobalTables::GetTypeTable().GetTypeTable().at(PTY_f64));
1411         Operand *opnd1 = SelectFloatingConst(*c, PTY_f64);
1412 
1413         RegOperand &resOpnd =
1414             cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
1415         SelectBand(resOpnd, opnd0, *opnd1, primType);
1416         return &resOpnd;
1417     } else if (IsUnsignedInteger(primType)) {
1418         return &opnd0;
1419     } else {
1420         /*
1421          * abs(x) = (x XOR y) - y
1422          * y = x >>> (bitSize - 1)
1423          */
1424         uint32 bitSize = GetPrimTypeBitSize(primType);
1425         CHECK_FATAL(bitSize == k64BitSize || bitSize == k32BitSize, "only support 32-bits or 64-bits");
1426         RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, primType);
1427         ImmOperand &immOpnd = cgFunc->GetOpndBuilder()->CreateImm(bitSize, bitSize - 1);
1428         RegOperand &regOpndy = cgFunc->GetOpndBuilder()->CreateVReg(bitSize, cgFunc->GetRegTyFromPrimTy(primType));
1429         SelectShift(regOpndy, regOpnd0, immOpnd, OP_ashr, primType, primType);
1430         RegOperand &tmpOpnd = cgFunc->GetOpndBuilder()->CreateVReg(bitSize, cgFunc->GetRegTyFromPrimTy(primType));
1431         SelectBxor(tmpOpnd, regOpnd0, regOpndy, primType);
1432         RegOperand &resOpnd = cgFunc->GetOpndBuilder()->CreateVReg(bitSize, cgFunc->GetRegTyFromPrimTy(primType));
1433         SelectSub(resOpnd, tmpOpnd, regOpndy, primType);
1434         return &resOpnd;
1435     }
1436 }
1437 
SelectAlloca(UnaryNode & node,Operand & opnd0)1438 Operand *MPISel::SelectAlloca(UnaryNode &node, Operand &opnd0)
1439 {
1440     DEBUG_ASSERT(node.GetPrimType() == PTY_a64, "wrong type");
1441     PrimType srcType = node.Opnd(0)->GetPrimType();
1442     RegOperand &sizeOpnd =
1443         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(PTY_u64), cgFunc->GetRegTyFromPrimTy(PTY_u64));
1444     SelectCopy(sizeOpnd, opnd0, PTY_u64, srcType);
1445 
1446     /* stack byte alignment */
1447     uint32 stackPtrAlignment = cgFunc->GetMemlayout()->GetStackPtrAlignment();
1448     RegOperand &aliOp =
1449         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(PTY_u64), cgFunc->GetRegTyFromPrimTy(PTY_u64));
1450     SelectAdd(aliOp, sizeOpnd, cgFunc->GetOpndBuilder()->CreateImm(k64BitSize, stackPtrAlignment - 1), PTY_u64);
1451     ImmOperand &shiftOpnd = cgFunc->GetOpndBuilder()->CreateImm(k64BitSize, __builtin_ctz(stackPtrAlignment));
1452     SelectShift(aliOp, aliOp, shiftOpnd, OP_lshr, PTY_u64, PTY_u64);
1453     SelectShift(aliOp, aliOp, shiftOpnd, OP_shl, PTY_u64, PTY_u64);
1454 
1455     RegOperand &spOpnd = GetTargetStackPointer(PTY_u64);
1456     SelectSub(spOpnd, spOpnd, aliOp, PTY_u64);
1457 
1458     RegOperand &resOpnd =
1459         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(PTY_u64), cgFunc->GetRegTyFromPrimTy(PTY_u64));
1460     uint32 argsToStkpassSize = cgFunc->GetMemlayout()->SizeOfArgsToStackPass();
1461     if (argsToStkpassSize > 0) {
1462         SelectAdd(resOpnd, spOpnd, cgFunc->GetOpndBuilder()->CreateImm(k64BitSize, argsToStkpassSize), PTY_u64);
1463     } else {
1464         SelectCopy(resOpnd, spOpnd, PTY_u64);
1465     }
1466     return &resOpnd;
1467 }
1468 
SelectCGArrayElemAdd(BinaryNode & node,const BaseNode & parent)1469 Operand *MPISel::SelectCGArrayElemAdd(BinaryNode &node, const BaseNode &parent)
1470 {
1471     BaseNode *opnd0 = node.Opnd(0);
1472     BaseNode *opnd1 = node.Opnd(1);
1473     DEBUG_ASSERT(opnd1->GetOpCode() == OP_constval, "NIY, opnd1->op should be OP_constval.");
1474 
1475     switch (opnd0->GetOpCode()) {
1476         case OP_regread: {
1477             return SelectRegread(static_cast<RegreadNode &>(*opnd0));
1478         }
1479         case OP_addrof: {
1480             Operand *addrOpnd = SelectAddrof(static_cast<AddrofNode &>(*opnd0), node);
1481 
1482             /* OP_constval */
1483             ConstvalNode *constvalNode = static_cast<ConstvalNode *>(opnd1);
1484             MIRConst *mirConst = constvalNode->GetConstVal();
1485             DEBUG_ASSERT(mirConst->GetKind() == kConstInt, "NIY");
1486             MIRIntConst *mirIntConst = static_cast<MIRIntConst *>(mirConst);
1487             Operand *immOpnd = SelectIntConst(*mirIntConst, constvalNode->GetPrimType());
1488 
1489             Operand &resOpnd =
1490                 cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(PTY_a64), cgFunc->GetRegTyFromPrimTy(PTY_a64));
1491             SelectAdd(resOpnd, *addrOpnd, *immOpnd, node.GetPrimType());
1492             return &resOpnd;
1493         }
1494         default:
1495             CHECK_FATAL(false, "cannot handle opnd0.");
1496     }
1497 }
1498 
HandleFuncEntry()1499 StmtNode *MPISel::HandleFuncEntry()
1500 {
1501     MIRFunction &mirFunc = cgFunc->GetFunction();
1502     BlockNode *block = mirFunc.GetBody();
1503 
1504     DEBUG_ASSERT(block != nullptr, "get func body block failed in CGFunc::GenerateInstruction");
1505 
1506     StmtNode *stmt = block->GetFirst();
1507     if (stmt == nullptr) {
1508         return nullptr;
1509     }
1510     DEBUG_ASSERT(stmt->GetOpCode() == OP_label, "The first statement should be a label");
1511     HandleLabel(*stmt, *this);
1512     cgFunc->SetFirstBB(*cgFunc->GetCurBB());
1513     stmt = stmt->GetNext();
1514     if (stmt == nullptr) {
1515         return nullptr;
1516     }
1517     cgFunc->SetCurBB(*cgFunc->StartNewBBImpl(false, *stmt));
1518     bool withFreqInfo = mirFunc.HasFreqMap() && !mirFunc.GetLastFreqMap().empty();
1519     if (withFreqInfo) {
1520         cgFunc->GetCurBB()->SetFrequency(kFreqBase);
1521     }
1522 
1523     return stmt;
1524 }
1525 
1526 /* This function loads src to a register, the src can be an imm, mem or a label.
1527  * Once the source and result(destination) types are different,
1528  * implicit conversion is executed here.*/
SelectCopy2Reg(Operand & src,PrimType toType,PrimType fromType)1529 RegOperand &MPISel::SelectCopy2Reg(Operand &src, PrimType toType, PrimType fromType)
1530 {
1531     uint32 fromSize = GetPrimTypeBitSize(fromType);
1532     uint32 toSize = GetPrimTypeBitSize(toType);
1533     if (src.IsRegister() && fromSize == toSize) {
1534         return static_cast<RegOperand &>(src);
1535     }
1536     RegOperand &dest =
1537         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(toType), cgFunc->GetRegTyFromPrimTy(toType));
1538     if (fromSize != toSize) {
1539         SelectCopy(dest, src, toType, fromType);
1540     } else {
1541         SelectCopy(dest, src, toType);
1542     }
1543     return dest;
1544 }
1545 /* Pretty sure that implicit type conversions will not occur. */
SelectCopy2Reg(Operand & src,PrimType dtype)1546 RegOperand &MPISel::SelectCopy2Reg(Operand &src, PrimType dtype)
1547 {
1548     DEBUG_ASSERT(src.GetSize() == GetPrimTypeBitSize(dtype), "NIY");
1549     if (src.IsRegister()) {
1550         return static_cast<RegOperand &>(src);
1551     }
1552     RegOperand &dest =
1553         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(dtype), cgFunc->GetRegTyFromPrimTy(dtype));
1554     SelectCopy(dest, src, dtype);
1555     return dest;
1556 }
1557 /* This function copy/load/store src to a dest, Once the src and dest types
1558  * are different, implicit conversion is executed here. */
SelectCopy(Operand & dest,Operand & src,PrimType toType,PrimType fromType)1559 void MPISel::SelectCopy(Operand &dest, Operand &src, PrimType toType, PrimType fromType)
1560 {
1561     if (GetPrimTypeBitSize(fromType) != GetPrimTypeBitSize(toType)) {
1562         RegOperand &srcRegOpnd = SelectCopy2Reg(src, fromType);
1563         RegOperand &dstRegOpnd =
1564             cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(toType), cgFunc->GetRegTyFromPrimTy(toType));
1565         SelectIntCvt(dstRegOpnd, srcRegOpnd, toType, fromType);
1566         SelectCopy(dest, dstRegOpnd, toType);
1567     } else {
1568         SelectCopy(dest, src, toType);
1569     }
1570 }
1571 
1572 /* Pretty sure that implicit type conversions will not occur. */
SelectCopy(Operand & dest,Operand & src,PrimType type)1573 void MPISel::SelectCopy(Operand &dest, Operand &src, PrimType type)
1574 {
1575     DEBUG_ASSERT(dest.GetSize() == src.GetSize(), "NIY");
1576     if (dest.GetKind() == Operand::kOpdRegister) {
1577         SelectCopyInsn(dest, src, type);
1578     } else if (dest.GetKind() == Operand::kOpdMem) {
1579         if (src.GetKind() != Operand::kOpdRegister) {
1580             RegOperand &tempReg =
1581                 cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(type), cgFunc->GetRegTyFromPrimTy(type));
1582             SelectCopyInsn(tempReg, src, type);
1583             SelectCopyInsn(dest, tempReg, type);
1584         } else {
1585             SelectCopyInsn(dest, src, type);
1586         }
1587     } else {
1588         CHECK_FATAL(false, "NIY, CPU supports more than memory and registers");
1589     }
1590     return;
1591 }
1592 
SelectCopyInsn(Operand & dest,Operand & src,PrimType type)1593 void MPISel::SelectCopyInsn(Operand &dest, Operand &src, PrimType type)
1594 {
1595     MOperator mop = GetFastIselMop(dest.GetKind(), src.GetKind(), type);
1596     CHECK_FATAL(mop != abstract::MOP_undef, "get mop failed");
1597     Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mop, InsnDesc::GetAbstractId(mop));
1598     (void)insn.AddOpndChain(dest).AddOpndChain(src);
1599     cgFunc->GetCurBB()->AppendInsn(insn);
1600 }
1601 
SelectBnot(const UnaryNode & node,Operand & opnd0,const BaseNode & parent)1602 Operand *MPISel::SelectBnot(const UnaryNode &node, Operand &opnd0, const BaseNode &parent)
1603 {
1604     PrimType dtype = node.GetPrimType();
1605 
1606     RegOperand *resOpnd = nullptr;
1607     if (!IsPrimitiveVector(dtype)) {
1608         resOpnd = &cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(dtype), cgFunc->GetRegTyFromPrimTy(dtype));
1609         RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, dtype, node.Opnd(0)->GetPrimType());
1610         SelectBnot(*resOpnd, regOpnd0, dtype);
1611     } else {
1612         /* vector operand */
1613         CHECK_FATAL(false, "NIY");
1614     }
1615     return resOpnd;
1616 }
1617 
SelectBnot(Operand & resOpnd,Operand & opnd0,PrimType primType)1618 void MPISel::SelectBnot(Operand &resOpnd, Operand &opnd0, PrimType primType)
1619 {
1620     const static auto fastBnotMappingFunc = DEF_MOPERATOR_MAPPING_FUNC(not);
1621     MOperator mOp = fastBnotMappingFunc(GetPrimTypeBitSize(primType));
1622     Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mOp, InsnDesc::GetAbstractId(mOp));
1623     (void)insn.AddOpndChain(resOpnd).AddOpndChain(opnd0);
1624     cgFunc->GetCurBB()->AppendInsn(insn);
1625 }
1626 
SelectMin(BinaryNode & node,Operand & opnd0,Operand & opnd1,const BaseNode & parent)1627 Operand *MPISel::SelectMin(BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent)
1628 {
1629     PrimType primType = node.GetPrimType();
1630     RegOperand &resOpnd =
1631         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
1632     SelectMin(resOpnd, opnd0, opnd1, primType);
1633     return &resOpnd;
1634 }
1635 
SelectMin(Operand & resOpnd,Operand & opnd0,Operand & opnd1,PrimType primType)1636 void MPISel::SelectMin(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType)
1637 {
1638     SelectMinOrMax(true, resOpnd, opnd0, opnd1, primType);
1639 }
1640 
SelectMax(BinaryNode & node,Operand & opnd0,Operand & opnd1,const BaseNode & parent)1641 Operand *MPISel::SelectMax(BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent)
1642 {
1643     PrimType primType = node.GetPrimType();
1644     RegOperand &resOpnd =
1645         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
1646     SelectMax(resOpnd, opnd0, opnd1, primType);
1647     return &resOpnd;
1648 }
1649 
SelectMax(Operand & resOpnd,Operand & opnd0,Operand & opnd1,PrimType primType)1650 void MPISel::SelectMax(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType)
1651 {
1652     SelectMinOrMax(false, resOpnd, opnd0, opnd1, primType);
1653 }
1654 
SelectRetype(TypeCvtNode & node,Operand & opnd0)1655 Operand *MPISel::SelectRetype(TypeCvtNode &node, Operand &opnd0)
1656 {
1657     PrimType fromType = node.Opnd(0)->GetPrimType();
1658     PrimType toType = node.GetPrimType();
1659     DEBUG_ASSERT(GetPrimTypeSize(fromType) == GetPrimTypeSize(toType), "retype bit widith doesn' match");
1660     if (IsPrimitivePoint(fromType) && IsPrimitivePoint(toType)) {
1661         return &SelectCopy2Reg(opnd0, toType);
1662     }
1663     if (IsPrimitiveVector(fromType) || IsPrimitiveVector(toType)) {
1664         return &SelectCopy2Reg(opnd0, toType);
1665     }
1666     if (IsPrimitiveInteger(fromType) && IsPrimitiveInteger(toType)) {
1667         return &SelectCopy2Reg(opnd0, toType, fromType);
1668     }
1669     if (IsPrimitiveInteger(fromType) && IsPrimitiveFloat(toType)) {
1670         RegOperand *resOpnd = &cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(toType),
1671         cgFunc->GetRegTyFromPrimTy(toType));
1672         SelectRetypeFloat(*resOpnd, opnd0, toType, fromType);
1673         return &(*resOpnd);
1674     }
1675     if (IsPrimitiveFloat(fromType) && IsPrimitiveInteger(toType)) {
1676         RegOperand *resOpnd = &cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(toType),
1677         cgFunc->GetRegTyFromPrimTy(toType));
1678         SelectRetypeFloat(*resOpnd, opnd0, toType, fromType);
1679         return &(*resOpnd);
1680     }
1681     CHECK_FATAL(false, "NIY, retype");
1682     return nullptr;
1683 }
1684 
HandleFuncExit()1685 void MPISel::HandleFuncExit()
1686 {
1687     BlockNode *block = cgFunc->GetFunction().GetBody();
1688     DEBUG_ASSERT(block != nullptr, "get func body block failed in CGFunc::GenerateInstruction");
1689     cgFunc->GetCurBB()->SetLastStmt(*block->GetLast());
1690     /* Set lastbb's frequency */
1691     cgFunc->SetLastBB(*cgFunc->GetCurBB());
1692     /* the last BB is return BB */
1693     cgFunc->GetLastBB()->SetKind(BB::kBBReturn);
1694     cgFunc->SetCleanupBB(*cgFunc->GetCurBB()->GetPrev());
1695 }
1696 
PhaseRun(maplebe::CGFunc & f)1697 bool InstructionSelector::PhaseRun(maplebe::CGFunc &f)
1698 {
1699     MPISel *mpIS = f.GetCG()->CreateMPIsel(*GetPhaseMemPool(), *GetPhaseAllocator(), f);
1700     mpIS->doMPIS();
1701     Standardize *stdz = f.GetCG()->CreateStandardize(*GetPhaseMemPool(), f);
1702     stdz->DoStandardize();
1703     return true;
1704 }
1705 }  // namespace maplebe
1706