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