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 "x64_reaching.h"
17 #include "x64_cg.h"
18 #include "insn.h"
19 #include "isa.h"
20 namespace maplebe {
21 /* find insn using register between startInsn and endInsn
22 * startInsn and endInsn must be in the same BB.
23 */
FindRegUseBetweenInsn(uint32 regNO,Insn * startInsn,Insn * endInsn,InsnSet & regUseInsnSet) const24 bool X64ReachingDefinition::FindRegUseBetweenInsn(uint32 regNO, Insn *startInsn, Insn *endInsn,
25 InsnSet ®UseInsnSet) const
26 {
27 DEBUG_ASSERT(startInsn->GetBB() == endInsn->GetBB(), "two insns must be in a same BB");
28 bool findFinish = false;
29 if (startInsn == nullptr || endInsn == nullptr) {
30 return findFinish;
31 }
32 for (Insn *insn = startInsn; insn != nullptr && insn != endInsn->GetNext(); insn = insn->GetNext()) {
33 if (!insn->IsMachineInstruction()) {
34 continue;
35 }
36 /* if insn is call and regNO is caller-saved register, then regNO will not be used later */
37 if (insn->IsCall() && IsRegKilledByCallInsn(*insn, regNO)) {
38 findFinish = true;
39 }
40
41 if (IsDiv(*insn) && regNO == x64::RAX) {
42 /* div insn use rax implicitly */
43 findFinish = true;
44 }
45
46 const InsnDesc *md = insn->GetDesc();
47 uint32 opndNum = insn->GetOperandSize();
48 for (uint32 i = 0; i < opndNum; ++i) {
49 Operand &opnd = insn->GetOperand(i);
50 /* handle def or def use */
51 auto *regProp = md->opndMD[i];
52 if (regProp->IsDef() && opnd.IsRegister() &&
53 (static_cast<RegOperand &>(opnd).GetRegisterNumber() == regNO)) {
54 findFinish = true;
55 }
56
57 if (opnd.IsList()) {
58 auto &listOpnd = static_cast<ListOperand &>(opnd);
59 for (auto listElem : listOpnd.GetOperands()) {
60 RegOperand *regOpnd = static_cast<RegOperand *>(listElem);
61 DEBUG_ASSERT(regOpnd != nullptr, "parameter operand must be RegOperand");
62 if (regNO == regOpnd->GetRegisterNumber()) {
63 (void)regUseInsnSet.insert(insn);
64 }
65 }
66 continue;
67 }
68 if (!regProp->IsUse() && !opnd.IsMemoryAccessOperand()) {
69 continue;
70 }
71
72 /* handle use */
73 if (opnd.IsMemoryAccessOperand()) {
74 auto &memOpnd = static_cast<MemOperand &>(opnd);
75 RegOperand *base = memOpnd.GetBaseRegister();
76 RegOperand *index = memOpnd.GetIndexRegister();
77 if ((base != nullptr && base->GetRegisterNumber() == regNO) ||
78 (index != nullptr && index->GetRegisterNumber() == regNO)) {
79 (void)regUseInsnSet.insert(insn);
80 }
81 } else if (opnd.IsConditionCode()) {
82 Operand &rflagOpnd = cgFunc->GetOrCreateRflag();
83 RegOperand &rflagReg = static_cast<RegOperand &>(rflagOpnd);
84 if (rflagReg.GetRegisterNumber() == regNO) {
85 (void)regUseInsnSet.insert(insn);
86 }
87 } else if (opnd.IsRegister() && (static_cast<RegOperand &>(opnd).GetRegisterNumber() == regNO)) {
88 (void)regUseInsnSet.insert(insn);
89 }
90 }
91 if (findFinish) {
92 break;
93 }
94 }
95 return findFinish;
96 }
97
FindRegDefBetweenInsnGlobal(uint32 regNO,Insn * startInsn,Insn * endInsn) const98 std::vector<Insn *> X64ReachingDefinition::FindRegDefBetweenInsnGlobal(uint32 regNO, Insn *startInsn,
99 Insn *endInsn) const
100 {
101 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
102 return {};
103 }
104
FindMemDefBetweenInsn(uint32 offset,const Insn * startInsn,Insn * endInsn) const105 std::vector<Insn *> X64ReachingDefinition::FindMemDefBetweenInsn(uint32 offset, const Insn *startInsn,
106 Insn *endInsn) const
107 {
108 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
109 return {};
110 }
111
FindRegUseBetweenInsnGlobal(uint32 regNO,Insn * startInsn,Insn * endInsn,BB * movBB) const112 bool X64ReachingDefinition::FindRegUseBetweenInsnGlobal(uint32 regNO, Insn *startInsn, Insn *endInsn, BB *movBB) const
113 {
114 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
115 return false;
116 }
117
FindMemUseBetweenInsn(uint32 offset,Insn * startInsn,const Insn * endInsn,InsnSet & useInsnSet) const118 bool X64ReachingDefinition::FindMemUseBetweenInsn(uint32 offset, Insn *startInsn, const Insn *endInsn,
119 InsnSet &useInsnSet) const
120 {
121 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
122 return false;
123 }
124
HasRegDefBetweenInsnGlobal(uint32 regNO,Insn & startInsn,Insn & endInsn)125 bool X64ReachingDefinition::HasRegDefBetweenInsnGlobal(uint32 regNO, Insn &startInsn, Insn &endInsn)
126 {
127 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
128 return false;
129 }
130
DFSFindRegDefBetweenBB(const BB & startBB,const BB & endBB,uint32 regNO,std::vector<VisitStatus> & visitedBB) const131 bool X64ReachingDefinition::DFSFindRegDefBetweenBB(const BB &startBB, const BB &endBB, uint32 regNO,
132 std::vector<VisitStatus> &visitedBB) const
133 {
134 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
135 return false;
136 }
137
FindDefForRegOpnd(Insn & insn,uint32 indexOrRegNO,bool isRegNO) const138 InsnSet X64ReachingDefinition::FindDefForRegOpnd(Insn &insn, uint32 indexOrRegNO, bool isRegNO) const
139 {
140 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
141 return {};
142 }
143
FindDefForMemOpnd(Insn & insn,uint32 indexOrOffset,bool isOffset) const144 InsnSet X64ReachingDefinition::FindDefForMemOpnd(Insn &insn, uint32 indexOrOffset, bool isOffset) const
145 {
146 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
147 return {};
148 }
149
FindUseForMemOpnd(Insn & insn,uint8 index,bool secondMem) const150 InsnSet X64ReachingDefinition::FindUseForMemOpnd(Insn &insn, uint8 index, bool secondMem) const
151 {
152 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
153 return {};
154 }
155
FindRegUsingBetweenInsn(uint32 regNO,Insn * startInsn,const Insn * endInsn) const156 bool X64ReachingDefinition::FindRegUsingBetweenInsn(uint32 regNO, Insn *startInsn, const Insn *endInsn) const
157 {
158 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
159 return false;
160 }
161
InitStartGen()162 void X64ReachingDefinition::InitStartGen()
163 {
164 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
165 return;
166 }
167
InitGenUse(BB & bb,bool firstTime)168 void X64ReachingDefinition::InitGenUse(BB &bb, bool firstTime)
169 {
170 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
171 return;
172 }
173
GenAllAsmDefRegs(BB & bb,Insn & insn,uint32 index)174 void X64ReachingDefinition::GenAllAsmDefRegs(BB &bb, Insn &insn, uint32 index)
175 {
176 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
177 return;
178 }
179
GenAllAsmUseRegs(BB & bb,Insn & insn,uint32 index)180 void X64ReachingDefinition::GenAllAsmUseRegs(BB &bb, Insn &insn, uint32 index)
181 {
182 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
183 return;
184 }
185
GenAllCallerSavedRegs(BB & bb,Insn & insn)186 void X64ReachingDefinition::GenAllCallerSavedRegs(BB &bb, Insn &insn)
187 {
188 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
189 return;
190 }
191
KilledByCallBetweenInsnInSameBB(const Insn & startInsn,const Insn & endInsn,regno_t regNO) const192 bool X64ReachingDefinition::KilledByCallBetweenInsnInSameBB(const Insn &startInsn, const Insn &endInsn,
193 regno_t regNO) const
194 {
195 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
196 return false;
197 }
198
AddRetPseudoInsn(BB & bb)199 void X64ReachingDefinition::AddRetPseudoInsn(BB &bb)
200 {
201 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
202 return;
203 }
204
IsCallerSavedReg(uint32 regNO) const205 bool X64ReachingDefinition::IsCallerSavedReg(uint32 regNO) const
206 {
207 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
208 return false;
209 }
210
FindRegDefInBB(uint32 regNO,BB & bb,InsnSet & defInsnSet) const211 void X64ReachingDefinition::FindRegDefInBB(uint32 regNO, BB &bb, InsnSet &defInsnSet) const
212 {
213 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
214 return;
215 }
216
FindMemDefInBB(uint32 offset,BB & bb,InsnSet & defInsnSet) const217 void X64ReachingDefinition::FindMemDefInBB(uint32 offset, BB &bb, InsnSet &defInsnSet) const
218 {
219 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
220 return;
221 }
222
DFSFindDefForRegOpnd(const BB & startBB,uint32 regNO,std::vector<VisitStatus> & visitedBB,InsnSet & defInsnSet) const223 void X64ReachingDefinition::DFSFindDefForRegOpnd(const BB &startBB, uint32 regNO, std::vector<VisitStatus> &visitedBB,
224 InsnSet &defInsnSet) const
225 {
226 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
227 return;
228 }
229
DFSFindDefForMemOpnd(const BB & startBB,uint32 offset,std::vector<VisitStatus> & visitedBB,InsnSet & defInsnSet) const230 void X64ReachingDefinition::DFSFindDefForMemOpnd(const BB &startBB, uint32 offset, std::vector<VisitStatus> &visitedBB,
231 InsnSet &defInsnSet) const
232 {
233 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
234 return;
235 }
236
GetStackSize() const237 int32 X64ReachingDefinition::GetStackSize() const
238 {
239 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
240 return 0;
241 };
242
AddRetPseudoInsns()243 void X64ReachingDefinition::AddRetPseudoInsns()
244 {
245 CHECK_FATAL(false, "x64_reaching analysis not implemented yet!");
246 return;
247 };
248
249 /* reg killed killed by call insn */
IsRegKilledByCallInsn(const Insn & insn,regno_t regNO) const250 bool X64ReachingDefinition::IsRegKilledByCallInsn(const Insn &insn, regno_t regNO) const
251 {
252 return !x64::IsCalleeSavedReg(static_cast<X64reg>(regNO));
253 }
254
IsDiv(const Insn & insn) const255 bool X64ReachingDefinition::IsDiv(const Insn &insn) const
256 {
257 MOperator mOp = insn.GetMachineOpcode();
258 return (MOP_idivw_r <= mOp && mOp <= MOP_divq_m);
259 }
260
261 } /* namespace maplebe */
262