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