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