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 kShiftLowerBe = 1U << kLowerBe;
34 constexpr uint32 kShiftLowerCG = 1U << kLowerCG;
35 constexpr uint32 kShiftLowerLNO = 1U << kLowerLNO;
36 // check if a block node ends with an unconditional jump
OpCodeNoFallThrough(Opcode opCode)37 inline bool OpCodeNoFallThrough(Opcode opCode)
38 {
39 return opCode == OP_goto || opCode == OP_return || opCode == OP_switch;
40 }
41
IfStmtNoFallThrough(const IfStmtNode &ifStmt)42 inline bool IfStmtNoFallThrough(const IfStmtNode &ifStmt)
43 {
44 return OpCodeNoFallThrough(ifStmt.GetThenPart()->GetLast()->GetOpCode());
45 }
46
47 class MIRLower {
48 public:
49 static const std::set<std::string> kSetArrayHotFunc;
50
MIRLower(MIRModule &mod, MIRFunction *f)51 MIRLower(MIRModule &mod, MIRFunction *f) : mirModule(mod), mirFunc(f) {}
52
53 virtual ~MIRLower() = default;
54
GetMirFunc() const55 const MIRFunction *GetMirFunc() const
56 {
57 return mirFunc;
58 }
59
SetMirFunc(MIRFunction *f)60 void SetMirFunc(MIRFunction *f)
61 {
62 mirFunc = f;
63 }
64
Init()65 void Init()
66 {
67 mirBuilder = mirModule.GetMemPool()->New<MIRBuilder>(&mirModule);
68 }
69
70 virtual BlockNode *LowerIfStmt(IfStmtNode &ifStmt, bool recursive);
71 BlockNode *LowerSwitchStmt(SwitchNode *switchNode);
72 BlockNode *LowerBlock(BlockNode &);
73 BaseNode *LowerEmbeddedCandCior(BaseNode *x, StmtNode *curstmt, BlockNode *block);
74 void LowerCandCior(BlockNode &block);
75 void LowerBuiltinExpect(BlockNode &block);
76 void LowerFunc(MIRFunction &func);
77 MIRFuncType *FuncTypeFromFuncPtrExpr(BaseNode *x);
SetLowerME()78 void SetLowerME()
79 {
80 lowerPhase |= kShiftLowerMe;
81 }
82
SetLowerLNO()83 void SetLowerLNO()
84 {
85 lowerPhase |= kShiftLowerLNO;
86 }
87
SetLowerBE()88 void SetLowerBE()
89 {
90 lowerPhase |= kShiftLowerBe;
91 }
92
SetLowerCG()93 void SetLowerCG()
94 {
95 lowerPhase |= kShiftLowerCG;
96 }
97
GetOptLevel() const98 uint8 GetOptLevel() const
99 {
100 return optLevel;
101 }
102
SetOptLevel(uint8 optlvl)103 void SetOptLevel(uint8 optlvl)
104 {
105 optLevel = optlvl;
106 }
107
IsLowerME() const108 bool IsLowerME() const
109 {
110 return lowerPhase & kShiftLowerMe;
111 }
112
IsLowerLNO() const113 bool IsLowerLNO() const
114 {
115 return lowerPhase & kShiftLowerLNO;
116 }
117
IsLowerBE() const118 bool IsLowerBE() const
119 {
120 return lowerPhase & kShiftLowerBe;
121 }
122
IsLowerCG() const123 bool IsLowerCG() const
124 {
125 return lowerPhase & kShiftLowerCG;
126 }
127
128 static bool ShouldOptArrayMrt(const MIRFunction &func);
129
InLFO() const130 virtual bool InLFO() const
131 {
132 return false;
133 }
134
GetFuncProfData()135 GcovFuncInfo *GetFuncProfData()
136 {
137 return mirFunc->GetFuncProfData();
138 }
CopyStmtFrequency(StmtNode *newStmt, StmtNode *oldStmt)139 void CopyStmtFrequency(StmtNode *newStmt, StmtNode *oldStmt)
140 {
141 DEBUG_ASSERT(GetFuncProfData() != nullptr, "nullptr check");
142 if (newStmt == oldStmt)
143 return;
144 int64_t freq = GetFuncProfData()->GetStmtFreq(oldStmt->GetStmtID());
145 GetFuncProfData()->SetStmtFreq(newStmt->GetStmtID(), freq);
146 }
147
148 protected:
149 MIRModule &mirModule;
150
151 private:
152 MIRFunction *mirFunc;
153 MIRBuilder *mirBuilder = nullptr;
154 uint32 lowerPhase = 0;
155 uint8 optLevel = 0;
156 LabelIdx CreateCondGotoStmt(Opcode op, BlockNode &blk, const IfStmtNode &ifStmt);
157 void CreateBrFalseStmt(BlockNode &blk, const IfStmtNode &ifStmt);
158 void CreateBrTrueStmt(BlockNode &blk, const IfStmtNode &ifStmt);
159 void CreateBrFalseAndGotoStmt(BlockNode &blk, const IfStmtNode &ifStmt);
160 };
161 } // namespace maple
162 #endif // MAPLE_IR_INCLUDE_MIR_LOWER_H
163