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