• 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 
21 namespace maplebe {
22 /* register,                       imm ,                         memory,                        cond */
23 #define DEF_FAST_ISEL_MAPPING_INT(SIZE)                                                                               \
24     MOperator fastIselMapI##SIZE[Operand::OperandType::kOpdPhi][Operand::OperandType::kOpdPhi] = {                    \
25         {abstract::MOP_copy_rr_##SIZE, abstract::MOP_copy_ri_##SIZE, abstract::MOP_load_##SIZE, abstract::MOP_undef}, \
26         {abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef},                         \
27         {abstract::MOP_str_##SIZE, abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef},                    \
28         {abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef},                         \
29     }
30 #define DEF_FAST_ISEL_MAPPING_FLOAT(SIZE)                                                            \
31     MOperator fastIselMapF##SIZE[Operand::OperandType::kOpdPhi][Operand::OperandType::kOpdPhi] = {   \
32         {abstract::MOP_copy_ff_##SIZE, abstract::MOP_copy_fi_##SIZE, abstract::MOP_load_f_##SIZE,    \
33          abstract::MOP_undef},                                                                       \
34         {abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef},        \
35         {abstract::MOP_str_f_##SIZE, abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef}, \
36         {abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef, abstract::MOP_undef},        \
37     }
38 
39 DEF_FAST_ISEL_MAPPING_INT(8);
40 DEF_FAST_ISEL_MAPPING_INT(16);
41 DEF_FAST_ISEL_MAPPING_INT(32);
42 DEF_FAST_ISEL_MAPPING_INT(64);
43 DEF_FAST_ISEL_MAPPING_FLOAT(8);
44 DEF_FAST_ISEL_MAPPING_FLOAT(16);
45 DEF_FAST_ISEL_MAPPING_FLOAT(32);
46 DEF_FAST_ISEL_MAPPING_FLOAT(64);
47 
48 #define DEF_SEL_MAPPING_TBL(SIZE)                                           \
49     MOperator SelMapping##SIZE(bool isInt, uint32 x, uint32 y)              \
50     {                                                                       \
51         return isInt ? fastIselMapI##SIZE[x][y] : fastIselMapF##SIZE[x][y]; \
52     }
53 #define USE_SELMAPPING_TBL(SIZE) \
54     {                            \
55         SIZE, SelMapping##SIZE   \
56     }
57 
58 DEF_SEL_MAPPING_TBL(8);
59 DEF_SEL_MAPPING_TBL(16);
60 DEF_SEL_MAPPING_TBL(32);
61 DEF_SEL_MAPPING_TBL(64);
62 
63 std::map<uint32, std::function<MOperator(bool, uint32, uint32)>> fastIselMappingTable = {
64     USE_SELMAPPING_TBL(8), USE_SELMAPPING_TBL(16), USE_SELMAPPING_TBL(32), USE_SELMAPPING_TBL(64)};
65 
GetFastIselMop(Operand::OperandType dTy,Operand::OperandType sTy,PrimType type)66 MOperator GetFastIselMop(Operand::OperandType dTy, Operand::OperandType sTy, PrimType type)
67 {
68     uint32 bitSize = GetPrimTypeBitSize(type);
69     bool isInteger = IsPrimitiveInteger(type);
70     auto tableDriven = fastIselMappingTable.find(bitSize);
71     if (tableDriven != fastIselMappingTable.end()) {
72         auto funcIt = tableDriven->second;
73         return funcIt(isInteger, dTy, sTy);
74     } else {
75         CHECK_FATAL(false, "unsupport type");
76     }
77     return abstract::MOP_undef;
78 }
79 
80 #define DEF_EXTEND_MAPPING_TBL(TYPE) \
81     [](bool isSigned) -> MOperator { return isSigned ? abstract::MOP_sext_rr_##TYPE : abstract::MOP_zext_rr_##TYPE; }
82 using fromToTy = std::pair<uint32, uint32>; /* std::pair<from, to> */
83 #define DEF_USE_EXTEND_MAPPING_TBL(FROMSIZE, TOSIZE)                                            \
84     {                                                                                           \
85         {k##FROMSIZE##BitSize, k##TOSIZE##BitSize}, DEF_EXTEND_MAPPING_TBL(TOSIZE##_##FROMSIZE) \
86     }
87 
88 std::map<fromToTy, std::function<MOperator(bool)>> fastCvtMappingTableI = {
89     DEF_USE_EXTEND_MAPPING_TBL(8, 16), /* Extend Mapping */
90     DEF_USE_EXTEND_MAPPING_TBL(8, 32),  DEF_USE_EXTEND_MAPPING_TBL(8, 64),  DEF_USE_EXTEND_MAPPING_TBL(16, 32),
91     DEF_USE_EXTEND_MAPPING_TBL(16, 64), DEF_USE_EXTEND_MAPPING_TBL(32, 64),
92 };
93 #undef DEF_USE_EXTEND_MAPPING_TBL
94 #undef DEF_EXTEND_MAPPING_TBL
95 
GetFastCvtMopI(uint32 fromSize,uint32 toSize,bool isSigned)96 static MOperator GetFastCvtMopI(uint32 fromSize, uint32 toSize, bool isSigned)
97 {
98     if (toSize < k8BitSize || toSize > k64BitSize) {
99         CHECK_FATAL(false, "unsupport type");
100     }
101     if (fromSize < k8BitSize || fromSize > k64BitSize) {
102         CHECK_FATAL(false, "unsupport type");
103     }
104     /* Extend: fromSize < toSize */
105     auto tableDriven = fastCvtMappingTableI.find({fromSize, toSize});
106     if (tableDriven == fastCvtMappingTableI.end()) {
107         CHECK_FATAL(false, "unsupport cvt");
108     }
109     MOperator mOp = tableDriven->second(isSigned);
110     if (mOp == abstract::MOP_undef) {
111         CHECK_FATAL(false, "unsupport cvt");
112     }
113     return mOp;
114 }
115 
116 /*
117  * fast get MOperator
118  * such as : and, or, shl ...
119  */
120 #define DEF_MOPERATOR_MAPPING_FUNC(TYPE)                                                           \
121     [](uint32 bitSize)->MOperator {                                                              \
122         /* 8-bits,                16-bits,                   32-bits,                   64-bits */ \
123         constexpr static std::array<MOperator, kBitIndexEnd> fastMapping_##TYPE = {                \
124             abstract::MOP_##TYPE##_8, abstract::MOP_##TYPE##_16, abstract::MOP_##TYPE##_32,        \
125             abstract::MOP_##TYPE##_64};                                                            \
126         return fastMapping_##TYPE[GetBitIndex(bitSize)];                                           \
127     }
128 
129 #define DEF_FLOAT_MOPERATOR_MAPPING_FUNC(TYPE)                                                     \
130     [](uint32 bitSize)->MOperator {                                                              \
131         /* 8-bits,                16-bits,                   32-bits,                   64-bits */ \
132         constexpr static std::array<MOperator, kBitIndexEnd> fastMapping_f_##TYPE = {              \
133             abstract::MOP_##TYPE##_f_8, abstract::MOP_##TYPE##_f_16, abstract::MOP_##TYPE##_f_32,  \
134             abstract::MOP_##TYPE##_f_64};                                                          \
135         return fastMapping_f_##TYPE[GetBitIndex(bitSize)];                                         \
136     }
137 
HandleDassign(StmtNode & stmt,MPISel & iSel)138 static void HandleDassign(StmtNode &stmt, MPISel &iSel)
139 {
140     DEBUG_ASSERT(stmt.GetOpCode() == OP_dassign, "expect dassign");
141     auto &dassignNode = static_cast<DassignNode &>(stmt);
142     BaseNode *rhs = dassignNode.GetRHS();
143     DEBUG_ASSERT(rhs != nullptr, "get rhs of dassignNode failed");
144     Operand *opndRhs = iSel.HandleExpr(dassignNode, *rhs);
145     if (opndRhs == nullptr) {
146         return;
147     }
148     iSel.SelectDassign(dassignNode, *opndRhs);
149 }
150 
HandleIassign(StmtNode & stmt,MPISel & iSel)151 static void HandleIassign(StmtNode &stmt, MPISel &iSel)
152 {
153     DEBUG_ASSERT(stmt.GetOpCode() == OP_iassign, "expect iassign");
154     auto &iassignNode = static_cast<IassignNode &>(stmt);
155     BaseNode *rhs = iassignNode.GetRHS();
156     DEBUG_ASSERT(rhs != nullptr, "null ptr check");
157     Operand *opndRhs = iSel.HandleExpr(stmt, *rhs);
158     BaseNode *addr = iassignNode.Opnd(0);
159     DEBUG_ASSERT(addr != nullptr, "null ptr check");
160     Operand *opndAddr = iSel.HandleExpr(stmt, *addr);
161     if (opndRhs == nullptr || opndAddr == nullptr) {
162         return;
163     }
164     iSel.SelectIassign(iassignNode, *opndAddr, *opndRhs);
165 }
166 
HandleRegassign(StmtNode & stmt,MPISel & iSel)167 static void HandleRegassign(StmtNode &stmt, MPISel &iSel)
168 {
169     DEBUG_ASSERT(stmt.GetOpCode() == OP_regassign, "expect regAssign");
170     auto &regAssignNode = static_cast<RegassignNode &>(stmt);
171     BaseNode *operand = regAssignNode.Opnd(0);
172     DEBUG_ASSERT(operand != nullptr, "get operand of regassignNode failed");
173     Operand *opnd0 = iSel.HandleExpr(regAssignNode, *operand);
174     iSel.SelectRegassign(regAssignNode, *opnd0);
175 }
176 
HandleLabel(StmtNode & stmt,const MPISel & iSel)177 static void HandleLabel(StmtNode &stmt, const MPISel &iSel)
178 {
179     CGFunc *cgFunc = iSel.GetCurFunc();
180     DEBUG_ASSERT(stmt.GetOpCode() == OP_label, "error");
181     auto &label = static_cast<LabelNode &>(stmt);
182     BB *newBB = cgFunc->StartNewBBImpl(false, label);
183     newBB->AddLabel(label.GetLabelIdx());
184     cgFunc->SetLab2BBMap(static_cast<int32>(newBB->GetLabIdx()), *newBB);
185     cgFunc->SetCurBB(*newBB);
186 }
187 
HandleGoto(StmtNode & stmt,MPISel & iSel)188 static void HandleGoto(StmtNode &stmt, MPISel &iSel)
189 {
190     CGFunc *cgFunc = iSel.GetCurFunc();
191     auto &gotoNode = static_cast<GotoNode &>(stmt);
192     DEBUG_ASSERT(gotoNode.GetOpCode() == OP_goto, "expect goto");
193     cgFunc->SetCurBBKind(BB::kBBGoto);
194     iSel.SelectGoto(gotoNode);
195     cgFunc->SetCurBB(*cgFunc->StartNewBB(gotoNode));
196     DEBUG_ASSERT(&stmt == &gotoNode, "stmt must be same as gotoNoe");
197     if ((gotoNode.GetNext() != nullptr) && (gotoNode.GetNext()->GetOpCode() != OP_label)) {
198         DEBUG_ASSERT(cgFunc->GetCurBB()->GetPrev()->GetLastStmt() == &stmt, "check the relation between BB and stmt");
199     }
200 }
201 
HandleIntrinCall(StmtNode & stmt,MPISel & iSel)202 static void HandleIntrinCall(StmtNode &stmt, MPISel &iSel)
203 {
204     auto &call = static_cast<IntrinsiccallNode &>(stmt);
205     iSel.SelectIntrinsicCall(call);
206 }
207 
HandleRangeGoto(StmtNode & stmt,MPISel & iSel)208 static void HandleRangeGoto(StmtNode &stmt, MPISel &iSel)
209 {
210     CGFunc *cgFunc = iSel.GetCurFunc();
211     auto &rangeGotoNode = static_cast<RangeGotoNode &>(stmt);
212     DEBUG_ASSERT(rangeGotoNode.GetOpCode() == OP_rangegoto, "expect rangegoto");
213     BaseNode *srcNode = rangeGotoNode.Opnd(0);
214     Operand *srcOpnd = iSel.HandleExpr(rangeGotoNode, *srcNode);
215     cgFunc->SetCurBBKind(BB::kBBRangeGoto);
216     iSel.SelectRangeGoto(rangeGotoNode, *srcOpnd);
217 }
218 
HandleReturn(StmtNode & stmt,MPISel & iSel)219 void HandleReturn(StmtNode &stmt, MPISel &iSel)
220 {
221     CGFunc *cgFunc = iSel.GetCurFunc();
222     auto &retNode = static_cast<NaryStmtNode &>(stmt);
223     DEBUG_ASSERT(retNode.NumOpnds() <= 1, "NYI return nodes number > 1");
224     if (retNode.NumOpnds() != 0) {
225         Operand *opnd = iSel.HandleExpr(retNode, *retNode.Opnd(0));
226         iSel.SelectReturn(retNode, *opnd);
227     }
228     iSel.SelectReturn();
229     /* return stmt will jump to the ret BB, so curBB is gotoBB */
230     cgFunc->SetCurBBKind(BB::kBBGoto);
231     cgFunc->SetCurBB(*cgFunc->StartNewBB(retNode));
232 }
233 
HandleComment(StmtNode & stmt,MPISel & iSel)234 static void HandleComment(StmtNode &stmt, MPISel &iSel)
235 {
236     return;
237 }
238 
HandleIcall(StmtNode & stmt,MPISel & iSel)239 static void HandleIcall(StmtNode &stmt, MPISel &iSel)
240 {
241     DEBUG_ASSERT(stmt.GetOpCode() == OP_icall || stmt.GetOpCode() == OP_icallproto, "error");
242     auto &iCallNode = static_cast<IcallNode &>(stmt);
243     iSel.SelectIcall(iCallNode);
244     iSel.SelectCallCommon(stmt, iSel);
245 }
246 
HandleCall(StmtNode & stmt,MPISel & iSel)247 static void HandleCall(StmtNode &stmt, MPISel &iSel)
248 {
249     DEBUG_ASSERT(stmt.GetOpCode() == OP_call, "error");
250     auto &callNode = static_cast<CallNode &>(stmt);
251     iSel.SelectCall(callNode);
252     iSel.SelectCallCommon(stmt, iSel);
253 }
254 
HandleCondbr(StmtNode & stmt,MPISel & iSel)255 static void HandleCondbr(StmtNode &stmt, MPISel &iSel)
256 {
257     CGFunc *cgFunc = iSel.GetCurFunc();
258     auto &condGotoNode = static_cast<CondGotoNode &>(stmt);
259     BaseNode *condNode = condGotoNode.Opnd(0);
260     DEBUG_ASSERT(condNode != nullptr, "expect first operand of cond br");
261     /* select cmpOp Insn and get the result "opnd0". However, the opnd0 is not used
262      * in most backend architectures */
263     Operand *opnd0 = iSel.HandleExpr(stmt, *condNode);
264     iSel.SelectCondGoto(condGotoNode, *condNode, *opnd0);
265     cgFunc->SetCurBB(*cgFunc->StartNewBB(condGotoNode));
266 }
267 
HandleShift(const BaseNode & parent,BaseNode & expr,MPISel & iSel)268 static Operand *HandleShift(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
269 {
270     return iSel.SelectShift(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
271                             *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
272 }
273 
HandleCvt(const BaseNode & parent,BaseNode & expr,MPISel & iSel)274 static Operand *HandleCvt(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
275 {
276     return iSel.SelectCvt(parent, static_cast<TypeCvtNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)));
277 }
278 
HandleExtractBits(const BaseNode & parent,BaseNode & expr,MPISel & iSel)279 static Operand *HandleExtractBits(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
280 {
281     return iSel.SelectExtractbits(parent, static_cast<ExtractbitsNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)));
282 }
283 
HandleDread(const BaseNode & parent,BaseNode & expr,MPISel & iSel)284 static Operand *HandleDread(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
285 {
286     auto &dreadNode = static_cast<AddrofNode &>(expr);
287     return iSel.SelectDread(parent, dreadNode);
288 }
289 
HandleAdd(const BaseNode & parent,BaseNode & expr,MPISel & iSel)290 static Operand *HandleAdd(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
291 {
292     return iSel.SelectAdd(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
293                           *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
294 }
295 
HandleBior(const BaseNode & parent,BaseNode & expr,MPISel & iSel)296 static Operand *HandleBior(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
297 {
298     return iSel.SelectBior(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
299                            *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
300 }
301 
HandleBxor(const BaseNode & parent,BaseNode & expr,MPISel & iSel)302 static Operand *HandleBxor(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
303 {
304     DEBUG_ASSERT(expr.Opnd(1) != nullptr, "nullptr check");
305     return iSel.SelectBxor(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
306                            *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
307 }
308 
HandleSub(const BaseNode & parent,BaseNode & expr,MPISel & iSel)309 static Operand *HandleSub(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
310 {
311     return iSel.SelectSub(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
312                           *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
313 }
314 
HandleDiv(const BaseNode & parent,BaseNode & expr,MPISel & iSel)315 static Operand *HandleDiv(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
316 {
317     return iSel.SelectDiv(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
318                           *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
319 }
320 
HandleRem(const BaseNode & parent,BaseNode & expr,MPISel & iSel)321 static Operand *HandleRem(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
322 {
323     return iSel.SelectRem(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
324                           *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
325 }
326 
HandleBand(const BaseNode & parent,BaseNode & expr,MPISel & iSel)327 static Operand *HandleBand(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
328 {
329     return iSel.SelectBand(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
330                            *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
331 }
332 
HandleMpy(const BaseNode & parent,BaseNode & expr,MPISel & iSel)333 static Operand *HandleMpy(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
334 {
335     return iSel.SelectMpy(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
336                           *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
337 }
338 
HandleTrunc(const BaseNode & parent,BaseNode & expr,MPISel & iSel)339 static Operand *HandleTrunc(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
340 {
341     DEBUG_ASSERT(expr.Opnd(0) != nullptr, "null ptr check");
342     return iSel.SelectCvt(parent, static_cast<TypeCvtNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)));
343 }
344 
HandleConstVal(const BaseNode & parent,BaseNode & expr,MPISel & iSel)345 static Operand *HandleConstVal(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
346 {
347     auto &constValNode = static_cast<ConstvalNode &>(expr);
348     MIRConst *mirConst = constValNode.GetConstVal();
349     DEBUG_ASSERT(mirConst != nullptr, "get constval of constvalnode failed");
350     if (mirConst->GetKind() == kConstInt) {
351         auto *mirIntConst = safe_cast<MIRIntConst>(mirConst);
352         return iSel.SelectIntConst(*mirIntConst, constValNode.GetPrimType());
353     } else if (mirConst->GetKind() == kConstDoubleConst) {
354         auto *mirDoubleConst = safe_cast<MIRDoubleConst>(mirConst);
355         return iSel.SelectFloatingConst(*mirDoubleConst, constValNode.GetPrimType());
356     } else if (mirConst->GetKind() == kConstFloatConst) {
357         auto *mirFloatConst = safe_cast<MIRFloatConst>(mirConst);
358         DEBUG_ASSERT(mirFloatConst != nullptr, "nullptr check");
359         return iSel.SelectFloatingConst(*mirFloatConst, constValNode.GetPrimType());
360     } else {
361         CHECK_FATAL(false, "NIY");
362     }
363     return nullptr;
364 }
365 
HandleRegread(const BaseNode & parent,BaseNode & expr,MPISel & iSel)366 static Operand *HandleRegread(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
367 {
368     (void)parent;
369     auto &regReadNode = static_cast<RegreadNode &>(expr);
370     /* handle return Val */
371     if (regReadNode.GetRegIdx() == -kSregRetval0 || regReadNode.GetRegIdx() == -kSregRetval1) {
372         return &iSel.ProcessReturnReg(regReadNode.GetPrimType(), -(regReadNode.GetRegIdx()));
373     }
374     return iSel.SelectRegread(regReadNode);
375 }
376 
HandleIread(const BaseNode & parent,BaseNode & expr,MPISel & iSel)377 static Operand *HandleIread(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
378 {
379     auto &ireadNode = static_cast<IreadNode &>(expr);
380     return iSel.SelectIread(parent, ireadNode);
381 }
382 
HandleBnot(const BaseNode & parent,BaseNode & expr,MPISel & iSel)383 static Operand *HandleBnot(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
384 {
385     return iSel.SelectBnot(static_cast<UnaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)), parent);
386 }
387 
HandleLnot(const BaseNode & parent,BaseNode & expr,MPISel & iSel)388 static Operand *HandleLnot(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
389 {
390     return iSel.SelectLnot(static_cast<UnaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)), parent);
391 }
392 
HandleCmp(const BaseNode & parent,BaseNode & expr,MPISel & iSel)393 static Operand *HandleCmp(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
394 {
395     // fix opnd type before select insn
396     PrimType targetPtyp = parent.GetPrimType();
397     if (kOpcodeInfo.IsCompare(parent.GetOpCode())) {
398         targetPtyp = static_cast<const CompareNode &>(parent).GetOpndType();
399     } else if (kOpcodeInfo.IsTypeCvt(parent.GetOpCode())) {
400         targetPtyp = static_cast<const TypeCvtNode &>(parent).FromType();
401     }
402     if ((IsPrimitiveInteger(targetPtyp) || IsPrimitiveFloat(targetPtyp)) && targetPtyp != expr.GetPrimType()) {
403         expr.SetPrimType(targetPtyp);
404     }
405     return iSel.SelectCmpOp(static_cast<CompareNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
406                             *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
407 }
408 
HandleAbs(const BaseNode & parent,BaseNode & expr,MPISel & iSel)409 static Operand *HandleAbs(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
410 {
411     return iSel.SelectAbs(static_cast<UnaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)));
412 }
413 
HandleMin(const BaseNode & parent,BaseNode & expr,MPISel & iSel)414 static Operand *HandleMin(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
415 {
416     return iSel.SelectMin(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
417                           *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
418 }
419 
HandleMax(const BaseNode & parent,BaseNode & expr,MPISel & iSel)420 static Operand *HandleMax(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
421 {
422     return iSel.SelectMax(static_cast<BinaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)),
423                           *iSel.HandleExpr(expr, *expr.Opnd(1)), parent);
424 }
HandleRetype(const BaseNode & parent,BaseNode & expr,MPISel & iSel)425 static Operand *HandleRetype(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
426 {
427     DEBUG_ASSERT(expr.Opnd(0) != nullptr, "expr.Opnd(0) should not be nullptr");
428     return iSel.SelectRetype(static_cast<TypeCvtNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)));
429 }
430 
HandleIntrinOp(const BaseNode & parent,BaseNode & expr,MPISel & iSel)431 static Operand *HandleIntrinOp(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
432 {
433     auto &intrinsicopNode = static_cast<IntrinsicopNode &>(expr);
434     switch (intrinsicopNode.GetIntrinsic()) {
435         case INTRN_C_clz32:
436         case INTRN_C_clz64:
437             return iSel.SelectCclz(intrinsicopNode, *iSel.HandleExpr(expr, *expr.Opnd(0)), parent);
438         default:
439             DEBUG_ASSERT(false, "NIY, unsupported intrinsicop.");
440             return nullptr;
441     }
442 }
443 
HandleSqrt(const BaseNode & parent,BaseNode & expr,MPISel & iSel)444 static Operand *HandleSqrt(const BaseNode &parent, BaseNode &expr, MPISel &iSel)
445 {
446     DEBUG_ASSERT(expr.Opnd(0) != nullptr, "expr.Opnd(0) should not be nullptr");
447     return iSel.SelectSqrt(static_cast<UnaryNode &>(expr), *iSel.HandleExpr(expr, *expr.Opnd(0)), parent);
448 }
449 
450 using HandleStmtFactory = FunctionFactory<Opcode, void, StmtNode &, MPISel &>;
451 using HandleExprFactory = FunctionFactory<Opcode, maplebe::Operand *, const BaseNode &, BaseNode &, MPISel &>;
452 namespace isel {
InitHandleStmtFactory()453 static void InitHandleStmtFactory()
454 {
455     RegisterFactoryFunction<HandleStmtFactory>(OP_label, HandleLabel);
456     RegisterFactoryFunction<HandleStmtFactory>(OP_dassign, HandleDassign);
457     RegisterFactoryFunction<HandleStmtFactory>(OP_iassign, HandleIassign);
458     RegisterFactoryFunction<HandleStmtFactory>(OP_regassign, HandleRegassign);
459     RegisterFactoryFunction<HandleStmtFactory>(OP_return, HandleReturn);
460     RegisterFactoryFunction<HandleStmtFactory>(OP_comment, HandleComment);
461     RegisterFactoryFunction<HandleStmtFactory>(OP_call, HandleCall);
462     RegisterFactoryFunction<HandleStmtFactory>(OP_icall, HandleIcall);
463     RegisterFactoryFunction<HandleStmtFactory>(OP_icallproto, HandleIcall);
464     RegisterFactoryFunction<HandleStmtFactory>(OP_goto, HandleGoto);
465     RegisterFactoryFunction<HandleStmtFactory>(OP_intrinsiccall, HandleIntrinCall);
466     RegisterFactoryFunction<HandleStmtFactory>(OP_intrinsiccallassigned, HandleIntrinCall);
467     RegisterFactoryFunction<HandleStmtFactory>(OP_intrinsiccallwithtype, HandleIntrinCall);
468     RegisterFactoryFunction<HandleStmtFactory>(OP_rangegoto, HandleRangeGoto);
469     RegisterFactoryFunction<HandleStmtFactory>(OP_brfalse, HandleCondbr);
470     RegisterFactoryFunction<HandleStmtFactory>(OP_brtrue, HandleCondbr);
471 }
InitHandleExprFactory()472 static void InitHandleExprFactory()
473 {
474     RegisterFactoryFunction<HandleExprFactory>(OP_dread, HandleDread);
475     RegisterFactoryFunction<HandleExprFactory>(OP_add, HandleAdd);
476     RegisterFactoryFunction<HandleExprFactory>(OP_sub, HandleSub);
477     RegisterFactoryFunction<HandleExprFactory>(OP_mul, HandleMpy);
478     RegisterFactoryFunction<HandleExprFactory>(OP_constval, HandleConstVal);
479     RegisterFactoryFunction<HandleExprFactory>(OP_regread, HandleRegread);
480     RegisterFactoryFunction<HandleExprFactory>(OP_shl, HandleShift);
481     RegisterFactoryFunction<HandleExprFactory>(OP_lshr, HandleShift);
482     RegisterFactoryFunction<HandleExprFactory>(OP_ashr, HandleShift);
483     RegisterFactoryFunction<HandleExprFactory>(OP_cvt, HandleCvt);
484     RegisterFactoryFunction<HandleExprFactory>(OP_zext, HandleExtractBits);
485     RegisterFactoryFunction<HandleExprFactory>(OP_sext, HandleExtractBits);
486     RegisterFactoryFunction<HandleExprFactory>(OP_band, HandleBand);
487     RegisterFactoryFunction<HandleExprFactory>(OP_bior, HandleBior);
488     RegisterFactoryFunction<HandleExprFactory>(OP_bxor, HandleBxor);
489     RegisterFactoryFunction<HandleExprFactory>(OP_iread, HandleIread);
490     RegisterFactoryFunction<HandleExprFactory>(OP_bnot, HandleBnot);
491     RegisterFactoryFunction<HandleExprFactory>(OP_lnot, HandleLnot);
492     RegisterFactoryFunction<HandleExprFactory>(OP_div, HandleDiv);
493     RegisterFactoryFunction<HandleExprFactory>(OP_rem, HandleRem);
494     RegisterFactoryFunction<HandleExprFactory>(OP_le, HandleCmp);
495     RegisterFactoryFunction<HandleExprFactory>(OP_ge, HandleCmp);
496     RegisterFactoryFunction<HandleExprFactory>(OP_gt, HandleCmp);
497     RegisterFactoryFunction<HandleExprFactory>(OP_lt, HandleCmp);
498     RegisterFactoryFunction<HandleExprFactory>(OP_ne, HandleCmp);
499     RegisterFactoryFunction<HandleExprFactory>(OP_eq, HandleCmp);
500     RegisterFactoryFunction<HandleExprFactory>(OP_abs, HandleAbs);
501     RegisterFactoryFunction<HandleExprFactory>(OP_min, HandleMin);
502     RegisterFactoryFunction<HandleExprFactory>(OP_max, HandleMax);
503     RegisterFactoryFunction<HandleExprFactory>(OP_retype, HandleRetype);
504     RegisterFactoryFunction<HandleExprFactory>(OP_trunc, HandleTrunc);
505     RegisterFactoryFunction<HandleExprFactory>(OP_intrinsicop, HandleIntrinOp);
506     RegisterFactoryFunction<HandleExprFactory>(OP_sqrt, HandleSqrt);
507 }
508 }  // namespace isel
509 
HandleExpr(const BaseNode & parent,BaseNode & expr)510 Operand *MPISel::HandleExpr(const BaseNode &parent, BaseNode &expr)
511 {
512     auto function = CreateProductFunction<HandleExprFactory>(expr.GetOpCode());
513     CHECK_FATAL(function != nullptr, "unsupported %d opCode in HandleExpr()", expr.GetOpCode());
514     Operand *opnd = function(parent, expr, *this);
515     return opnd;
516 }
517 
doMPIS()518 void MPISel::doMPIS()
519 {
520     isel::InitHandleStmtFactory();
521     isel::InitHandleExprFactory();
522     StmtNode *secondStmt = HandleFuncEntry();
523     for (StmtNode *stmt = secondStmt; stmt != nullptr; stmt = stmt->GetNext()) {
524         auto function = CreateProductFunction<HandleStmtFactory>(stmt->GetOpCode());
525         CHECK_FATAL(function != nullptr, "unsupported opCode or has been lowered before");
526         cgFunc->GetInsnBuilder()->SetDebugComment(stmt->GetDebugComment());
527         function(*stmt, *this);
528         cgFunc->GetInsnBuilder()->ClearDebugComment();
529     }
530     HandleFuncExit();
531 }
532 
GetIntegerPrimTypeFromSize(bool isSigned,uint32 bitSize)533 PrimType MPISel::GetIntegerPrimTypeFromSize(bool isSigned, uint32 bitSize)
534 {
535     static constexpr std::array<PrimType, kBitIndexEnd> signedPrimType = {PTY_i8, PTY_i16, PTY_i32, PTY_i64};
536     static constexpr std::array<PrimType, kBitIndexEnd> unsignedPrimType = {PTY_u8, PTY_u16, PTY_u32, PTY_u64};
537     BitIndex index = GetBitIndex(bitSize);
538     return isSigned ? signedPrimType[index] : unsignedPrimType[index];
539 }
540 
SelectCallCommon(StmtNode & stmt,const MPISel & iSel)541 void MPISel::SelectCallCommon(StmtNode &stmt, const MPISel &iSel)
542 {
543     CGFunc *cgFunc = iSel.GetCurFunc();
544     if (cgFunc->GetCurBB()->GetKind() != BB::kBBFallthru) {
545         cgFunc->SetCurBB(*cgFunc->StartNewBB(stmt));
546     }
547 }
548 
SelectBasicOp(Operand & resOpnd,Operand & opnd0,Operand & opnd1,MOperator mOp,PrimType primType)549 void MPISel::SelectBasicOp(Operand &resOpnd, Operand &opnd0, Operand &opnd1, MOperator mOp, PrimType primType)
550 {
551     RegOperand &firstOpnd = SelectCopy2Reg(opnd0, primType);
552     RegOperand &secondOpnd = SelectCopy2Reg(opnd1, primType);
553     Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mOp, InsnDesc::GetAbstractId(mOp));
554     (void)insn.AddOpndChain(resOpnd).AddOpndChain(firstOpnd).AddOpndChain(secondOpnd);
555     cgFunc->GetCurBB()->AppendInsn(insn);
556 }
557 
GetFieldIdAndMirTypeFromMirNode(const BaseNode & node)558 std::pair<FieldID, MIRType *> MPISel::GetFieldIdAndMirTypeFromMirNode(const BaseNode &node)
559 {
560     FieldID fieldId = 0;
561     MIRType *mirType = nullptr;
562     if (node.GetOpCode() == maple::OP_iread) {
563         /* mirType stored in an addr. */
564         auto &iread = static_cast<const IreadNode &>(node);
565         fieldId = iread.GetFieldID();
566         MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(iread.GetTyIdx());
567         MIRPtrType *pointerType = static_cast<MIRPtrType *>(type);
568         DEBUG_ASSERT(pointerType != nullptr, "expect a pointer type at iread node");
569         mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(pointerType->GetPointedTyIdx());
570         if (mirType->GetKind() == kTypeArray) {
571             MIRArrayType *arrayType = static_cast<MIRArrayType *>(mirType);
572             mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(arrayType->GetElemTyIdx());
573         }
574     } else if (node.GetOpCode() == maple::OP_dassign) {
575         /* mirSymbol */
576         auto &dassign = static_cast<const DassignNode &>(node);
577         fieldId = dassign.GetFieldID();
578         MIRSymbol *symbol = cgFunc->GetFunction().GetLocalOrGlobalSymbol(dassign.GetStIdx());
579         mirType = symbol->GetType();
580     } else if (node.GetOpCode() == maple::OP_dread) {
581         /* mirSymbol */
582         auto &dread = static_cast<const AddrofNode &>(node);
583         fieldId = dread.GetFieldID();
584         MIRSymbol *symbol = cgFunc->GetFunction().GetLocalOrGlobalSymbol(dread.GetStIdx());
585         mirType = symbol->GetType();
586     } else if (node.GetOpCode() == maple::OP_iassign) {
587         auto &iassign = static_cast<const IassignNode &>(node);
588         fieldId = iassign.GetFieldID();
589         MIRType *iassignMirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(iassign.GetTyIdx());
590         MIRPtrType *pointerType = nullptr;
591         DEBUG_ASSERT(iassignMirType->GetKind() == kTypePointer, "non-pointer");
592         pointerType = static_cast<MIRPtrType *>(iassignMirType);
593         mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(pointerType->GetPointedTyIdx());
594     } else {
595         CHECK_FATAL(false, "unsupported OpCode");
596     }
597     return {fieldId, mirType};
598 }
599 
GetMirTypeInfoFormFieldIdAndMirType(FieldID fieldId,MIRType * mirType)600 MirTypeInfo MPISel::GetMirTypeInfoFormFieldIdAndMirType(FieldID fieldId, MIRType *mirType)
601 {
602     MirTypeInfo mirTypeInfo;
603     /* fixup primType and offset */
604     mirTypeInfo.primType = mirType->GetPrimType();
605     return mirTypeInfo;
606 }
607 
GetMirTypeInfoFromMirNode(const BaseNode & node)608 MirTypeInfo MPISel::GetMirTypeInfoFromMirNode(const BaseNode &node)
609 {
610     auto [fieldId, mirType] = GetFieldIdAndMirTypeFromMirNode(node);
611     return GetMirTypeInfoFormFieldIdAndMirType(fieldId, mirType);
612 }
613 
SelectDassign(const DassignNode & stmt,Operand & opndRhs)614 void MPISel::SelectDassign(const DassignNode &stmt, Operand &opndRhs)
615 {
616     /* mirSymbol info */
617     MIRSymbol *symbol = cgFunc->GetFunction().GetLocalOrGlobalSymbol(stmt.GetStIdx());
618     MirTypeInfo symbolInfo = GetMirTypeInfoFromMirNode(stmt);
619     /* Get symbol location */
620     DEBUG_ASSERT(symbol != nullptr, "nullptr check");
621     MemOperand &symbolMem = GetOrCreateMemOpndFromSymbol(*symbol, stmt.GetFieldID());
622     /* rhs mirType info */
623     PrimType rhsType = stmt.GetRHS()->GetPrimType();
624     /* Generate Insn */
625     PrimType memType = symbolInfo.primType;
626     SelectCopy(symbolMem, opndRhs, memType, rhsType);
627 }
628 
SelectIassign(const IassignNode & stmt,Operand & opndAddr,Operand & opndRhs)629 void MPISel::SelectIassign(const IassignNode &stmt, Operand &opndAddr, Operand &opndRhs)
630 {
631     /* mirSymbol info */
632     MirTypeInfo symbolInfo = GetMirTypeInfoFromMirNode(stmt);
633     /* handle Lhs, generate (%Rxx) via Rxx*/
634     PrimType memType = symbolInfo.primType;
635     RegOperand &lhsBaseOpnd = SelectCopy2Reg(opndAddr, stmt.Opnd(0)->GetPrimType());
636     MemOperand &lhsMemOpnd =
637         cgFunc->GetOpndBuilder()->CreateMem(lhsBaseOpnd, symbolInfo.offset, GetPrimTypeBitSize(memType));
638     /* handle Rhs, get R## from Rhs */
639     PrimType rhsType = stmt.GetRHS()->GetPrimType();
640     /* mov %R##, (%Rxx) */
641     SelectCopy(lhsMemOpnd, opndRhs, memType, rhsType);
642 }
643 
SelectIntConst(const MIRIntConst & intConst,PrimType primType)644 ImmOperand *MPISel::SelectIntConst(const MIRIntConst &intConst, PrimType primType)
645 {
646     return &cgFunc->GetOpndBuilder()->CreateImm(GetPrimTypeBitSize(primType), intConst.GetExtValue());
647 }
648 
SelectShift(const BinaryNode & node,Operand & opnd0,Operand & opnd1,const BaseNode & parent)649 Operand *MPISel::SelectShift(const BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent)
650 {
651     PrimType primType = node.GetPrimType();
652     RegOperand *resOpnd = nullptr;
653     Opcode opcode = node.GetOpCode();
654 
655     if (IsPrimitiveInteger(primType)) {
656         resOpnd =
657             &(cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType)));
658         RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, primType, node.Opnd(0)->GetPrimType());
659         SelectShift(*resOpnd, regOpnd0, opnd1, opcode, primType, node.Opnd(1)->GetPrimType());
660     } else {
661         CHECK_FATAL(false, "NIY vector cvt");
662     }
663     return resOpnd;
664 }
665 
SelectShift(Operand & resOpnd,Operand & opnd0,Operand & opnd1,Opcode shiftDirect,PrimType opnd0Type,PrimType opnd1Type)666 void MPISel::SelectShift(Operand &resOpnd, Operand &opnd0, Operand &opnd1, Opcode shiftDirect, PrimType opnd0Type,
667                          PrimType opnd1Type)
668 {
669     if (opnd1.IsIntImmediate() && static_cast<ImmOperand &>(opnd1).GetValue() == 0) {
670         SelectCopy(resOpnd, opnd0, opnd0Type);
671         return;
672     }
673 
674     uint32 dsize = GetPrimTypeBitSize(opnd0Type);
675     MOperator mOp = abstract::MOP_undef;
676     if (shiftDirect == OP_shl) {
677         const static auto fastShlMappingFunc = DEF_MOPERATOR_MAPPING_FUNC(shl);
678         mOp = fastShlMappingFunc(dsize);
679     } else if (shiftDirect == OP_ashr) {
680         const static auto fastAshrMappingFunc = DEF_MOPERATOR_MAPPING_FUNC(ashr);
681         mOp = fastAshrMappingFunc(dsize);
682     } else if (shiftDirect == OP_lshr) {
683         const static auto fastLshrMappingFunc = DEF_MOPERATOR_MAPPING_FUNC(lshr);
684         mOp = fastLshrMappingFunc(dsize);
685     } else {
686         CHECK_FATAL(false, "NIY, Not support shiftdirect case");
687     }
688     RegOperand &firstOpnd = SelectCopy2Reg(opnd0, opnd0Type);
689     RegOperand &secondOpnd = SelectCopy2Reg(opnd1, opnd1Type);
690     Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mOp, InsnDesc::GetAbstractId(mOp));
691     insn.AddOpndChain(resOpnd).AddOpndChain(firstOpnd).AddOpndChain(secondOpnd);
692     cgFunc->GetCurBB()->AppendInsn(insn);
693 }
694 
SelectRegassign(RegassignNode & stmt,Operand & opnd0)695 void MPISel::SelectRegassign(RegassignNode &stmt, Operand &opnd0)
696 {
697     PrimType rhsType = stmt.Opnd(0)->GetPrimType();
698     PregIdx pregIdx = stmt.GetRegIdx();
699     PrimType regType = stmt.GetPrimType();
700     RegOperand &regOpnd = *cgFunc->GetOrCreateRegOpndFromPregIdx(pregIdx, regType);
701     SelectCopy(regOpnd, opnd0, regType, rhsType);
702 
703     const auto &derived2BaseRef = cgFunc->GetFunction().GetDerived2BaseRef();
704     auto itr = derived2BaseRef.find(pregIdx);
705     if (itr != derived2BaseRef.end()) {
706         auto *derivedRegOpnd =  cgFunc->GetOrCreateRegOpndFromPregIdx(itr->first, PTY_ref);
707         auto *baseRegOpnd =  cgFunc->GetOrCreateRegOpndFromPregIdx(itr->second, PTY_ref);
708         derivedRegOpnd->SetBaseRefOpnd(*baseRegOpnd);
709     }
710     if ((Globals::GetInstance()->GetOptimLevel() == CGOptions::kLevel0) && (pregIdx >= 0)) {
711         const SymbolAlloc *symLoc = cgFunc->GetMemlayout()->GetSpillLocOfPseduoRegister(pregIdx);
712         int64 offset = static_cast<int64>(cgFunc->GetBaseOffset(*symLoc));
713         MIRPreg *preg = cgFunc->GetFunction().GetPregTab()->PregFromPregIdx(pregIdx);
714         uint32 bitLen = GetPrimTypeSize(preg->GetPrimType()) * kBitsPerByte;
715         RegOperand &base = GetTargetBasicPointer(PTY_u64);
716         MemOperand *dest = &cgFunc->GetOpndBuilder()->CreateMem(base, offset, bitLen);
717         SelectCopy(*dest, regOpnd, preg->GetPrimType(), regType);
718     }
719 }
720 
SelectRegread(RegreadNode & expr)721 RegOperand *MPISel::SelectRegread(RegreadNode &expr)
722 {
723     PregIdx pregIdx = expr.GetRegIdx();
724     PrimType rhsType = expr.GetPrimType();
725     if (pregIdx < 0) {
726         return &SelectSpecialRegread(pregIdx, rhsType);
727     }
728 
729     RegOperand &reg = *cgFunc->GetOrCreateRegOpndFromPregIdx(pregIdx, rhsType);
730     if (Globals::GetInstance()->GetOptimLevel() == CGOptions::kLevel0) {
731         const SymbolAlloc *symLoc = cgFunc->GetMemlayout()->GetSpillLocOfPseduoRegister(pregIdx);
732         int64 offset = static_cast<int64>(cgFunc->GetBaseOffset(*symLoc));
733         MIRPreg *preg = cgFunc->GetFunction().GetPregTab()->PregFromPregIdx(pregIdx);
734         uint32 bitLen = GetPrimTypeSize(preg->GetPrimType()) * kBitsPerByte;
735         RegOperand &base = GetTargetBasicPointer(PTY_u64);
736         MemOperand *src = &cgFunc->GetOpndBuilder()->CreateMem(base, offset, bitLen);
737         SelectCopy(reg, *src, rhsType, preg->GetPrimType());
738     }
739     return &reg;
740 }
741 
SelectDread(const BaseNode & parent,const AddrofNode & expr)742 Operand *MPISel::SelectDread(const BaseNode &parent, const AddrofNode &expr)
743 {
744     /* get mirSymbol info*/
745     MIRSymbol *symbol = cgFunc->GetFunction().GetLocalOrGlobalSymbol(expr.GetStIdx());
746     MirTypeInfo symbolInfo = GetMirTypeInfoFromMirNode(expr);
747     PrimType symbolType = symbolInfo.primType;
748     /* Get symbol location */
749     MemOperand &symbolMem = GetOrCreateMemOpndFromSymbol(*symbol, expr.GetFieldID());
750     PrimType primType = expr.GetPrimType();
751 
752     /* for BasicType, load symbolVal to register. */
753     RegOperand &regOpnd =
754         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
755     /* Generate Insn */
756     SelectCopy(regOpnd, symbolMem, primType, symbolType);
757     return &regOpnd;
758 }
759 
SelectAdd(const BinaryNode & node,Operand & opnd0,Operand & opnd1,const BaseNode & parent)760 Operand *MPISel::SelectAdd(const BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent)
761 {
762     PrimType primType = node.GetPrimType();
763     RegOperand &resReg =
764         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
765     RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, primType, node.Opnd(0)->GetPrimType());
766     RegOperand &regOpnd1 = SelectCopy2Reg(opnd1, primType, node.Opnd(1)->GetPrimType());
767     SelectAdd(resReg, regOpnd0, regOpnd1, primType);
768     return &resReg;
769 }
770 
SelectBand(const BinaryNode & node,Operand & opnd0,Operand & opnd1,const BaseNode & parent)771 Operand *MPISel::SelectBand(const BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent)
772 {
773     PrimType primType = node.GetPrimType();
774     RegOperand &resReg =
775         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
776     RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, primType, node.Opnd(0)->GetPrimType());
777     RegOperand &regOpnd1 = SelectCopy2Reg(opnd1, primType, node.Opnd(1)->GetPrimType());
778     SelectBand(resReg, regOpnd0, regOpnd1, primType);
779     return &resReg;
780 }
781 
SelectSub(const BinaryNode & node,Operand & opnd0,Operand & opnd1,const BaseNode & parent)782 Operand *MPISel::SelectSub(const BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent)
783 {
784     PrimType primType = node.GetPrimType();
785     RegOperand &resOpnd =
786         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
787     RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, primType, node.Opnd(0)->GetPrimType());
788     RegOperand &regOpnd1 = SelectCopy2Reg(opnd1, primType, node.Opnd(1)->GetPrimType());
789     SelectSub(resOpnd, regOpnd0, regOpnd1, primType);
790     return &resOpnd;
791 }
792 
SelectExtractbits(RegOperand & resOpnd,RegOperand & opnd0,uint8 bitOffset,uint8 bitSize,PrimType primType)793 void MPISel::SelectExtractbits(RegOperand &resOpnd, RegOperand &opnd0, uint8 bitOffset, uint8 bitSize,
794                                PrimType primType)
795 {
796     uint32 primBitSize = GetPrimTypeBitSize(primType);
797     bool isSigned = IsSignedInteger(primType);
798     if (bitOffset == 0 && !isSigned) {
799         /*
800          * resOpnd = opnd0 & ((1 << bitSize) - 1)
801          */
802         ImmOperand &imm = cgFunc->GetOpndBuilder()->CreateImm(primBitSize, (static_cast<int64>(1) << bitSize) - 1);
803         SelectBand(resOpnd, opnd0, imm, primType);
804     } else {
805         /*
806          * tmpOpnd = opnd0 << (primBitSize - bitSize - bitOffset)
807          * resOpnd = tmpOpnd >> (primBitSize - bitSize)
808          * if signed : use sar; else use shr
809          */
810         RegOperand &tmpOpnd =
811             cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
812         ImmOperand &imm1Opnd = cgFunc->GetOpndBuilder()->CreateImm(primBitSize, primBitSize - bitSize - bitOffset);
813         SelectShift(tmpOpnd, opnd0, imm1Opnd, OP_shl, primType, primType);
814         Opcode opcode = isSigned ? OP_ashr : OP_lshr;
815         ImmOperand &imm2Opnd = cgFunc->GetOpndBuilder()->CreateImm(primBitSize, primBitSize - bitSize);
816         SelectShift(resOpnd, tmpOpnd, imm2Opnd, opcode, primType, primType);
817     }
818 }
819 
SelectExtractbits(const BaseNode & parent,const ExtractbitsNode & node,Operand & opnd0)820 Operand *MPISel::SelectExtractbits(const BaseNode &parent, const ExtractbitsNode &node, Operand &opnd0)
821 {
822     PrimType fromType = node.Opnd(0)->GetPrimType();
823     PrimType toType = node.GetPrimType();
824     uint8 bitSize = node.GetBitsSize();
825     RegOperand &resOpnd =
826         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(toType), cgFunc->GetRegTyFromPrimTy(toType));
827     if (IsPrimitiveInteger(toType)) {
828         // OP_extractbits or bitSize < 8-bit or bitSize is not pow of 2
829         if (node.GetOpCode() == OP_extractbits || bitSize < k8BitSize || (bitSize & (bitSize - 1)) != 0) {
830             SelectCopy(resOpnd, opnd0, toType, fromType);
831             SelectExtractbits(resOpnd, resOpnd, node.GetBitsOffset(), bitSize, toType);
832         } else {
833             PrimType opndType = GetIntegerPrimTypeFromSize(node.GetOpCode() == OP_sext, bitSize);
834             RegOperand &tmpRegOpnd = SelectCopy2Reg(opnd0, opndType, fromType);
835             SelectIntCvt(resOpnd, tmpRegOpnd, toType, opndType);
836         }
837     } else {
838         CHECK_FATAL(false, "NIY vector cvt");
839     }
840     return &resOpnd;
841 }
842 
SelectCvt(const BaseNode & parent,const TypeCvtNode & node,Operand & opnd0)843 Operand *MPISel::SelectCvt(const BaseNode &parent, const TypeCvtNode &node, Operand &opnd0)
844 {
845     PrimType fromType = node.Opnd(0)->GetPrimType();
846     PrimType toType = node.GetPrimType();
847     if (fromType == toType) {
848         return &opnd0;
849     }
850     RegOperand *resOpnd =
851         &cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(toType), cgFunc->GetRegTyFromPrimTy(toType));
852     if (IsPrimitiveInteger(toType) && IsPrimitiveInteger(fromType)) {
853         SelectIntCvt(*resOpnd, opnd0, toType, fromType);
854     } else if (IsPrimitiveFloat(toType) && IsPrimitiveInteger(fromType)) {
855         SelectCvtInt2Float(*resOpnd, opnd0, toType, fromType);
856     } else if (IsPrimitiveFloat(toType) && IsPrimitiveFloat(fromType)) {
857         SelectFloatCvt(*resOpnd, opnd0, toType, fromType);
858     } else if (IsPrimitiveInteger(toType) && IsPrimitiveFloat(fromType)) {
859         SelectCvtFloat2Int(*resOpnd, opnd0, toType, fromType);
860     } else {
861         CHECK_FATAL(false, "NIY cvt");
862     }
863     return resOpnd;
864 }
865 
SelectCvtFloat2Int(RegOperand & resOpnd,Operand & opnd0,PrimType toType,PrimType fromType)866 void MPISel::SelectCvtFloat2Int(RegOperand &resOpnd, Operand &opnd0, PrimType toType, PrimType fromType)
867 {
868     uint32 toSize = GetPrimTypeBitSize(toType);
869     bool isSigned = !IsPrimitiveUnsigned(toType);
870 
871     // Due to fp precision, should use one insn to perform cvt.
872     RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, fromType);
873     MOperator mOp = abstract::MOP_undef;
874     switch (fromType) {
875         case PTY_f64:
876             mOp = (toSize <= k32BitSize) ? ((isSigned) ? abstract::MOP_cvt_i32_f64 : abstract::MOP_cvt_u32_f64) :
877                                            ((isSigned) ? abstract::MOP_cvt_i64_f64 : abstract::MOP_cvt_u64_f64);
878             break;
879         case PTY_f32:
880             mOp = (toSize <= k32BitSize) ? ((isSigned) ? abstract::MOP_cvt_i32_f32 : abstract::MOP_cvt_u32_f32) :
881                                            ((isSigned) ? abstract::MOP_cvt_i64_f32 : abstract::MOP_cvt_u64_f32);
882             break;
883         default:
884             CHECK_FATAL(false, "NYI");
885     }
886     Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mOp, InsnDesc::GetAbstractId(mOp));
887     (void)insn.AddOpndChain(resOpnd).AddOpndChain(regOpnd0);
888     cgFunc->GetCurBB()->AppendInsn(insn);
889 }
890 
SelectCvtInt2Float(RegOperand & resOpnd,Operand & opnd0,PrimType toType,PrimType fromType)891 void MPISel::SelectCvtInt2Float(RegOperand &resOpnd, Operand &opnd0, PrimType toType, PrimType fromType)
892 {
893     uint32 fromSize = GetPrimTypeBitSize(fromType);
894     bool isSigned = !IsPrimitiveUnsigned(fromType);
895     MOperator mOp = abstract::MOP_undef;
896     switch (toType) {
897         case PTY_f64:
898             mOp = (fromSize <= k32BitSize) ? ((isSigned) ? abstract::MOP_cvt_f64_i32 : abstract::MOP_cvt_f64_u32) :
899                                              ((isSigned) ? abstract::MOP_cvt_f64_i64 : abstract::MOP_cvt_f64_u64);
900             break;
901         case PTY_f32:
902             mOp = (fromSize <= k32BitSize) ? ((isSigned) ? abstract::MOP_cvt_f32_i32 : abstract::MOP_cvt_f32_u32) :
903                                              ((isSigned) ? abstract::MOP_cvt_f32_i64 : abstract::MOP_cvt_f32_u64);
904             break;
905         default:
906             CHECK_FATAL(false, "NYI");
907     }
908     RegOperand *regOpnd0 = nullptr;
909     if (!isSigned && fromSize <= k32BitSize && toType == PTY_f64) {
910         regOpnd0 = &cgFunc->GetOpndBuilder()->CreateVReg(k64BitSize, kRegTyInt);
911         SelectIntCvt(*regOpnd0, opnd0, maple::PTY_i64, fromType);
912     } else {
913         regOpnd0 = &SelectCopy2Reg(opnd0, fromType);
914     }
915     Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mOp, InsnDesc::GetAbstractId(mOp));
916     (void)insn.AddOpndChain(resOpnd).AddOpndChain(*regOpnd0);
917     cgFunc->GetCurBB()->AppendInsn(insn);
918 }
919 
SelectIntCvt(RegOperand & resOpnd,Operand & opnd0,PrimType toType,PrimType fromType)920 void MPISel::SelectIntCvt(RegOperand &resOpnd, Operand &opnd0, PrimType toType, PrimType fromType)
921 {
922     uint32 fromSize = GetPrimTypeBitSize(fromType);
923     uint32 toSize = GetPrimTypeBitSize(toType);
924     /*
925      * It is redundancy to insert "nop" casts (unsigned 32 -> singed 32) in abstract CG IR
926      * The signedness of operands would be shown in the expression.
927      */
928     RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, fromType);
929     if (toSize <= fromSize) {
930         resOpnd = cgFunc->GetOpndBuilder()->CreateVReg(regOpnd0.GetRegisterNumber(), GetPrimTypeBitSize(toType),
931                                                        cgFunc->GetRegTyFromPrimTy(toType));
932         return;
933     }
934     bool isSigned = !IsPrimitiveUnsigned(fromType);
935     MOperator mOp = GetFastCvtMopI(fromSize, toSize, isSigned);
936     Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mOp, InsnDesc::GetAbstractId(mOp));
937     (void)insn.AddOpndChain(resOpnd).AddOpndChain(regOpnd0);
938     cgFunc->GetCurBB()->AppendInsn(insn);
939     return;
940 }
941 
SelectFloatCvt(RegOperand & resOpnd,Operand & opnd0,PrimType toType,PrimType fromType)942 void MPISel::SelectFloatCvt(RegOperand &resOpnd, Operand &opnd0, PrimType toType, PrimType fromType)
943 {
944     uint32 fromSize = GetPrimTypeBitSize(fromType);
945     uint32 toSize = GetPrimTypeBitSize(toType);
946     RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, fromType);
947     if (fromSize == toSize) {
948         resOpnd = regOpnd0;
949         return;
950     }
951     MOperator mOp = abstract::MOP_undef;
952     if (fromSize == k32BitSize && toSize == k64BitSize) {
953         mOp = abstract::MOP_cvt_ff_64_32;
954     } else if (fromSize == k64BitSize && toSize == k32BitSize) {
955         mOp = abstract::MOP_cvt_ff_32_64;
956     } else {
957         CHECK_FATAL(false, "niy");
958     }
959     Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mOp, InsnDesc::GetAbstractId(mOp));
960     (void)insn.AddOpndChain(resOpnd).AddOpndChain(regOpnd0);
961     cgFunc->GetCurBB()->AppendInsn(insn);
962     return;
963 }
964 
SelectSub(Operand & resOpnd,Operand & opnd0,Operand & opnd1,PrimType primType)965 void MPISel::SelectSub(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType)
966 {
967     MOperator mOp = abstract::MOP_undef;
968     if (IsPrimitiveInteger(primType)) {
969         const static auto fastSubMappingFunc = DEF_MOPERATOR_MAPPING_FUNC(sub);
970         mOp = fastSubMappingFunc(GetPrimTypeBitSize(primType));
971     } else {
972         const static auto fastSubFloatMappingFunc = DEF_FLOAT_MOPERATOR_MAPPING_FUNC(sub);
973         mOp = fastSubFloatMappingFunc(GetPrimTypeBitSize(primType));
974     }
975     SelectBasicOp(resOpnd, opnd0, opnd1, mOp, primType);
976 }
977 
SelectBand(Operand & resOpnd,Operand & opnd0,Operand & opnd1,PrimType primType)978 void MPISel::SelectBand(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType)
979 {
980     MOperator mOp = abstract::MOP_undef;
981     if (IsPrimitiveInteger(primType)) {
982         const static auto fastAndMappingFunc = DEF_MOPERATOR_MAPPING_FUNC(and);
983         mOp = fastAndMappingFunc(GetPrimTypeBitSize(primType));
984     } else {
985         const static auto fastAndFloatMappingFunc = DEF_FLOAT_MOPERATOR_MAPPING_FUNC(and);
986         mOp = fastAndFloatMappingFunc(GetPrimTypeBitSize(primType));
987     }
988     SelectBasicOp(resOpnd, opnd0, opnd1, mOp, primType);
989 }
990 
SelectAdd(Operand & resOpnd,Operand & opnd0,Operand & opnd1,PrimType primType)991 void MPISel::SelectAdd(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType)
992 {
993     MOperator mOp = abstract::MOP_undef;
994     if (IsPrimitiveInteger(primType)) {
995         const static auto fastAddMappingFunc = DEF_MOPERATOR_MAPPING_FUNC(add);
996         mOp = fastAddMappingFunc(GetPrimTypeBitSize(primType));
997     } else {
998         const static auto fastAddFloatMappingFunc = DEF_FLOAT_MOPERATOR_MAPPING_FUNC(add);
999         mOp = fastAddFloatMappingFunc(GetPrimTypeBitSize(primType));
1000     }
1001     SelectBasicOp(resOpnd, opnd0, opnd1, mOp, primType);
1002 }
1003 
SelectBior(const BinaryNode & node,Operand & opnd0,Operand & opnd1,const BaseNode & parent)1004 Operand *MPISel::SelectBior(const BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent)
1005 {
1006     PrimType primType = node.GetPrimType();
1007     RegOperand *resOpnd =
1008         &cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
1009     RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, primType, node.Opnd(0)->GetPrimType());
1010     RegOperand &regOpnd1 = SelectCopy2Reg(opnd1, primType, node.Opnd(1)->GetPrimType());
1011     SelectBior(*resOpnd, regOpnd0, regOpnd1, primType);
1012     return resOpnd;
1013 }
1014 
SelectBior(Operand & resOpnd,Operand & opnd0,Operand & opnd1,PrimType primType)1015 void MPISel::SelectBior(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType)
1016 {
1017     const static auto fastBiorMappingFunc = DEF_MOPERATOR_MAPPING_FUNC(or);
1018     MOperator mOp = fastBiorMappingFunc(GetPrimTypeBitSize(primType));
1019     SelectBasicOp(resOpnd, opnd0, opnd1, mOp, primType);
1020 }
1021 
SelectBxor(const BinaryNode & node,Operand & opnd0,Operand & opnd1,const BaseNode & parent)1022 Operand *MPISel::SelectBxor(const BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent)
1023 {
1024     PrimType primType = node.GetPrimType();
1025     RegOperand *resOpnd =
1026         &cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
1027     RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, primType, node.Opnd(0)->GetPrimType());
1028     RegOperand &regOpnd1 = SelectCopy2Reg(opnd1, primType, node.Opnd(1)->GetPrimType());
1029     SelectBxor(*resOpnd, regOpnd0, regOpnd1, primType);
1030     return resOpnd;
1031 }
1032 
SelectBxor(Operand & resOpnd,Operand & opnd0,Operand & opnd1,PrimType primType)1033 void MPISel::SelectBxor(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType)
1034 {
1035     const static auto fastBxorMappingFunc = DEF_MOPERATOR_MAPPING_FUNC(xor);
1036     MOperator mOp = fastBxorMappingFunc(GetPrimTypeBitSize(primType));
1037     SelectBasicOp(resOpnd, opnd0, opnd1, mOp, primType);
1038 }
1039 
GetOrCreateMemOpndFromIreadNode(const IreadNode & expr,PrimType primType,int offset)1040 MemOperand *MPISel::GetOrCreateMemOpndFromIreadNode(const IreadNode &expr, PrimType primType, int offset)
1041 {
1042     /* get rhs*/
1043     Operand *addrOpnd = HandleExpr(expr, *expr.Opnd(0));
1044     RegOperand &addrOnReg = SelectCopy2Reg(*addrOpnd, PTY_a64);
1045     /* Generate memOpnd */
1046     MemOperand &memOpnd = cgFunc->GetOpndBuilder()->CreateMem(addrOnReg, offset, GetPrimTypeBitSize(primType));
1047     return &memOpnd;
1048 }
1049 
SelectIread(const BaseNode & parent,const IreadNode & expr,int extraOffset)1050 Operand *MPISel::SelectIread(const BaseNode &parent, const IreadNode &expr, int extraOffset)
1051 {
1052     /* get lhs mirType info */
1053     MirTypeInfo lhsInfo = GetMirTypeInfoFromMirNode(expr);
1054     /* get memOpnd */
1055     MemOperand &memOpnd = *GetOrCreateMemOpndFromIreadNode(expr, lhsInfo.primType, lhsInfo.offset + extraOffset);
1056     /* for BasicType, load val in addr to register. */
1057     PrimType primType = expr.GetPrimType();
1058     RegOperand &result =
1059         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
1060     SelectCopy(result, memOpnd, primType, lhsInfo.primType);
1061     return &result;
1062 }
1063 
SelectAbs(UnaryNode & node,Operand & opnd0)1064 Operand *MPISel::SelectAbs(UnaryNode &node, Operand &opnd0)
1065 {
1066     PrimType primType = node.GetPrimType();
1067     if (IsPrimitiveFloat(primType)) {
1068         /*
1069          * fabs(x) = x AND 0x7fffffff ffffffff [set sign bit to 0]
1070          */
1071         const static uint64 kNaN = 0x7fffffffffffffffUL;
1072         const static double kNaNDouble = *(double *)(&kNaN);
1073         const static uint64 kNaNf = 0x7fffffffUL;
1074         const static double kNaNFloat = *(double *)(&kNaNf);
1075         CHECK_FATAL(primType == PTY_f64 || primType == PTY_f32, "niy");
1076 
1077         double mask = primType == PTY_f64 ? kNaNDouble : kNaNFloat;
1078         MIRDoubleConst *c = cgFunc->GetMemoryPool()->New<MIRDoubleConst>(
1079             mask, *GlobalTables::GetTypeTable().GetTypeTable().at(PTY_f64));
1080         Operand *opnd1 = SelectFloatingConst(*c, PTY_f64);
1081 
1082         RegOperand &resOpnd =
1083             cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
1084         SelectBand(resOpnd, opnd0, *opnd1, primType);
1085         return &resOpnd;
1086     } else if (IsUnsignedInteger(primType)) {
1087         return &opnd0;
1088     } else {
1089         /*
1090          * abs(x) = (x XOR y) - y
1091          * y = x >>> (bitSize - 1)
1092          */
1093         uint32 bitSize = GetPrimTypeBitSize(primType);
1094         CHECK_FATAL(bitSize == k64BitSize || bitSize == k32BitSize, "only support 32-bits or 64-bits");
1095         RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, primType);
1096         ImmOperand &immOpnd = cgFunc->GetOpndBuilder()->CreateImm(bitSize, bitSize - 1);
1097         RegOperand &regOpndy = cgFunc->GetOpndBuilder()->CreateVReg(bitSize, cgFunc->GetRegTyFromPrimTy(primType));
1098         SelectShift(regOpndy, regOpnd0, immOpnd, OP_ashr, primType, primType);
1099         RegOperand &tmpOpnd = cgFunc->GetOpndBuilder()->CreateVReg(bitSize, cgFunc->GetRegTyFromPrimTy(primType));
1100         SelectBxor(tmpOpnd, regOpnd0, regOpndy, primType);
1101         RegOperand &resOpnd = cgFunc->GetOpndBuilder()->CreateVReg(bitSize, cgFunc->GetRegTyFromPrimTy(primType));
1102         SelectSub(resOpnd, tmpOpnd, regOpndy, primType);
1103         return &resOpnd;
1104     }
1105 }
1106 
HandleFuncEntry()1107 StmtNode *MPISel::HandleFuncEntry()
1108 {
1109     MIRFunction &mirFunc = cgFunc->GetFunction();
1110     BlockNode *block = mirFunc.GetBody();
1111 
1112     DEBUG_ASSERT(block != nullptr, "get func body block failed in CGFunc::GenerateInstruction");
1113 
1114     StmtNode *stmt = block->GetFirst();
1115     if (stmt == nullptr) {
1116         return nullptr;
1117     }
1118     DEBUG_ASSERT(stmt->GetOpCode() == OP_label, "The first statement should be a label");
1119     HandleLabel(*stmt, *this);
1120     cgFunc->SetFirstBB(*cgFunc->GetCurBB());
1121     stmt = stmt->GetNext();
1122     if (stmt == nullptr) {
1123         return nullptr;
1124     }
1125     cgFunc->SetCurBB(*cgFunc->StartNewBBImpl(false, *stmt));
1126     bool withFreqInfo = mirFunc.HasFreqMap() && !mirFunc.GetLastFreqMap().empty();
1127     if (withFreqInfo) {
1128         cgFunc->GetCurBB()->SetFrequency(kFreqBase);
1129     }
1130 
1131     return stmt;
1132 }
1133 
1134 /* This function loads src to a register, the src can be an imm, mem or a label.
1135  * Once the source and result(destination) types are different,
1136  * implicit conversion is executed here.*/
SelectCopy2Reg(Operand & src,PrimType toType,PrimType fromType)1137 RegOperand &MPISel::SelectCopy2Reg(Operand &src, PrimType toType, PrimType fromType)
1138 {
1139     uint32 fromSize = GetPrimTypeBitSize(fromType);
1140     uint32 toSize = GetPrimTypeBitSize(toType);
1141     if (src.IsRegister() && fromSize == toSize) {
1142         return static_cast<RegOperand &>(src);
1143     }
1144     RegOperand &dest =
1145         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(toType), cgFunc->GetRegTyFromPrimTy(toType));
1146     if (fromSize != toSize) {
1147         SelectCopy(dest, src, toType, fromType);
1148     } else {
1149         SelectCopy(dest, src, toType);
1150     }
1151     return dest;
1152 }
1153 /* Pretty sure that implicit type conversions will not occur. */
SelectCopy2Reg(Operand & src,PrimType dtype)1154 RegOperand &MPISel::SelectCopy2Reg(Operand &src, PrimType dtype)
1155 {
1156     DEBUG_ASSERT(src.GetSize() == GetPrimTypeBitSize(dtype), "NIY");
1157     if (src.IsRegister()) {
1158         return static_cast<RegOperand &>(src);
1159     }
1160     RegOperand &dest =
1161         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(dtype), cgFunc->GetRegTyFromPrimTy(dtype));
1162     SelectCopy(dest, src, dtype);
1163     return dest;
1164 }
1165 /* This function copy/load/store src to a dest, Once the src and dest types
1166  * are different, implicit conversion is executed here. */
SelectCopy(Operand & dest,Operand & src,PrimType toType,PrimType fromType)1167 void MPISel::SelectCopy(Operand &dest, Operand &src, PrimType toType, PrimType fromType)
1168 {
1169     if (GetPrimTypeBitSize(fromType) != GetPrimTypeBitSize(toType)) {
1170         RegOperand &srcRegOpnd = SelectCopy2Reg(src, fromType);
1171         RegOperand &dstRegOpnd =
1172             cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(toType), cgFunc->GetRegTyFromPrimTy(toType));
1173         SelectIntCvt(dstRegOpnd, srcRegOpnd, toType, fromType);
1174         SelectCopy(dest, dstRegOpnd, toType);
1175     } else {
1176         SelectCopy(dest, src, toType);
1177     }
1178 }
1179 
1180 /* Pretty sure that implicit type conversions will not occur. */
SelectCopy(Operand & dest,Operand & src,PrimType type)1181 void MPISel::SelectCopy(Operand &dest, Operand &src, PrimType type)
1182 {
1183     DEBUG_ASSERT(dest.GetSize() == src.GetSize(), "NIY");
1184     if (dest.GetKind() == Operand::kOpdRegister) {
1185         SelectCopyInsn(dest, src, type);
1186     } else if (dest.GetKind() == Operand::kOpdMem) {
1187         if (src.GetKind() != Operand::kOpdRegister) {
1188             RegOperand &tempReg =
1189                 cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(type), cgFunc->GetRegTyFromPrimTy(type));
1190             SelectCopyInsn(tempReg, src, type);
1191             SelectCopyInsn(dest, tempReg, type);
1192         } else {
1193             SelectCopyInsn(dest, src, type);
1194         }
1195     } else {
1196         CHECK_FATAL(false, "NIY, CPU supports more than memory and registers");
1197     }
1198     return;
1199 }
1200 
SelectCopyInsn(Operand & dest,Operand & src,PrimType type)1201 void MPISel::SelectCopyInsn(Operand &dest, Operand &src, PrimType type)
1202 {
1203     MOperator mop = GetFastIselMop(dest.GetKind(), src.GetKind(), type);
1204     CHECK_FATAL(mop != abstract::MOP_undef, "get mop failed");
1205     Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mop, InsnDesc::GetAbstractId(mop));
1206     (void)insn.AddOpndChain(dest).AddOpndChain(src);
1207     cgFunc->GetCurBB()->AppendInsn(insn);
1208 }
1209 
SelectBnot(const UnaryNode & node,Operand & opnd0,const BaseNode & parent)1210 Operand *MPISel::SelectBnot(const UnaryNode &node, Operand &opnd0, const BaseNode &parent)
1211 {
1212     PrimType dtype = node.GetPrimType();
1213 
1214     RegOperand *resOpnd = nullptr;
1215     resOpnd = &cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(dtype), cgFunc->GetRegTyFromPrimTy(dtype));
1216     RegOperand &regOpnd0 = SelectCopy2Reg(opnd0, dtype, node.Opnd(0)->GetPrimType());
1217     SelectBnot(*resOpnd, regOpnd0, dtype);
1218     return resOpnd;
1219 }
1220 
SelectBnot(Operand & resOpnd,Operand & opnd0,PrimType primType)1221 void MPISel::SelectBnot(Operand &resOpnd, Operand &opnd0, PrimType primType)
1222 {
1223     const static auto fastBnotMappingFunc = DEF_MOPERATOR_MAPPING_FUNC(not);
1224     MOperator mOp = fastBnotMappingFunc(GetPrimTypeBitSize(primType));
1225     Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mOp, InsnDesc::GetAbstractId(mOp));
1226     (void)insn.AddOpndChain(resOpnd).AddOpndChain(opnd0);
1227     cgFunc->GetCurBB()->AppendInsn(insn);
1228 }
1229 
SelectMin(BinaryNode & node,Operand & opnd0,Operand & opnd1,const BaseNode & parent)1230 Operand *MPISel::SelectMin(BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent)
1231 {
1232     PrimType primType = node.GetPrimType();
1233     RegOperand &resOpnd =
1234         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
1235     SelectMin(resOpnd, opnd0, opnd1, primType);
1236     return &resOpnd;
1237 }
1238 
SelectMin(Operand & resOpnd,Operand & opnd0,Operand & opnd1,PrimType primType)1239 void MPISel::SelectMin(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType)
1240 {
1241     SelectMinOrMax(true, resOpnd, opnd0, opnd1, primType);
1242 }
1243 
SelectMax(BinaryNode & node,Operand & opnd0,Operand & opnd1,const BaseNode & parent)1244 Operand *MPISel::SelectMax(BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent)
1245 {
1246     PrimType primType = node.GetPrimType();
1247     RegOperand &resOpnd =
1248         cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType));
1249     SelectMax(resOpnd, opnd0, opnd1, primType);
1250     return &resOpnd;
1251 }
1252 
SelectMax(Operand & resOpnd,Operand & opnd0,Operand & opnd1,PrimType primType)1253 void MPISel::SelectMax(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType)
1254 {
1255     SelectMinOrMax(false, resOpnd, opnd0, opnd1, primType);
1256 }
1257 
SelectRetype(TypeCvtNode & node,Operand & opnd0)1258 Operand *MPISel::SelectRetype(TypeCvtNode &node, Operand &opnd0)
1259 {
1260     PrimType fromType = node.Opnd(0)->GetPrimType();
1261     PrimType toType = node.GetPrimType();
1262     DEBUG_ASSERT(GetPrimTypeSize(fromType) == GetPrimTypeSize(toType), "retype bit widith doesn' match");
1263     if (IsPrimitivePoint(fromType) && IsPrimitivePoint(toType)) {
1264         return &SelectCopy2Reg(opnd0, toType);
1265     }
1266     if (IsPrimitiveInteger(fromType) && IsPrimitiveInteger(toType)) {
1267         return &SelectCopy2Reg(opnd0, toType, fromType);
1268     }
1269     if (IsPrimitiveInteger(fromType) && IsPrimitiveFloat(toType)) {
1270         RegOperand *resOpnd =
1271             &cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(toType), cgFunc->GetRegTyFromPrimTy(toType));
1272         SelectRetypeFloat(*resOpnd, opnd0, toType, fromType);
1273         return &(*resOpnd);
1274     }
1275     if (IsPrimitiveFloat(fromType) && IsPrimitiveInteger(toType)) {
1276         RegOperand *resOpnd =
1277             &cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(toType), cgFunc->GetRegTyFromPrimTy(toType));
1278         SelectRetypeFloat(*resOpnd, opnd0, toType, fromType);
1279         return &(*resOpnd);
1280     }
1281     CHECK_FATAL(false, "NIY, retype");
1282     return nullptr;
1283 }
1284 
HandleFuncExit()1285 void MPISel::HandleFuncExit()
1286 {
1287     BlockNode *block = cgFunc->GetFunction().GetBody();
1288     DEBUG_ASSERT(block != nullptr, "get func body block failed in CGFunc::GenerateInstruction");
1289     cgFunc->GetCurBB()->SetLastStmt(*block->GetLast());
1290     /* Set lastbb's frequency */
1291     cgFunc->SetLastBB(*cgFunc->GetCurBB());
1292     /* the last BB is return BB */
1293     cgFunc->GetLastBB()->SetKind(BB::kBBReturn);
1294 }
1295 
PhaseRun(maplebe::CGFunc & f)1296 bool InstructionSelector::PhaseRun(maplebe::CGFunc &f)
1297 {
1298     MPISel *mpIS = f.GetCG()->CreateMPIsel(*GetPhaseMemPool(), *GetPhaseAllocator(), f);
1299     DEBUG_ASSERT(mpIS != nullptr, "null ptr check");
1300     mpIS->doMPIS();
1301     Standardize *stdz = f.GetCG()->CreateStandardize(*GetPhaseMemPool(), f);
1302     DEBUG_ASSERT(stdz != nullptr, "null ptr check");
1303     stdz->DoStandardize();
1304     return true;
1305 }
1306 }  // namespace maplebe
1307