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 "cgfunc.h"
17 #if DEBUG
18 #include <iomanip>
19 #endif
20 #include <fstream>
21 #include "cg.h"
22 #include "insn.h"
23 #include "loop.h"
24 #include "mir_builder.h"
25 #include "factory.h"
26 #include "cfgo.h"
27 #include "optimize_common.h"
28
29 namespace maplebe {
30 using namespace maple;
31
HandleDread(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)32 static Operand *HandleDread(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
33 {
34 auto &dreadNode = static_cast<AddrofNode &>(expr);
35 return cgFunc.SelectDread(parent, dreadNode);
36 }
37
HandleRegread(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)38 static Operand *HandleRegread(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
39 {
40 (void)parent;
41 auto ®ReadNode = static_cast<RegreadNode &>(expr);
42 return cgFunc.SelectRegread(regReadNode);
43 }
44
HandleConstVal(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)45 static Operand *HandleConstVal(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
46 {
47 auto &constValNode = static_cast<ConstvalNode &>(expr);
48 MIRConst *mirConst = constValNode.GetConstVal();
49 DEBUG_ASSERT(mirConst != nullptr, "get constval of constvalnode failed");
50 if (mirConst->GetKind() == kConstInt) {
51 auto *mirIntConst = safe_cast<MIRIntConst>(mirConst);
52 return cgFunc.SelectIntConst(*mirIntConst, parent);
53 } else if (mirConst->GetKind() == kConstFloatConst) {
54 auto *mirFloatConst = safe_cast<MIRFloatConst>(mirConst);
55 return cgFunc.SelectFloatConst(*mirFloatConst, parent);
56 } else {
57 CHECK_FATAL(mirConst->GetKind() == kConstDoubleConst, "NYI");
58 auto *mirDoubleConst = safe_cast<MIRDoubleConst>(mirConst);
59 return cgFunc.SelectDoubleConst(*mirDoubleConst, parent);
60 }
61 return nullptr;
62 }
63
HandleAdd(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)64 static Operand *HandleAdd(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
65 {
66 return cgFunc.SelectAdd(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
67 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
68 }
69
HandleShift(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)70 static Operand *HandleShift(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
71 {
72 return cgFunc.SelectShift(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
73 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
74 }
75
HandleMpy(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)76 static Operand *HandleMpy(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
77 {
78 return cgFunc.SelectMpy(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
79 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
80 }
81
HandleDiv(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)82 static Operand *HandleDiv(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
83 {
84 return cgFunc.SelectDiv(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
85 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
86 }
87
HandleRem(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)88 static Operand *HandleRem(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
89 {
90 return cgFunc.SelectRem(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
91 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
92 }
93
HandleIread(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)94 static Operand *HandleIread(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
95 {
96 auto &ireadNode = static_cast<IreadNode &>(expr);
97 return cgFunc.SelectIread(parent, ireadNode);
98 }
99
HandleSub(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)100 static Operand *HandleSub(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
101 {
102 return cgFunc.SelectSub(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
103 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
104 }
105
HandleBand(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)106 static Operand *HandleBand(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
107 {
108 return cgFunc.SelectBand(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
109 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
110 }
111
HandleBior(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)112 static Operand *HandleBior(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
113 {
114 return cgFunc.SelectBior(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
115 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
116 }
117
HandleBxor(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)118 static Operand *HandleBxor(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
119 {
120 return cgFunc.SelectBxor(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
121 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
122 }
123
HandleAbs(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)124 static Operand *HandleAbs(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
125 {
126 (void)parent;
127 DEBUG_ASSERT(expr.Opnd(0) != nullptr, "expr.Opnd(0) should not be nullptr");
128 return cgFunc.SelectAbs(static_cast<UnaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)));
129 }
130
HandleBnot(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)131 static Operand *HandleBnot(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
132 {
133 return cgFunc.SelectBnot(static_cast<UnaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
134 }
135
HandleExtractBits(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)136 static Operand *HandleExtractBits(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
137 {
138 ExtractbitsNode &node = static_cast<ExtractbitsNode &>(expr);
139 uint8 bitOffset = node.GetBitsOffset();
140 uint8 bitSize = node.GetBitsSize();
141 if (!CGOptions::IsBigEndian() && (bitSize == k8BitSize || bitSize == k16BitSize) &&
142 GetPrimTypeBitSize(node.GetPrimType()) != k64BitSize &&
143 (bitOffset == 0 || bitOffset == k8BitSize || bitOffset == k16BitSize || bitOffset == k24BitSize) &&
144 expr.Opnd(0)->GetOpCode() == OP_iread && node.GetOpCode() == OP_extractbits) {
145 return cgFunc.SelectRegularBitFieldLoad(node, parent);
146 }
147 return cgFunc.SelectExtractbits(static_cast<ExtractbitsNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
148 parent);
149 }
150
HandleLnot(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)151 static Operand *HandleLnot(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
152 {
153 DEBUG_ASSERT(expr.Opnd(0) != nullptr, "nullptr check");
154 return cgFunc.SelectLnot(static_cast<UnaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
155 }
156
157
HandleMin(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)158 static Operand *HandleMin(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
159 {
160 return cgFunc.SelectMin(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
161 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
162 }
163
HandleMax(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)164 static Operand *HandleMax(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
165 {
166 return cgFunc.SelectMax(static_cast<BinaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
167 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
168 }
169
HandleSqrt(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)170 static Operand *HandleSqrt(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
171 {
172 return cgFunc.SelectSqrt(static_cast<UnaryNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
173 }
174
HandleCeil(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)175 static Operand *HandleCeil(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
176 {
177 return cgFunc.SelectCeil(static_cast<TypeCvtNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
178 }
179
HandleFloor(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)180 static Operand *HandleFloor(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
181 {
182 DEBUG_ASSERT(expr.Opnd(0) != nullptr, "expr.Opnd(0) should not be nullptr");
183 return cgFunc.SelectFloor(static_cast<TypeCvtNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
184 }
185
HandleRetype(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)186 static Operand *HandleRetype(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
187 {
188 (void)parent;
189 DEBUG_ASSERT(expr.Opnd(0) != nullptr, "nullptr check");
190 return cgFunc.SelectRetype(static_cast<TypeCvtNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)));
191 }
192
HandleCvt(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)193 static Operand *HandleCvt(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
194 {
195 return cgFunc.SelectCvt(parent, static_cast<TypeCvtNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)));
196 }
197
HandleTrunc(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)198 static Operand *HandleTrunc(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
199 {
200 DEBUG_ASSERT(expr.Opnd(0) != nullptr, "expr should not be nullptr");
201 return cgFunc.SelectTrunc(static_cast<TypeCvtNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)), parent);
202 }
203
HandleCmp(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)204 static Operand *HandleCmp(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
205 {
206 // fix opnd type before select insn
207 PrimType targetPtyp = parent.GetPrimType();
208 if (kOpcodeInfo.IsCompare(parent.GetOpCode())) {
209 targetPtyp = static_cast<const CompareNode &>(parent).GetOpndType();
210 } else if (kOpcodeInfo.IsTypeCvt(parent.GetOpCode())) {
211 targetPtyp = static_cast<const TypeCvtNode &>(parent).FromType();
212 }
213 if (IsPrimitiveInteger(targetPtyp) && targetPtyp != expr.GetPrimType()) {
214 expr.SetPrimType(targetPtyp);
215 }
216 return cgFunc.SelectCmpOp(static_cast<CompareNode &>(expr), *cgFunc.HandleExpr(expr, *expr.Opnd(0)),
217 *cgFunc.HandleExpr(expr, *expr.Opnd(1)), parent);
218 }
219
HandleIntrinOp(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)220 static Operand *HandleIntrinOp(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc)
221 {
222 auto &intrinsicopNode = static_cast<IntrinsicopNode &>(expr);
223 switch (intrinsicopNode.GetIntrinsic()) {
224 case INTRN_C_clz32:
225 case INTRN_C_clz64:
226 return cgFunc.SelectCclz(intrinsicopNode);
227 default:
228 DEBUG_ASSERT(false, "Should not reach here.");
229 return nullptr;
230 }
231 }
232
233 using HandleExprFactory = FunctionFactory<Opcode, maplebe::Operand *, const BaseNode &, BaseNode &, CGFunc &>;
InitHandleExprFactory()234 void InitHandleExprFactory()
235 {
236 RegisterFactoryFunction<HandleExprFactory>(OP_dread, HandleDread);
237 RegisterFactoryFunction<HandleExprFactory>(OP_regread, HandleRegread);
238 RegisterFactoryFunction<HandleExprFactory>(OP_constval, HandleConstVal);
239 RegisterFactoryFunction<HandleExprFactory>(OP_add, HandleAdd);
240 RegisterFactoryFunction<HandleExprFactory>(OP_ashr, HandleShift);
241 RegisterFactoryFunction<HandleExprFactory>(OP_lshr, HandleShift);
242 RegisterFactoryFunction<HandleExprFactory>(OP_shl, HandleShift);
243 RegisterFactoryFunction<HandleExprFactory>(OP_mul, HandleMpy);
244 RegisterFactoryFunction<HandleExprFactory>(OP_div, HandleDiv);
245 RegisterFactoryFunction<HandleExprFactory>(OP_rem, HandleRem);
246 RegisterFactoryFunction<HandleExprFactory>(OP_iread, HandleIread);
247 RegisterFactoryFunction<HandleExprFactory>(OP_sub, HandleSub);
248 RegisterFactoryFunction<HandleExprFactory>(OP_band, HandleBand);
249 RegisterFactoryFunction<HandleExprFactory>(OP_bior, HandleBior);
250 RegisterFactoryFunction<HandleExprFactory>(OP_bxor, HandleBxor);
251 RegisterFactoryFunction<HandleExprFactory>(OP_abs, HandleAbs);
252 RegisterFactoryFunction<HandleExprFactory>(OP_bnot, HandleBnot);
253 RegisterFactoryFunction<HandleExprFactory>(OP_sext, HandleExtractBits);
254 RegisterFactoryFunction<HandleExprFactory>(OP_zext, HandleExtractBits);
255 RegisterFactoryFunction<HandleExprFactory>(OP_lnot, HandleLnot);
256 RegisterFactoryFunction<HandleExprFactory>(OP_min, HandleMin);
257 RegisterFactoryFunction<HandleExprFactory>(OP_max, HandleMax);
258 RegisterFactoryFunction<HandleExprFactory>(OP_sqrt, HandleSqrt);
259 RegisterFactoryFunction<HandleExprFactory>(OP_ceil, HandleCeil);
260 RegisterFactoryFunction<HandleExprFactory>(OP_floor, HandleFloor);
261 RegisterFactoryFunction<HandleExprFactory>(OP_retype, HandleRetype);
262 RegisterFactoryFunction<HandleExprFactory>(OP_cvt, HandleCvt);
263 RegisterFactoryFunction<HandleExprFactory>(OP_trunc, HandleTrunc);
264 RegisterFactoryFunction<HandleExprFactory>(OP_le, HandleCmp);
265 RegisterFactoryFunction<HandleExprFactory>(OP_ge, HandleCmp);
266 RegisterFactoryFunction<HandleExprFactory>(OP_gt, HandleCmp);
267 RegisterFactoryFunction<HandleExprFactory>(OP_lt, HandleCmp);
268 RegisterFactoryFunction<HandleExprFactory>(OP_ne, HandleCmp);
269 RegisterFactoryFunction<HandleExprFactory>(OP_eq, HandleCmp);
270 RegisterFactoryFunction<HandleExprFactory>(OP_intrinsicop, HandleIntrinOp);
271 }
272
HandleLabel(StmtNode &stmt, CGFunc &cgFunc)273 static void HandleLabel(StmtNode &stmt, CGFunc &cgFunc)
274 {
275 DEBUG_ASSERT(stmt.GetOpCode() == OP_label, "error");
276 auto &label = static_cast<LabelNode &>(stmt);
277 BB *newBB = cgFunc.StartNewBBImpl(false, label);
278 newBB->AddLabel(label.GetLabelIdx());
279 if (newBB->GetId() == 1) {
280 newBB->SetFrequency(kFreqBase);
281 }
282 cgFunc.SetLab2BBMap(newBB->GetLabIdx(), *newBB);
283 cgFunc.SetCurBB(*newBB);
284 }
285
HandleGoto(StmtNode &stmt, CGFunc &cgFunc)286 static void HandleGoto(StmtNode &stmt, CGFunc &cgFunc)
287 {
288 auto &gotoNode = static_cast<GotoNode &>(stmt);
289 cgFunc.SetCurBBKind(BB::kBBGoto);
290 cgFunc.SelectGoto(gotoNode);
291 cgFunc.SetCurBB(*cgFunc.StartNewBB(gotoNode));
292 DEBUG_ASSERT(&stmt == &gotoNode, "stmt must be same as gotoNoe");
293
294 if ((gotoNode.GetNext() != nullptr) && (gotoNode.GetNext()->GetOpCode() != OP_label)) {
295 DEBUG_ASSERT(cgFunc.GetCurBB()->GetPrev()->GetLastStmt() == &stmt, "check the relation between BB and stmt");
296 }
297 }
298
HandleCondbr(StmtNode &stmt, CGFunc &cgFunc)299 static void HandleCondbr(StmtNode &stmt, CGFunc &cgFunc)
300 {
301 auto &condGotoNode = static_cast<CondGotoNode &>(stmt);
302 BaseNode *condNode = condGotoNode.Opnd(0);
303 DEBUG_ASSERT(condNode != nullptr, "expect first operand of cond br");
304 Opcode condOp = condGotoNode.GetOpCode();
305 if (condNode->GetOpCode() == OP_constval) {
306 auto *constValNode = static_cast<ConstvalNode *>(condNode);
307 if ((constValNode->GetConstVal()->IsZero() && (OP_brfalse == condOp)) ||
308 (!constValNode->GetConstVal()->IsZero() && (OP_brtrue == condOp))) {
309 auto *gotoStmt = cgFunc.GetMemoryPool()->New<GotoNode>(OP_goto);
310 gotoStmt->SetOffset(condGotoNode.GetOffset());
311 HandleGoto(*gotoStmt, cgFunc);
312 auto *labelStmt = cgFunc.GetMemoryPool()->New<LabelNode>();
313 labelStmt->SetLabelIdx(cgFunc.CreateLabel());
314 HandleLabel(*labelStmt, cgFunc);
315 }
316 return;
317 }
318 cgFunc.SetCurBBKind(BB::kBBIf);
319 /* if condNode is not a cmp node, cmp it with zero. */
320 if (!kOpcodeInfo.IsCompare(condNode->GetOpCode())) {
321 Operand *opnd0 = cgFunc.HandleExpr(condGotoNode, *condNode);
322 PrimType primType = condNode->GetPrimType();
323 Operand *zeroOpnd = nullptr;
324 if (IsPrimitiveInteger(primType)) {
325 zeroOpnd = &cgFunc.CreateImmOperand(primType, 0);
326 } else {
327 DEBUG_ASSERT(((PTY_f32 == primType) || (PTY_f64 == primType)),
328 "we don't support half-precision FP operands yet");
329 zeroOpnd = &cgFunc.CreateImmOperand(primType, 0);
330 }
331 cgFunc.SelectCondGoto(condGotoNode, *opnd0, *zeroOpnd);
332 cgFunc.SetCurBB(*cgFunc.StartNewBB(condGotoNode));
333 return;
334 }
335 /*
336 * Special case:
337 * bgt (cmp (op0, op1), 0) ==>
338 * bgt (op0, op1)
339 * but skip the case cmp(op0, 0)
340 */
341 BaseNode *op0 = condNode->Opnd(0);
342 DEBUG_ASSERT(op0 != nullptr, "get first opnd of a condNode failed");
343 BaseNode *op1 = condNode->Opnd(1);
344 DEBUG_ASSERT(op1 != nullptr, "get second opnd of a condNode failed");
345 if ((op0->GetOpCode() == OP_cmp) && (op1->GetOpCode() == OP_constval)) {
346 auto *constValNode = static_cast<ConstvalNode *>(op1);
347 MIRConst *mirConst = constValNode->GetConstVal();
348 auto *cmpNode = static_cast<CompareNode *>(op0);
349 bool skip = false;
350 if (cmpNode->Opnd(1)->GetOpCode() == OP_constval) {
351 auto *constVal = static_cast<ConstvalNode *>(cmpNode->Opnd(1))->GetConstVal();
352 if (constVal->IsZero()) {
353 skip = true;
354 }
355 }
356 if (!skip && mirConst->IsZero()) {
357 cgFunc.SelectCondSpecialCase1(condGotoNode, *op0);
358 cgFunc.SetCurBB(*cgFunc.StartNewBB(condGotoNode));
359 return;
360 }
361 }
362
363 Operand *opnd0 = cgFunc.HandleExpr(*condNode, *condNode->Opnd(0));
364 Operand *opnd1 = cgFunc.HandleExpr(*condNode, *condNode->Opnd(1));
365 cgFunc.SelectCondGoto(condGotoNode, *opnd0, *opnd1);
366 cgFunc.SetCurBB(*cgFunc.StartNewBB(condGotoNode));
367 }
368
HandleReturn(StmtNode &stmt, CGFunc &cgFunc)369 static void HandleReturn(StmtNode &stmt, CGFunc &cgFunc)
370 {
371 auto &retNode = static_cast<NaryStmtNode &>(stmt);
372 DEBUG_ASSERT(retNode.NumOpnds() <= 1, "NYI return nodes number > 1");
373 Operand *opnd = nullptr;
374 if (retNode.NumOpnds() != 0) {
375 opnd = cgFunc.HandleExpr(retNode, *retNode.Opnd(0));
376 }
377 cgFunc.SelectReturn(opnd);
378 cgFunc.SetCurBBKind(BB::kBBReturn);
379 cgFunc.SetCurBB(*cgFunc.StartNewBB(retNode));
380 }
381
HandleCall(StmtNode &stmt, CGFunc &cgFunc)382 static void HandleCall(StmtNode &stmt, CGFunc &cgFunc)
383 {
384 auto &callNode = static_cast<CallNode &>(stmt);
385 cgFunc.SelectCall(callNode);
386 }
387
HandleICall(StmtNode &stmt, CGFunc &cgFunc)388 static void HandleICall(StmtNode &stmt, CGFunc &cgFunc)
389 {
390 auto &icallNode = static_cast<IcallNode &>(stmt);
391 cgFunc.GetCurBB()->SetHasCall();
392 cgFunc.SelectIcall(icallNode);
393 }
394
HandleIntrinsicCall(StmtNode &stmt, CGFunc &cgFunc)395 static void HandleIntrinsicCall(StmtNode &stmt, CGFunc &cgFunc)
396 {
397 auto &call = static_cast<IntrinsiccallNode &>(stmt);
398 cgFunc.SelectIntrinsicCall(call);
399 }
400
HandleDassign(StmtNode &stmt, CGFunc &cgFunc)401 static void HandleDassign(StmtNode &stmt, CGFunc &cgFunc)
402 {
403 auto &dassignNode = static_cast<DassignNode &>(stmt);
404 DEBUG_ASSERT(dassignNode.GetOpCode() == OP_dassign, "expect dassign");
405 BaseNode *rhs = dassignNode.GetRHS();
406 DEBUG_ASSERT(rhs != nullptr, "get rhs of dassignNode failed");
407 bool isSaveRetvalToLocal = false;
408 if (rhs->GetOpCode() == OP_regread) {
409 isSaveRetvalToLocal = (static_cast<RegreadNode *>(rhs)->GetRegIdx() == -kSregRetval0);
410 }
411 Operand *opnd0 = cgFunc.HandleExpr(dassignNode, *rhs);
412 cgFunc.SelectDassign(dassignNode, *opnd0);
413 if (isSaveRetvalToLocal && cgFunc.GetCurBB() && cgFunc.GetCurBB()->GetLastMachineInsn()) {
414 cgFunc.GetCurBB()->GetLastMachineInsn()->MarkAsSaveRetValToLocal();
415 }
416 }
417
HandleRegassign(StmtNode &stmt, CGFunc &cgFunc)418 static void HandleRegassign(StmtNode &stmt, CGFunc &cgFunc)
419 {
420 DEBUG_ASSERT(stmt.GetOpCode() == OP_regassign, "expect regAssign");
421 auto ®AssignNode = static_cast<RegassignNode &>(stmt);
422 bool isSaveRetvalToLocal = false;
423 BaseNode *operand = regAssignNode.Opnd(0);
424 DEBUG_ASSERT(operand != nullptr, "get operand of regassignNode failed");
425 if (operand->GetOpCode() == OP_regread) {
426 isSaveRetvalToLocal = (static_cast<RegreadNode *>(operand)->GetRegIdx() == -kSregRetval0);
427 }
428 Operand *opnd0 = cgFunc.HandleExpr(regAssignNode, *operand);
429 cgFunc.SelectRegassign(regAssignNode, *opnd0);
430 if (isSaveRetvalToLocal && cgFunc.GetCurBB() && cgFunc.GetCurBB()->GetLastMachineInsn()) {
431 cgFunc.GetCurBB()->GetLastMachineInsn()->MarkAsSaveRetValToLocal();
432 }
433 }
434
HandleIassign(StmtNode &stmt, CGFunc &cgFunc)435 static void HandleIassign(StmtNode &stmt, CGFunc &cgFunc)
436 {
437 DEBUG_ASSERT(stmt.GetOpCode() == OP_iassign, "expect stmt");
438 auto &iassignNode = static_cast<IassignNode &>(stmt);
439 if ((iassignNode.GetRHS() != nullptr)) {
440 cgFunc.SelectIassign(iassignNode);
441 } else {
442 CHECK_FATAL(false, "NIY");
443 }
444 }
445
HandleRangeGoto(StmtNode &stmt, CGFunc &cgFunc)446 void HandleRangeGoto(StmtNode &stmt, CGFunc &cgFunc)
447 {
448 auto &rangeGotoNode = static_cast<RangeGotoNode &>(stmt);
449 cgFunc.SetCurBBKind(BB::kBBRangeGoto);
450 cgFunc.SelectRangeGoto(rangeGotoNode, *cgFunc.HandleExpr(rangeGotoNode, *rangeGotoNode.Opnd(0)));
451 cgFunc.SetCurBB(*cgFunc.StartNewBB(rangeGotoNode));
452 }
453
HandleComment(StmtNode &stmt, CGFunc &cgFunc)454 void HandleComment(StmtNode &stmt, CGFunc &cgFunc)
455 {
456 if (cgFunc.GetCG()->GenerateVerboseAsm() || cgFunc.GetCG()->GenerateVerboseCG()) {
457 cgFunc.SelectComment(static_cast<CommentNode &>(stmt));
458 }
459 }
460
461 using HandleStmtFactory = FunctionFactory<Opcode, void, StmtNode &, CGFunc &>;
InitHandleStmtFactory()462 static void InitHandleStmtFactory()
463 {
464 RegisterFactoryFunction<HandleStmtFactory>(OP_label, HandleLabel);
465 RegisterFactoryFunction<HandleStmtFactory>(OP_goto, HandleGoto);
466 RegisterFactoryFunction<HandleStmtFactory>(OP_brfalse, HandleCondbr);
467 RegisterFactoryFunction<HandleStmtFactory>(OP_brtrue, HandleCondbr);
468 RegisterFactoryFunction<HandleStmtFactory>(OP_return, HandleReturn);
469 RegisterFactoryFunction<HandleStmtFactory>(OP_call, HandleCall);
470 RegisterFactoryFunction<HandleStmtFactory>(OP_icall, HandleICall);
471 RegisterFactoryFunction<HandleStmtFactory>(OP_icallproto, HandleICall);
472 RegisterFactoryFunction<HandleStmtFactory>(OP_intrinsiccall, HandleIntrinsicCall);
473 RegisterFactoryFunction<HandleStmtFactory>(OP_intrinsiccallassigned, HandleIntrinsicCall);
474 RegisterFactoryFunction<HandleStmtFactory>(OP_intrinsiccallwithtype, HandleIntrinsicCall);
475 RegisterFactoryFunction<HandleStmtFactory>(OP_dassign, HandleDassign);
476 RegisterFactoryFunction<HandleStmtFactory>(OP_regassign, HandleRegassign);
477 RegisterFactoryFunction<HandleStmtFactory>(OP_iassign, HandleIassign);
478 RegisterFactoryFunction<HandleStmtFactory>(OP_rangegoto, HandleRangeGoto);
479 RegisterFactoryFunction<HandleStmtFactory>(OP_comment, HandleComment);
480 }
481
CGFunc(MIRModule &mod, CG &cg, MIRFunction &mirFunc, BECommon &beCommon, MemPool &memPool, StackMemPool &stackMp, MapleAllocator &allocator, uint32 funcId)482 CGFunc::CGFunc(MIRModule &mod, CG &cg, MIRFunction &mirFunc, BECommon &beCommon, MemPool &memPool,
483 StackMemPool &stackMp, MapleAllocator &allocator, uint32 funcId)
484 : bbVec(allocator.Adapter()),
485 referenceVirtualRegs(allocator.Adapter()),
486 referenceStackSlots(allocator.Adapter()),
487 pregIdx2Opnd(mirFunc.GetPregTab()->Size(), nullptr, allocator.Adapter()),
488 pRegSpillMemOperands(allocator.Adapter()),
489 spillRegMemOperands(allocator.Adapter()),
490 reuseSpillLocMem(allocator.Adapter()),
491 labelMap(std::less<LabelIdx>(), allocator.Adapter()),
492 vregsToPregsMap(std::less<regno_t>(), allocator.Adapter()),
493 stackMapInsns(allocator.Adapter()),
494 hasVLAOrAlloca(mirFunc.HasVlaOrAlloca()),
495 cg(&cg),
496 mirModule(mod),
497 memPool(&memPool),
498 stackMp(stackMp),
499 func(mirFunc),
500 exitBBVec(allocator.Adapter()),
501 noReturnCallBBVec(allocator.Adapter()),
502 extendSet(allocator.Adapter()),
503 lab2BBMap(allocator.Adapter()),
504 beCommon(beCommon),
505 funcScopeAllocator(&allocator),
506 emitStVec(allocator.Adapter()),
507 switchLabelCnt(allocator.Adapter()),
508 shortFuncName(mirFunc.GetName() + "." + std::to_string(funcId), &memPool)
509 {
510 mirModule.SetCurFunction(&func);
511 dummyBB = CreateNewBB();
512 vReg.SetCount(static_cast<uint32>(kBaseVirtualRegNO + func.GetPregTab()->Size()));
513 firstNonPregVRegNO = vReg.GetCount();
514 /* maximum register count initial be increased by 1024 */
515 SetMaxRegNum(vReg.GetCount() + 1024);
516
517 maplebe::VregInfo::vRegOperandTable.clear();
518
519 insnBuilder = memPool.New<InsnBuilder>(memPool);
520 opndBuilder = memPool.New<OperandBuilder>(memPool, func.GetPregTab()->Size());
521
522 vReg.VRegTableResize(GetMaxRegNum());
523 /* func.GetPregTab()->_preg_table[0] is nullptr, so skip it */
524 DEBUG_ASSERT(func.GetPregTab()->PregFromPregIdx(0) == nullptr, "PregFromPregIdx(0) must be nullptr");
525 for (size_t i = 1; i < func.GetPregTab()->Size(); ++i) {
526 PrimType primType = func.GetPregTab()->PregFromPregIdx(i)->GetPrimType();
527 uint32 byteLen = GetPrimTypeSize(primType);
528 if (byteLen < k4ByteSize) {
529 byteLen = k4ByteSize;
530 }
531 new (&GetVirtualRegNodeFromPseudoRegIdx(i)) VirtualRegNode(GetRegTyFromPrimTy(primType), byteLen);
532 }
533 lSymSize = 0;
534 if (func.GetSymTab()) {
535 lSymSize = func.GetSymTab()->GetSymbolTableSize();
536 }
537 callingConventionKind = CCImpl::GetCallConvKind(mirFunc);
538 }
539
~CGFunc()540 CGFunc::~CGFunc()
541 {
542 mirModule.SetCurFunction(nullptr);
543 }
544
HandleExpr(const BaseNode &parent, BaseNode &expr)545 Operand *CGFunc::HandleExpr(const BaseNode &parent, BaseNode &expr)
546 {
547 auto function = CreateProductFunction<HandleExprFactory>(expr.GetOpCode());
548 CHECK_FATAL(function != nullptr, "unsupported %d opCode in HandleExpr()", expr.GetOpCode());
549 return function(parent, expr, *this);
550 }
551
HandleFirstStmt()552 StmtNode *CGFunc::HandleFirstStmt()
553 {
554 BlockNode *block = func.GetBody();
555
556 DEBUG_ASSERT(block != nullptr, "get func body block failed in CGFunc::GenerateInstruction");
557 StmtNode *stmt = block->GetFirst();
558 if (stmt == nullptr) {
559 return nullptr;
560 }
561 DEBUG_ASSERT(stmt->GetOpCode() == OP_label, "The first statement should be a label");
562 HandleLabel(*stmt, *this);
563 firstBB = curBB;
564 stmt = stmt->GetNext();
565 if (stmt == nullptr) {
566 return nullptr;
567 }
568 curBB = StartNewBBImpl(false, *stmt);
569 return stmt;
570 }
571
RemoveUnreachableBB()572 void CGFunc::RemoveUnreachableBB()
573 {
574 OptimizationPattern *pattern = memPool->New<UnreachBBPattern>(*this);
575 for (BB *bb = firstBB; bb != nullptr; bb = bb->GetNext()) {
576 (void)pattern->Optimize(*bb);
577 }
578 }
579
GenerateInstruction()580 void CGFunc::GenerateInstruction()
581 {
582 InitHandleExprFactory();
583 InitHandleStmtFactory();
584 StmtNode *secondStmt = HandleFirstStmt();
585
586 std::set<uint32> bbFreqSet;
587 for (StmtNode *stmt = secondStmt; stmt != nullptr; stmt = stmt->GetNext()) {
588 GetInsnBuilder()->SetDebugComment(stmt->GetDebugComment());
589 auto function = CreateProductFunction<HandleStmtFactory>(stmt->GetOpCode());
590 CHECK_FATAL(function != nullptr, "unsupported opCode or has been lowered before");
591 function(*stmt, *this);
592 GetInsnBuilder()->ClearDebugComment();
593 }
594
595 /* Set lastbb's frequency */
596 BlockNode *block = func.GetBody();
597 DEBUG_ASSERT(block != nullptr, "get func body block failed in CGFunc::GenerateInstruction");
598 curBB->SetLastStmt(*block->GetLast());
599 lastBB = curBB;
600 }
601
CreateLabel()602 LabelIdx CGFunc::CreateLabel()
603 {
604 MIRSymbol *funcSt = GlobalTables::GetGsymTable().GetSymbolFromStidx(func.GetStIdx().Idx());
605 DEBUG_ASSERT(funcSt != nullptr, "Get func failed at CGFunc::CreateLabel");
606 std::string funcName = funcSt->GetName();
607 std::string labelStr = funcName += std::to_string(labelIdx++);
608 return func.GetOrCreateLableIdxFromName(labelStr);
609 }
610
ProcessExitBBVec()611 void CGFunc::ProcessExitBBVec()
612 {
613 if (exitBBVec.empty()) {
614 BB *retBB = CreateNewBB();
615 retBB->SetKind(BB::kBBReturn);
616 SetLab2BBMap(retBB->GetLabIdx(), *retBB);
617 GetLastBB()->PrependBB(*retBB);
618 exitBBVec.emplace_back(retBB);
619 return;
620 }
621 /* split an empty exitBB */
622 BB *bb = exitBBVec[0];
623 if (bb->NumInsn() > 0) {
624 BB *retBBPart = CreateNewBB(false, BB::kBBFallthru, bb->GetFrequency());
625 DEBUG_ASSERT(retBBPart != nullptr, "retBBPart should not be nullptr");
626 LabelIdx retBBPartLabelIdx = bb->GetLabIdx();
627 if (retBBPartLabelIdx != MIRLabelTable::GetDummyLabel()) {
628 retBBPart->AddLabel(retBBPartLabelIdx);
629 lab2BBMap[retBBPartLabelIdx] = retBBPart;
630 }
631 Insn *insn = bb->GetFirstInsn();
632 while (insn != nullptr) {
633 bb->RemoveInsn(*insn);
634 retBBPart->AppendInsn(*insn);
635 insn = bb->GetFirstInsn();
636 }
637 bb->PrependBB(*retBBPart);
638 LabelIdx newLabelIdx = CreateLabel();
639 bb->AddLabel(newLabelIdx);
640 lab2BBMap[newLabelIdx] = bb;
641 }
642 }
643
AddCommonExitBB()644 void CGFunc::AddCommonExitBB()
645 {
646 if (commonExitBB != nullptr) {
647 return;
648 }
649 // create fake commonExitBB
650 commonExitBB = CreateNewBB(true, BB::kBBFallthru, 0);
651 DEBUG_ASSERT(commonExitBB != nullptr, "cannot create fake commonExitBB");
652 for (BB *cgbb : exitBBVec) {
653 if (!cgbb->IsUnreachable()) {
654 commonExitBB->PushBackPreds(*cgbb);
655 }
656 }
657 }
658
HandleFunction()659 void CGFunc::HandleFunction()
660 {
661 /* select instruction */
662 GenerateInstruction();
663 /* merge multi return */
664 MergeReturn();
665 ProcessExitBBVec();
666 /* build control flow graph */
667 theCFG = memPool->New<CGCFG>(*this);
668 theCFG->BuildCFG();
669 RemoveUnreachableBB();
670 AddCommonExitBB();
671 theCFG->UnreachCodeAnalysis();
672 EraseUnreachableStackMapInsns();
673 }
674
DumpCFG() const675 void CGFunc::DumpCFG() const
676 {
677 #ifdef ARK_LITECG_DEBUG
678 MIRSymbol *funcSt = GlobalTables::GetGsymTable().GetSymbolFromStidx(func.GetStIdx().Idx());
679 DEBUG_ASSERT(funcSt != nullptr, "null ptr check");
680 LogInfo::MapleLogger() << "\n****** CFG built by CG for " << funcSt->GetName() << " *******\n";
681 FOR_ALL_BB_CONST(bb, this)
682 {
683 LogInfo::MapleLogger() << "=== BB ( " << std::hex << bb << std::dec << " ) <" << bb->GetKindName() << "> ===\n";
684 LogInfo::MapleLogger() << "BB id:" << bb->GetId() << "\n";
685 if (!bb->GetPreds().empty()) {
686 LogInfo::MapleLogger() << " pred [ ";
687 for (auto *pred : bb->GetPreds()) {
688 LogInfo::MapleLogger() << pred->GetId() << " ";
689 }
690 LogInfo::MapleLogger() << "]\n";
691 }
692 if (!bb->GetSuccs().empty()) {
693 LogInfo::MapleLogger() << " succ [ ";
694 for (auto *succ : bb->GetSuccs()) {
695 LogInfo::MapleLogger() << succ->GetId() << " ";
696 }
697 LogInfo::MapleLogger() << "]\n";
698 }
699 const StmtNode *stmt = bb->GetFirstStmt();
700 if (stmt != nullptr) {
701 bool done = false;
702 do {
703 done = stmt == bb->GetLastStmt();
704 stmt->Dump(1);
705 LogInfo::MapleLogger() << "\n";
706 stmt = stmt->GetNext();
707 } while (!done);
708 } else {
709 LogInfo::MapleLogger() << "<empty BB>\n";
710 }
711 }
712 #endif
713 }
714
DumpBBInfo(const BB *bb) const715 void CGFunc::DumpBBInfo(const BB *bb) const
716 {
717 #ifdef ARK_LITECG_DEBUG
718 LogInfo::MapleLogger() << "=== BB " << " <" << bb->GetKindName();
719 if (bb->GetLabIdx() != MIRLabelTable::GetDummyLabel()) {
720 LogInfo::MapleLogger() << "[labeled with " << bb->GetLabIdx();
721 LogInfo::MapleLogger() << " ==> @" << func.GetLabelName(bb->GetLabIdx()) << "]";
722 }
723
724 LogInfo::MapleLogger() << "> <" << bb->GetId() << "> ";
725 if (bb->IsCleanup()) {
726 LogInfo::MapleLogger() << "[is_cleanup] ";
727 }
728 if (bb->IsUnreachable()) {
729 LogInfo::MapleLogger() << "[unreachable] ";
730 }
731 if (!bb->GetSuccs().empty()) {
732 LogInfo::MapleLogger() << "succs: ";
733 for (auto *succBB : bb->GetSuccs()) {
734 LogInfo::MapleLogger() << succBB->GetId() << " ";
735 }
736 }
737 if (!bb->GetPreds().empty()) {
738 LogInfo::MapleLogger() << "preds: ";
739 for (auto *predBB : bb->GetPreds()) {
740 LogInfo::MapleLogger() << predBB->GetId() << " ";
741 }
742 }
743 LogInfo::MapleLogger() << "===\n";
744 LogInfo::MapleLogger() << "frequency:" << bb->GetFrequency() << "\n";
745 #endif
746 }
747
DumpCGIR() const748 void CGFunc::DumpCGIR() const
749 {
750 #ifdef ARK_LITECG_DEBUG
751 MIRSymbol *funcSt = GlobalTables::GetGsymTable().GetSymbolFromStidx(func.GetStIdx().Idx());
752 DEBUG_ASSERT(funcSt != nullptr, "null ptr check");
753 LogInfo::MapleLogger() << "\n****** CGIR for " << funcSt->GetName() << " *******\n";
754 FOR_ALL_BB_CONST(bb, this)
755 {
756 if (bb->IsUnreachable()) {
757 continue;
758 }
759 DumpBBInfo(bb);
760 FOR_BB_INSNS_CONST(insn, bb)
761 {
762 insn->Dump();
763 }
764 }
765 #endif
766 }
767
768 // Cgirverify phase function: all insns will be verified before cgemit.
VerifyAllInsn()769 void CGFunc::VerifyAllInsn()
770 {
771 #ifdef ARK_LITECG_DEBUG
772 FOR_ALL_BB(bb, this)
773 {
774 FOR_BB_INSNS(insn, bb)
775 {
776 if (VERIFY_INSN(insn) && insn->CheckMD()) {
777 continue;
778 }
779 LogInfo::MapleLogger() << "Illegal insn is:\n";
780 insn->Dump();
781 LogInfo::MapleLogger() << "Function name is:\n" << GetName() << "\n";
782 CHECK_FATAL_FALSE("The problem is illegal insn, info is above.");
783 }
784 }
785 #endif
786 }
787
PhaseRun(maplebe::CGFunc &f)788 bool CgHandleFunction::PhaseRun(maplebe::CGFunc &f)
789 {
790 f.HandleFunction();
791 return false;
792 }
793 MAPLE_TRANSFORM_PHASE_REGISTER(CgHandleFunction, handlefunction)
794
PhaseRun(maplebe::CGFunc &f)795 bool CgVerify::PhaseRun(maplebe::CGFunc &f)
796 {
797 #ifdef ARK_LITECG_DEBUG
798 f.VerifyAllInsn();
799 if (!f.GetCG()->GetCGOptions().DoEmitCode() || f.GetCG()->GetCGOptions().DoDumpCFG()) {
800 f.DumpCFG();
801 }
802 #endif
803 return false;
804 }
805 MAPLE_TRANSFORM_PHASE_REGISTER(CgVerify, cgirverify)
806 } /* namespace maplebe */
807