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