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