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