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 #ifndef MAPLE_IR_INCLUDE_MIR_LOWER_H
17 #define MAPLE_IR_INCLUDE_MIR_LOWER_H
18 #include <iostream>
19 #include "mir_builder.h"
20 #include "opcodes.h"
21
22 namespace maple {
23 // The base value for branch probability notes and edge probabilities.
24 static constexpr int32 kProbAll = 10000;
25 static constexpr int32 kProbLikely = 9000;
26 static constexpr int32 kProbUnlikely = kProbAll - kProbLikely;
27 constexpr uint32 kNodeFirstOpnd = 0;
28 constexpr uint32 kNodeSecondOpnd = 1;
29 constexpr uint32 kNodeThirdOpnd = 2;
30 enum MirLowerPhase : uint8 { kLowerUnder, kLowerMe, kLowerExpandArray, kLowerBe, kLowerCG, kLowerLNO };
31
32 constexpr uint32 kShiftLowerMe = 1U << kLowerMe;
33 constexpr uint32 kShiftLowerExpandArray = 1U << kLowerExpandArray;
34 constexpr uint32 kShiftLowerBe = 1U << kLowerBe;
35 constexpr uint32 kShiftLowerCG = 1U << kLowerCG;
36 constexpr uint32 kShiftLowerLNO = 1U << kLowerLNO;
37 // check if a block node ends with an unconditional jump
OpCodeNoFallThrough(Opcode opCode)38 inline bool OpCodeNoFallThrough(Opcode opCode)
39 {
40 return opCode == OP_goto || opCode == OP_return || opCode == OP_switch || opCode == OP_throw ||
41 opCode == OP_gosub || opCode == OP_retsub;
42 }
43
IfStmtNoFallThrough(const IfStmtNode & ifStmt)44 inline bool IfStmtNoFallThrough(const IfStmtNode &ifStmt)
45 {
46 return OpCodeNoFallThrough(ifStmt.GetThenPart()->GetLast()->GetOpCode());
47 }
48
49 class MIRLower {
50 public:
51 static const std::set<std::string> kSetArrayHotFunc;
52
MIRLower(MIRModule & mod,MIRFunction * f)53 MIRLower(MIRModule &mod, MIRFunction *f) : mirModule(mod), mirFunc(f) {}
54
55 virtual ~MIRLower() = default;
56
GetMirFunc()57 const MIRFunction *GetMirFunc() const
58 {
59 return mirFunc;
60 }
61
SetMirFunc(MIRFunction * f)62 void SetMirFunc(MIRFunction *f)
63 {
64 mirFunc = f;
65 }
66
Init()67 void Init()
68 {
69 mirBuilder = mirModule.GetMemPool()->New<MIRBuilder>(&mirModule);
70 }
71
72 virtual BlockNode *LowerIfStmt(IfStmtNode &ifStmt, bool recursive);
73 BlockNode *LowerSwitchStmt(SwitchNode *switchNode);
74 virtual BlockNode *LowerWhileStmt(WhileStmtNode &);
75 BlockNode *LowerDowhileStmt(WhileStmtNode &);
76 BlockNode *LowerDoloopStmt(DoloopNode &);
77 BlockNode *LowerBlock(BlockNode &);
78 BaseNode *LowerEmbeddedCandCior(BaseNode *x, StmtNode *curstmt, BlockNode *block);
79 void LowerCandCior(BlockNode &block);
80 void LowerBuiltinExpect(BlockNode &block);
81 void LowerFunc(MIRFunction &func);
82 BaseNode *LowerFarray(ArrayNode *array);
83 BaseNode *LowerCArray(ArrayNode *array);
84 void ExpandArrayMrt(MIRFunction &func);
85 IfStmtNode *ExpandArrayMrtIfBlock(IfStmtNode &node);
86 WhileStmtNode *ExpandArrayMrtWhileBlock(WhileStmtNode &node);
87 DoloopNode *ExpandArrayMrtDoloopBlock(DoloopNode &node);
88 ForeachelemNode *ExpandArrayMrtForeachelemBlock(ForeachelemNode &node);
89 BlockNode *ExpandArrayMrtBlock(BlockNode &block);
90 void AddArrayMrtMpl(BaseNode &exp, BlockNode &newblk);
91 MIRFuncType *FuncTypeFromFuncPtrExpr(BaseNode *x);
SetLowerME()92 void SetLowerME()
93 {
94 lowerPhase |= kShiftLowerMe;
95 }
96
SetLowerLNO()97 void SetLowerLNO()
98 {
99 lowerPhase |= kShiftLowerLNO;
100 }
101
SetLowerExpandArray()102 void SetLowerExpandArray()
103 {
104 lowerPhase |= kShiftLowerExpandArray;
105 }
106
SetLowerBE()107 void SetLowerBE()
108 {
109 lowerPhase |= kShiftLowerBe;
110 }
111
SetLowerCG()112 void SetLowerCG()
113 {
114 lowerPhase |= kShiftLowerCG;
115 }
116
GetOptLevel()117 uint8 GetOptLevel() const
118 {
119 return optLevel;
120 }
121
SetOptLevel(uint8 optlvl)122 void SetOptLevel(uint8 optlvl)
123 {
124 optLevel = optlvl;
125 }
126
IsLowerME()127 bool IsLowerME() const
128 {
129 return lowerPhase & kShiftLowerMe;
130 }
131
IsLowerLNO()132 bool IsLowerLNO() const
133 {
134 return lowerPhase & kShiftLowerLNO;
135 }
136
IsLowerExpandArray()137 bool IsLowerExpandArray() const
138 {
139 return lowerPhase & kShiftLowerExpandArray;
140 }
141
IsLowerBE()142 bool IsLowerBE() const
143 {
144 return lowerPhase & kShiftLowerBe;
145 }
146
IsLowerCG()147 bool IsLowerCG() const
148 {
149 return lowerPhase & kShiftLowerCG;
150 }
151
152 static bool ShouldOptArrayMrt(const MIRFunction &func);
153
InLFO()154 virtual bool InLFO() const
155 {
156 return false;
157 }
158
GetFuncProfData()159 GcovFuncInfo *GetFuncProfData()
160 {
161 return mirFunc->GetFuncProfData();
162 }
CopyStmtFrequency(StmtNode * newStmt,StmtNode * oldStmt)163 void CopyStmtFrequency(StmtNode *newStmt, StmtNode *oldStmt)
164 {
165 DEBUG_ASSERT(GetFuncProfData() != nullptr, "nullptr check");
166 if (newStmt == oldStmt)
167 return;
168 int64_t freq = GetFuncProfData()->GetStmtFreq(oldStmt->GetStmtID());
169 GetFuncProfData()->SetStmtFreq(newStmt->GetStmtID(), freq);
170 }
171
172 protected:
173 MIRModule &mirModule;
174
175 private:
176 MIRFunction *mirFunc;
177 MIRBuilder *mirBuilder = nullptr;
178 uint32 lowerPhase = 0;
179 uint8 optLevel = 0;
180 LabelIdx CreateCondGotoStmt(Opcode op, BlockNode &blk, const IfStmtNode &ifStmt);
181 void CreateBrFalseStmt(BlockNode &blk, const IfStmtNode &ifStmt);
182 void CreateBrTrueStmt(BlockNode &blk, const IfStmtNode &ifStmt);
183 void CreateBrFalseAndGotoStmt(BlockNode &blk, const IfStmtNode &ifStmt);
184 };
185 } // namespace maple
186 #endif // MAPLE_IR_INCLUDE_MIR_LOWER_H
187