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 &regReadNode = 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 &regAssignNode = 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