• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "peep.h"
17 #include "cg.h"
18 #include "mpl_logging.h"
19 #include "common_utils.h"
20 #if TARGAARCH64
21 #include "aarch64_peep.h"
22 #elif TARGRISCV64
23 #include "riscv64_peep.h"
24 #elif defined TARGX86_64
25 #include "x64_peep.h"
26 #endif
27 #if TARGARM32
28 #include "arm32_peep.h"
29 #endif
30 
31 namespace maplebe {
32 #if TARGAARCH64
IsCCRegCrossVersion(Insn & startInsn,Insn & endInsn,const RegOperand & ccReg)33 bool CGPeepPattern::IsCCRegCrossVersion(Insn &startInsn, Insn &endInsn, const RegOperand &ccReg)
34 {
35     if (startInsn.GetBB() != endInsn.GetBB()) {
36         return true;
37     }
38     CHECK_FATAL(ssaInfo != nullptr, "must have ssaInfo");
39     CHECK_FATAL(ccReg.IsSSAForm(), "cc reg must be ssa form");
40     for (auto *curInsn = startInsn.GetNext(); curInsn != nullptr && curInsn != &endInsn; curInsn = curInsn->GetNext()) {
41         if (!curInsn->IsMachineInstruction()) {
42             continue;
43         }
44         if (curInsn->IsCall()) {
45             return true;
46         }
47         uint32 opndNum = curInsn->GetOperandSize();
48         for (uint32 i = 0; i < opndNum; ++i) {
49             Operand &opnd = curInsn->GetOperand(i);
50             if (!opnd.IsRegister()) {
51                 continue;
52             }
53             auto &regOpnd = static_cast<RegOperand &>(opnd);
54             if (!curInsn->IsRegDefined(regOpnd.GetRegisterNumber())) {
55                 continue;
56             }
57             if (static_cast<RegOperand &>(opnd).IsOfCC()) {
58                 VRegVersion *ccVersion = ssaInfo->FindSSAVersion(ccReg.GetRegisterNumber());
59                 VRegVersion *curCCVersion = ssaInfo->FindSSAVersion(regOpnd.GetRegisterNumber());
60                 CHECK_FATAL(ccVersion != nullptr && curCCVersion != nullptr,
61                             "RegVersion must not be null based on ssa");
62                 CHECK_FATAL(!ccVersion->IsDeleted() && !curCCVersion->IsDeleted(), "deleted version");
63                 if (ccVersion->GetVersionIdx() != curCCVersion->GetVersionIdx()) {
64                     return true;
65                 }
66             }
67         }
68     }
69     return false;
70 }
71 
GetLogValueAtBase2(int64 val) const72 int64 CGPeepPattern::GetLogValueAtBase2(int64 val) const
73 {
74     return (__builtin_popcountll(static_cast<uint64>(val)) == 1) ? (__builtin_ffsll(val) - 1) : -1;
75 }
76 
GetAllUseInsn(const RegOperand & defReg)77 InsnSet CGPeepPattern::GetAllUseInsn(const RegOperand &defReg)
78 {
79     InsnSet allUseInsn;
80     if ((ssaInfo != nullptr) && defReg.IsSSAForm()) {
81         VRegVersion *defVersion = ssaInfo->FindSSAVersion(defReg.GetRegisterNumber());
82         CHECK_FATAL(defVersion != nullptr, "useVRegVersion must not be null based on ssa");
83         for (auto insnInfo : defVersion->GetAllUseInsns()) {
84             Insn *secondInsn = insnInfo.second->GetInsn();
85             allUseInsn.emplace(secondInsn);
86         }
87     }
88     return allUseInsn;
89 }
90 
GetDefInsn(const RegOperand & useReg)91 Insn *CGPeepPattern::GetDefInsn(const RegOperand &useReg)
92 {
93     if (!useReg.IsSSAForm()) {
94         return nullptr;
95     }
96     regno_t useRegNO = useReg.GetRegisterNumber();
97     VRegVersion *useVersion = ssaInfo->FindSSAVersion(useRegNO);
98     DEBUG_ASSERT(useVersion != nullptr, "useVRegVersion must not be null based on ssa");
99     CHECK_FATAL(!useVersion->IsDeleted(), "deleted version");
100     DUInsnInfo *defInfo = useVersion->GetDefInsnInfo();
101     return defInfo == nullptr ? nullptr : defInfo->GetInsn();
102 }
103 
DumpAfterPattern(std::vector<Insn * > & prevInsns,const Insn * replacedInsn,const Insn * newInsn)104 void CGPeepPattern::DumpAfterPattern(std::vector<Insn *> &prevInsns, const Insn *replacedInsn, const Insn *newInsn)
105 {
106     LogInfo::MapleLogger() << ">>>>>>> In " << GetPatternName() << " : <<<<<<<\n";
107     if (!prevInsns.empty()) {
108         if ((replacedInsn == nullptr) && (newInsn == nullptr)) {
109             LogInfo::MapleLogger() << "======= RemoveInsns : {\n";
110         } else {
111             LogInfo::MapleLogger() << "======= PrevInsns : {\n";
112         }
113         for (auto *prevInsn : prevInsns) {
114             if (prevInsn != nullptr) {
115                 LogInfo::MapleLogger() << "[primal form] ";
116                 prevInsn->Dump();
117                 if (ssaInfo != nullptr) {
118                     LogInfo::MapleLogger() << "[ssa form] ";
119                     ssaInfo->DumpInsnInSSAForm(*prevInsn);
120                 }
121             }
122         }
123         LogInfo::MapleLogger() << "}\n";
124     }
125     if (replacedInsn != nullptr) {
126         LogInfo::MapleLogger() << "======= OldInsn :\n";
127         LogInfo::MapleLogger() << "[primal form] ";
128         replacedInsn->Dump();
129         if (ssaInfo != nullptr) {
130             LogInfo::MapleLogger() << "[ssa form] ";
131             ssaInfo->DumpInsnInSSAForm(*replacedInsn);
132         }
133     }
134     if (newInsn != nullptr) {
135         LogInfo::MapleLogger() << "======= NewInsn :\n";
136         LogInfo::MapleLogger() << "[primal form] ";
137         newInsn->Dump();
138         if (ssaInfo != nullptr) {
139             LogInfo::MapleLogger() << "[ssa form] ";
140             ssaInfo->DumpInsnInSSAForm(*newInsn);
141         }
142     }
143 }
144 
145 /* Check if a regOpnd is live after insn. True if live, otherwise false. */
IfOperandIsLiveAfterInsn(const RegOperand & regOpnd,Insn & insn)146 bool CGPeepPattern::IfOperandIsLiveAfterInsn(const RegOperand &regOpnd, Insn &insn)
147 {
148     for (Insn *nextInsn = insn.GetNext(); nextInsn != nullptr; nextInsn = nextInsn->GetNext()) {
149         if (!nextInsn->IsMachineInstruction()) {
150             continue;
151         }
152         int32 lastOpndId = static_cast<int32>(nextInsn->GetOperandSize() - 1);
153         for (int32 i = lastOpndId; i >= 0; --i) {
154             Operand &opnd = nextInsn->GetOperand(static_cast<uint32>(i));
155             if (opnd.IsMemoryAccessOperand()) {
156                 auto &mem = static_cast<MemOperand &>(opnd);
157                 Operand *base = mem.GetBaseRegister();
158                 Operand *offset = mem.GetOffset();
159 
160                 if (base != nullptr && base->IsRegister()) {
161                     auto *tmpRegOpnd = static_cast<RegOperand *>(base);
162                     if (tmpRegOpnd->GetRegisterNumber() == regOpnd.GetRegisterNumber()) {
163                         return true;
164                     }
165                 }
166                 if (offset != nullptr && offset->IsRegister()) {
167                     auto *tmpRegOpnd = static_cast<RegOperand *>(offset);
168                     if (tmpRegOpnd->GetRegisterNumber() == regOpnd.GetRegisterNumber()) {
169                         return true;
170                     }
171                 }
172             } else if (opnd.IsList()) {
173                 auto &opndList = static_cast<ListOperand&>(opnd).GetOperands();
174                 if (find(opndList.begin(), opndList.end(), &regOpnd) != opndList.end()) {
175                     return true;
176                 }
177             }
178 
179             if (!opnd.IsRegister()) {
180                 continue;
181             }
182             auto &tmpRegOpnd = static_cast<RegOperand &>(opnd);
183             if (opnd.IsRegister() && tmpRegOpnd.GetRegisterNumber() != regOpnd.GetRegisterNumber()) {
184                 continue;
185             }
186             const InsnDesc *md = nextInsn->GetDesc();
187             auto *regProp = (md->opndMD[static_cast<uint64>(i)]);
188             bool isUse = regProp->IsUse();
189             /* if noUse Redefined, no need to check live-out. */
190             return isUse;
191         }
192     }
193     /* Check if it is live-out. */
194     return FindRegLiveOut(regOpnd, *insn.GetBB());
195 }
196 
197 /* entrance for find if a regOpnd is live-out. */
FindRegLiveOut(const RegOperand & regOpnd,const BB & bb)198 bool CGPeepPattern::FindRegLiveOut(const RegOperand &regOpnd, const BB &bb)
199 {
200     /*
201      * Each time use peephole, index is initialized by the constructor,
202      * and the internal_flags3 should be cleared.
203      */
204     if (PeepOptimizer::index == 0) {
205         FOR_ALL_BB(currbb, cgFunc) {
206             currbb->SetInternalFlag3(0);
207         }
208     }
209     /* before each invoke check function, increase index. */
210     ++PeepOptimizer::index;
211     return CheckOpndLiveinSuccs(regOpnd, bb);
212 }
213 
214 /* Check regOpnd in succs/ehSuccs. True is live-out, otherwise false. */
CheckOpndLiveinSuccs(const RegOperand & regOpnd,const BB & bb) const215 bool CGPeepPattern::CheckOpndLiveinSuccs(const RegOperand &regOpnd, const BB &bb) const
216 {
217     for (auto succ : bb.GetSuccs()) {
218         DEBUG_ASSERT(succ->GetInternalFlag3() <= PeepOptimizer::index, "internal error.");
219         if (succ->GetInternalFlag3() == PeepOptimizer::index) {
220             continue;
221         }
222         succ->SetInternalFlag3(PeepOptimizer::index);
223         ReturnType result = IsOpndLiveinBB(regOpnd, *succ);
224         if (result == kResNotFind) {
225             if (CheckOpndLiveinSuccs(regOpnd, *succ)) {
226                 return true;
227             }
228             continue;
229         } else if (result == kResUseFirst) {
230             return true;
231         } else if (result == kResDefFirst) {
232             continue;
233         }
234     }
235     for (auto ehSucc : bb.GetEhSuccs()) {
236         DEBUG_ASSERT(ehSucc->GetInternalFlag3() <= PeepOptimizer::index, "internal error.");
237         if (ehSucc->GetInternalFlag3() == PeepOptimizer::index) {
238             continue;
239         }
240         ehSucc->SetInternalFlag3(PeepOptimizer::index);
241         ReturnType result = IsOpndLiveinBB(regOpnd, *ehSucc);
242         if (result == kResNotFind) {
243             if (CheckOpndLiveinSuccs(regOpnd, *ehSucc)) {
244                 return true;
245             }
246             continue;
247         } else if (result == kResUseFirst) {
248             return true;
249         } else if (result == kResDefFirst) {
250             continue;
251         }
252     }
253     return CheckRegLiveinReturnBB(regOpnd, bb);
254 }
255 
256 /* Check if the reg is used in return BB */
CheckRegLiveinReturnBB(const RegOperand & regOpnd,const BB & bb) const257 bool CGPeepPattern::CheckRegLiveinReturnBB(const RegOperand &regOpnd, const BB &bb) const
258 {
259 #if TARGAARCH64 || TARGRISCV64
260     if (bb.GetKind() == BB::kBBReturn) {
261         regno_t regNO = regOpnd.GetRegisterNumber();
262         RegType regType = regOpnd.GetRegisterType();
263         if (regType == kRegTyVary) {
264             return false;
265         }
266         PrimType returnType = cgFunc->GetFunction().GetReturnType()->GetPrimType();
267         regno_t returnReg = R0;
268         if (IsPrimitiveFloat(returnType)) {
269             returnReg = V0;
270         } else if (IsPrimitiveInteger(returnType)) {
271             returnReg = R0;
272         }
273         if (regNO == returnReg) {
274             return true;
275         }
276     }
277 #endif
278     return false;
279 }
280 
281 /*
282  * Check regNO in current bb:
283  * kResUseFirst:first find use point; kResDefFirst:first find define point;
284  * kResNotFind:cannot find regNO, need to continue searching.
285  */
IsOpndLiveinBB(const RegOperand & regOpnd,const BB & bb) const286 ReturnType CGPeepPattern::IsOpndLiveinBB(const RegOperand &regOpnd, const BB &bb) const
287 {
288     FOR_BB_INSNS_CONST(insn, &bb) {
289         if (!insn->IsMachineInstruction()) {
290             continue;
291         }
292         const InsnDesc *md = insn->GetDesc();
293         int32 lastOpndId = static_cast<int32>(insn->GetOperandSize() - 1);
294         for (int32 i = lastOpndId; i >= 0; --i) {
295             Operand &opnd = insn->GetOperand(static_cast<uint32>(i));
296             auto *regProp = (md->opndMD[static_cast<uint64>(i)]);
297             if (opnd.IsConditionCode()) {
298                 if (regOpnd.GetRegisterNumber() == kRFLAG) {
299                     bool isUse = regProp->IsUse();
300                     if (isUse) {
301                         return kResUseFirst;
302                     }
303                     DEBUG_ASSERT(regProp->IsDef(), "register should be redefined.");
304                     return kResDefFirst;
305                 }
306             } else if (opnd.IsList()) {
307                 auto &listOpnd = static_cast<ListOperand &>(opnd);
308                 if (insn->GetMachineOpcode() == MOP_asm) {
309                     if (static_cast<uint32>(i) == kAsmOutputListOpnd || static_cast<uint32>(i) == kAsmClobberListOpnd) {
310                         for (auto op : listOpnd.GetOperands()) {
311                             if (op->GetRegisterNumber() == regOpnd.GetRegisterNumber()) {
312                                 return kResDefFirst;
313                             }
314                         }
315                         continue;
316                     } else if (static_cast<uint32>(i) != kAsmInputListOpnd) {
317                         continue;
318                     }
319                     /* fall thru for kAsmInputListOpnd */
320                 }
321                 for (auto op : listOpnd.GetOperands()) {
322                     if (op->GetRegisterNumber() == regOpnd.GetRegisterNumber()) {
323                         return kResUseFirst;
324                     }
325                 }
326             } else if (opnd.IsMemoryAccessOperand()) {
327                 auto &mem = static_cast<MemOperand &>(opnd);
328                 Operand *base = mem.GetBaseRegister();
329                 Operand *offset = mem.GetOffset();
330 
331                 if (base != nullptr) {
332                     DEBUG_ASSERT(base->IsRegister(), "internal error.");
333                     auto *tmpRegOpnd = static_cast<RegOperand *>(base);
334                     if (tmpRegOpnd->GetRegisterNumber() == regOpnd.GetRegisterNumber()) {
335                         return kResUseFirst;
336                     }
337                 }
338                 if (offset != nullptr && offset->IsRegister()) {
339                     auto *tmpRegOpnd = static_cast<RegOperand *>(offset);
340                     if (tmpRegOpnd->GetRegisterNumber() == regOpnd.GetRegisterNumber()) {
341                         return kResUseFirst;
342                     }
343                 }
344             } else if (opnd.IsRegister()) {
345                 auto &tmpRegOpnd = static_cast<RegOperand &>(opnd);
346                 if (tmpRegOpnd.GetRegisterNumber() == regOpnd.GetRegisterNumber()) {
347                     bool isUse = regProp->IsUse();
348                     if (isUse) {
349                         return kResUseFirst;
350                     }
351                     DEBUG_ASSERT(regProp->IsDef(), "register should be redefined.");
352                     return kResDefFirst;
353                 }
354             }
355         }
356     }
357     return kResNotFind;
358 }
359 
logValueAtBase2(int64 val) const360 int PeepPattern::logValueAtBase2(int64 val) const
361 {
362     return (__builtin_popcountll(static_cast<uint64>(val)) == 1) ? (__builtin_ffsll(val) - 1) : (-1);
363 }
364 
365 /* Check if a regOpnd is live after insn. True if live, otherwise false. */
IfOperandIsLiveAfterInsn(const RegOperand & regOpnd,Insn & insn)366 bool PeepPattern::IfOperandIsLiveAfterInsn(const RegOperand &regOpnd, Insn &insn)
367 {
368     for (Insn *nextInsn = insn.GetNext(); nextInsn != nullptr; nextInsn = nextInsn->GetNext()) {
369         if (!nextInsn->IsMachineInstruction()) {
370             continue;
371         }
372         int32 lastOpndId = static_cast<int32>(nextInsn->GetOperandSize() - 1);
373         for (int32 i = lastOpndId; i >= 0; --i) {
374             Operand &opnd = nextInsn->GetOperand(static_cast<uint32>(i));
375             if (opnd.IsMemoryAccessOperand()) {
376                 auto &mem = static_cast<MemOperand &>(opnd);
377                 Operand *base = mem.GetBaseRegister();
378                 Operand *offset = mem.GetOffset();
379 
380                 if (base != nullptr && base->IsRegister()) {
381                     auto *tmpRegOpnd = static_cast<RegOperand *>(base);
382                     if (tmpRegOpnd->GetRegisterNumber() == regOpnd.GetRegisterNumber()) {
383                         return true;
384                     }
385                 }
386                 if (offset != nullptr && offset->IsRegister()) {
387                     auto *tmpRegOpnd = static_cast<RegOperand *>(offset);
388                     if (tmpRegOpnd->GetRegisterNumber() == regOpnd.GetRegisterNumber()) {
389                         return true;
390                     }
391                 }
392             } else if (opnd.IsList()) {
393                 auto &opndList = static_cast<ListOperand&>(opnd).GetOperands();
394                 if (find(opndList.begin(), opndList.end(), &regOpnd) != opndList.end()) {
395                     return true;
396                 }
397             }
398 
399             if (!opnd.IsRegister()) {
400                 continue;
401             }
402             auto &tmpRegOpnd = static_cast<RegOperand &>(opnd);
403             if (opnd.IsRegister() && tmpRegOpnd.GetRegisterNumber() != regOpnd.GetRegisterNumber()) {
404                 continue;
405             }
406             const InsnDesc *md = nextInsn->GetDesc();
407             auto *regProp = (md->opndMD[static_cast<uint64>(i)]);
408             bool isUse = regProp->IsUse();
409             /* if noUse Redefined, no need to check live-out. */
410             return isUse;
411         }
412     }
413     /* Check if it is live-out. */
414     return FindRegLiveOut(regOpnd, *insn.GetBB());
415 }
416 
417 /* entrance for find if a regOpnd is live-out. */
FindRegLiveOut(const RegOperand & regOpnd,const BB & bb)418 bool PeepPattern::FindRegLiveOut(const RegOperand &regOpnd, const BB &bb)
419 {
420     /*
421      * Each time use peephole, index is initialized by the constructor,
422      * and the internal_flags3 should be cleared.
423      */
424     if (PeepOptimizer::index == 0) {
425         FOR_ALL_BB(currbb, &cgFunc) {
426             currbb->SetInternalFlag3(0);
427         }
428     }
429     /* before each invoke check function, increase index. */
430     ++PeepOptimizer::index;
431     return CheckOpndLiveinSuccs(regOpnd, bb);
432 }
433 
434 /* Check regOpnd in succs/ehSuccs. True is live-out, otherwise false. */
CheckOpndLiveinSuccs(const RegOperand & regOpnd,const BB & bb) const435 bool PeepPattern::CheckOpndLiveinSuccs(const RegOperand &regOpnd, const BB &bb) const
436 {
437     for (auto succ : bb.GetSuccs()) {
438         DEBUG_ASSERT(succ->GetInternalFlag3() <= PeepOptimizer::index, "internal error.");
439         if (succ->GetInternalFlag3() == PeepOptimizer::index) {
440             continue;
441         }
442         succ->SetInternalFlag3(PeepOptimizer::index);
443         ReturnType result = IsOpndLiveinBB(regOpnd, *succ);
444         if (result == kResNotFind) {
445             if (CheckOpndLiveinSuccs(regOpnd, *succ)) {
446                 return true;
447             }
448             continue;
449         } else if (result == kResUseFirst) {
450             return true;
451         } else if (result == kResDefFirst) {
452             continue;
453         }
454     }
455     for (auto ehSucc : bb.GetEhSuccs()) {
456         DEBUG_ASSERT(ehSucc->GetInternalFlag3() <= PeepOptimizer::index, "internal error.");
457         if (ehSucc->GetInternalFlag3() == PeepOptimizer::index) {
458             continue;
459         }
460         ehSucc->SetInternalFlag3(PeepOptimizer::index);
461         ReturnType result = IsOpndLiveinBB(regOpnd, *ehSucc);
462         if (result == kResNotFind) {
463             if (CheckOpndLiveinSuccs(regOpnd, *ehSucc)) {
464                 return true;
465             }
466             continue;
467         } else if (result == kResUseFirst) {
468             return true;
469         } else if (result == kResDefFirst) {
470             continue;
471         }
472     }
473     return CheckRegLiveinReturnBB(regOpnd, bb);
474 }
475 
476 /* Check if the reg is used in return BB */
CheckRegLiveinReturnBB(const RegOperand & regOpnd,const BB & bb) const477 bool PeepPattern::CheckRegLiveinReturnBB(const RegOperand &regOpnd, const BB &bb) const
478 {
479 #if TARGAARCH64 || TARGRISCV64
480     if (bb.GetKind() == BB::kBBReturn) {
481         regno_t regNO = regOpnd.GetRegisterNumber();
482         RegType regType = regOpnd.GetRegisterType();
483         if (regType == kRegTyVary) {
484             return false;
485         }
486         PrimType returnType = cgFunc.GetFunction().GetReturnType()->GetPrimType();
487         regno_t returnReg = R0;
488         if (IsPrimitiveFloat(returnType)) {
489             returnReg = V0;
490         } else if (IsPrimitiveInteger(returnType)) {
491             returnReg = R0;
492         }
493         if (regNO == returnReg) {
494             return true;
495         }
496     }
497 #endif
498     return false;
499 }
500 
501 /*
502  * Check regNO in current bb:
503  * kResUseFirst:first find use point; kResDefFirst:first find define point;
504  * kResNotFind:cannot find regNO, need to continue searching.
505  */
IsOpndLiveinBB(const RegOperand & regOpnd,const BB & bb) const506 ReturnType PeepPattern::IsOpndLiveinBB(const RegOperand &regOpnd, const BB &bb) const
507 {
508     FOR_BB_INSNS_CONST(insn, &bb) {
509         if (!insn->IsMachineInstruction()) {
510             continue;
511         }
512         const InsnDesc *md = insn->GetDesc();
513         int32 lastOpndId = static_cast<int32>(insn->GetOperandSize() - 1);
514         for (int32 i = lastOpndId; i >= 0; --i) {
515             Operand &opnd = insn->GetOperand(static_cast<uint32>(i));
516             auto *regProp = (md->opndMD[static_cast<uint64>(i)]);
517             if (opnd.IsConditionCode()) {
518                 if (regOpnd.GetRegisterNumber() == kRFLAG) {
519                     bool isUse = regProp->IsUse();
520                     if (isUse) {
521                         return kResUseFirst;
522                     }
523                     DEBUG_ASSERT(regProp->IsDef(), "register should be redefined.");
524                     return kResDefFirst;
525                 }
526             } else if (opnd.IsList()) {
527                 auto &listOpnd = static_cast<ListOperand &>(opnd);
528                 if (insn->GetMachineOpcode() == MOP_asm) {
529                     if (static_cast<uint32>(i) == kAsmOutputListOpnd || static_cast<uint32>(i) == kAsmClobberListOpnd) {
530                         for (auto op : listOpnd.GetOperands()) {
531                             if (op->GetRegisterNumber() == regOpnd.GetRegisterNumber()) {
532                                 return kResDefFirst;
533                             }
534                         }
535                         continue;
536                     } else if (static_cast<uint32>(i) != kAsmInputListOpnd) {
537                         continue;
538                     }
539                     /* fall thru for kAsmInputListOpnd */
540                 }
541                 for (auto op : listOpnd.GetOperands()) {
542                     if (op->GetRegisterNumber() == regOpnd.GetRegisterNumber()) {
543                         return kResUseFirst;
544                     }
545                 }
546             } else if (opnd.IsMemoryAccessOperand()) {
547                 auto &mem = static_cast<MemOperand &>(opnd);
548                 Operand *base = mem.GetBaseRegister();
549                 Operand *offset = mem.GetOffset();
550 
551                 if (base != nullptr) {
552                     DEBUG_ASSERT(base->IsRegister(), "internal error.");
553                     auto *tmpRegOpnd = static_cast<RegOperand *>(base);
554                     if (tmpRegOpnd->GetRegisterNumber() == regOpnd.GetRegisterNumber()) {
555                         return kResUseFirst;
556                     }
557                 }
558                 if (offset != nullptr && offset->IsRegister()) {
559                     auto *tmpRegOpnd = static_cast<RegOperand *>(offset);
560                     if (tmpRegOpnd->GetRegisterNumber() == regOpnd.GetRegisterNumber()) {
561                         return kResUseFirst;
562                     }
563                 }
564             } else if (opnd.IsRegister()) {
565                 auto &tmpRegOpnd = static_cast<RegOperand &>(opnd);
566                 if (tmpRegOpnd.GetRegisterNumber() == regOpnd.GetRegisterNumber()) {
567                     bool isUse = regProp->IsUse();
568                     if (isUse) {
569                         return kResUseFirst;
570                     }
571                     DEBUG_ASSERT(regProp->IsDef(), "register should be redefined.");
572                     return kResDefFirst;
573                 }
574             }
575         }
576     }
577     return kResNotFind;
578 }
579 
IsMemOperandOptPattern(const Insn & insn,Insn & nextInsn)580 bool PeepPattern::IsMemOperandOptPattern(const Insn &insn, Insn &nextInsn)
581 {
582     /* Check if base register of nextInsn and the dest operand of insn are identical. */
583     auto *memOpnd = static_cast<MemOperand *>(nextInsn.GetMemOpnd());
584     DEBUG_ASSERT(memOpnd != nullptr, "null ptr check");
585     /* Only for AddrMode_B_OI addressing mode. */
586     if (memOpnd->GetAddrMode() != MemOperand::kAddrModeBOi) {
587         return false;
588     }
589     /* Only for immediate is  0. */
590     if (memOpnd->GetOffsetImmediate()->GetOffsetValue() != 0) {
591         return false;
592     }
593     /* Only for intact memory addressing. */
594     if (!memOpnd->IsIntactIndexed()) {
595         return false;
596     }
597 
598     auto &oldBaseOpnd = static_cast<RegOperand &>(insn.GetOperand(kInsnFirstOpnd));
599     /* Check if dest operand of insn is idential with base register of nextInsn. */
600     if (memOpnd->GetBaseRegister() != &oldBaseOpnd) {
601         return false;
602     }
603 
604 #ifdef USE_32BIT_REF
605     if (nextInsn.IsAccessRefField() && nextInsn.GetOperand(kInsnFirstOpnd).GetSize() > k32BitSize) {
606         return false;
607     }
608 #endif
609     /* Check if x0 is used after ldr insn, and if it is in live-out. */
610     if (IfOperandIsLiveAfterInsn(oldBaseOpnd, nextInsn)) {
611         return false;
612     }
613     return true;
614 }
615 
616 template <typename T>
Run()617 void PeepOptimizer::Run()
618 {
619     auto *patterMatcher = peepOptMemPool->New<T>(cgFunc, peepOptMemPool);
620     patterMatcher->InitOpts();
621     FOR_ALL_BB(bb, &cgFunc) {
622         FOR_BB_INSNS_SAFE(insn, bb, nextInsn) {
623             if (!insn->IsMachineInstruction()) {
624                 continue;
625             }
626             patterMatcher->Run(*bb, *insn);
627         }
628     }
629 }
630 
631 int32 PeepOptimizer::index = 0;
632 
Peephole0()633 void PeepHoleOptimizer::Peephole0()
634 {
635     auto memPool = std::make_unique<ThreadLocalMemPool>(memPoolCtrler, "peepholeOptObj");
636     PeepOptimizer peepOptimizer(*cgFunc, memPool.get());
637 #if TARGAARCH64 || TARGRISCV64
638     peepOptimizer.Run<AArch64PeepHole0>();
639 #endif
640 #if TARGARM32
641     peepOptimizer.Run<Arm32PeepHole0>();
642 #endif
643 }
644 
PeepholeOpt()645 void PeepHoleOptimizer::PeepholeOpt()
646 {
647     auto memPool = std::make_unique<ThreadLocalMemPool>(memPoolCtrler, "peepholeOptObj");
648     PeepOptimizer peepOptimizer(*cgFunc, memPool.get());
649 #if TARGAARCH64 || TARGRISCV64
650     peepOptimizer.Run<AArch64PeepHole>();
651 #endif
652 #if TARGARM32
653     peepOptimizer.Run<Arm32PeepHole>();
654 #endif
655 }
656 
PrePeepholeOpt()657 void PeepHoleOptimizer::PrePeepholeOpt()
658 {
659     auto memPool = std::make_unique<ThreadLocalMemPool>(memPoolCtrler, "peepholeOptObj");
660     PeepOptimizer peepOptimizer(*cgFunc, memPool.get());
661 #if TARGAARCH64 || TARGRISCV64
662     peepOptimizer.Run<AArch64PrePeepHole>();
663 #endif
664 #if TARGARM32
665     peepOptimizer.Run<Arm32PrePeepHole>();
666 #endif
667 }
668 
PrePeepholeOpt1()669 void PeepHoleOptimizer::PrePeepholeOpt1()
670 {
671     auto memPool = std::make_unique<ThreadLocalMemPool>(memPoolCtrler, "peepholeOptObj");
672     PeepOptimizer peepOptimizer(*cgFunc, memPool.get());
673 #if TARGAARCH64 || TARGRISCV64
674     peepOptimizer.Run<AArch64PrePeepHole1>();
675 #endif
676 #if TARGARM32
677     peepOptimizer.Run<Arm32PrePeepHole1>();
678 #endif
679 }
680 
681 /* === SSA form === */
PhaseRun(maplebe::CGFunc & f)682 bool CgPeepHole::PhaseRun(maplebe::CGFunc &f)
683 {
684     CGSSAInfo *cgssaInfo = GET_ANALYSIS(CgSSAConstruct, f);
685     CHECK_FATAL((cgssaInfo != nullptr), "Get ssaInfo failed!");
686     MemPool *mp = GetPhaseMemPool();
687     auto *cgpeep = mp->New<AArch64CGPeepHole>(f, mp, cgssaInfo);
688     CHECK_FATAL((cgpeep != nullptr), "Creat AArch64CGPeepHole failed!");
689     cgpeep->Run();
690     return false;
691 }
692 
GetAnalysisDependence(AnalysisDep & aDep) const693 void CgPeepHole::GetAnalysisDependence(AnalysisDep &aDep) const
694 {
695     aDep.AddRequired<CgSSAConstruct>();
696     aDep.AddPreserved<CgSSAConstruct>();
697 }
MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(CgPeepHole,cgpeephole)698 MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(CgPeepHole, cgpeephole)
699 #endif
700 /* === Physical Pre Form === */
701 bool CgPrePeepHole::PhaseRun(maplebe::CGFunc &f)
702 {
703     MemPool *mp = GetPhaseMemPool();
704 #if defined TARGAARCH64
705     auto *cgpeep = mp->New<AArch64CGPeepHole>(f, mp);
706 #elif defined TARGX86_64
707     auto *cgpeep = mp->New<X64CGPeepHole>(f, mp);
708 #endif
709     CHECK_FATAL(cgpeep != nullptr, "PeepHoleOptimizer instance create failure");
710     cgpeep->Run();
711     return false;
712 }
MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(CgPrePeepHole,cgprepeephole)713 MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(CgPrePeepHole, cgprepeephole)
714 
715 /* === Physical Post Form === */
716 bool CgPostPeepHole::PhaseRun(maplebe::CGFunc &f)
717 {
718     MemPool *mp = GetPhaseMemPool();
719 #if defined TARGAARCH64
720     auto *cgpeep = mp->New<AArch64CGPeepHole>(f, mp);
721 #elif defined TARGX86_64
722     auto *cgpeep = mp->New<X64CGPeepHole>(f, mp);
723 #endif
724     CHECK_FATAL(cgpeep != nullptr, "PeepHoleOptimizer instance create failure");
725     cgpeep->Run();
726     return false;
727 }
MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(CgPostPeepHole,cgpostpeephole)728 MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(CgPostPeepHole, cgpostpeephole)
729 
730 #if TARGAARCH64
731 bool CgPrePeepHole0::PhaseRun(maplebe::CGFunc &f)
732 {
733     auto *peep = GetPhaseMemPool()->New<PeepHoleOptimizer>(&f);
734     CHECK_FATAL(peep != nullptr, "PeepHoleOptimizer instance create failure");
735     peep->PrePeepholeOpt();
736     return false;
737 }
MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(CgPrePeepHole0,prepeephole)738 MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(CgPrePeepHole0, prepeephole)
739 
740 bool CgPrePeepHole1::PhaseRun(maplebe::CGFunc &f)
741 {
742     auto *peep = GetPhaseMemPool()->New<PeepHoleOptimizer>(&f);
743     CHECK_FATAL(peep != nullptr, "PeepHoleOptimizer instance create failure");
744     peep->PrePeepholeOpt1();
745     return false;
746 }
MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(CgPrePeepHole1,prepeephole1)747 MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(CgPrePeepHole1, prepeephole1)
748 
749 bool CgPeepHole0::PhaseRun(maplebe::CGFunc &f)
750 {
751     auto *peep = GetPhaseMemPool()->New<PeepHoleOptimizer>(&f);
752     CHECK_FATAL(peep != nullptr, "PeepHoleOptimizer instance create failure");
753     peep->Peephole0();
754     return false;
755 }
MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(CgPeepHole0,peephole0)756 MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(CgPeepHole0, peephole0)
757 
758 bool CgPeepHole1::PhaseRun(maplebe::CGFunc &f)
759 {
760     auto *peep = GetPhaseMemPool()->New<PeepHoleOptimizer>(&f);
761     CHECK_FATAL(peep != nullptr, "PeepHoleOptimizer instance create failure");
762     peep->PeepholeOpt();
763     return false;
764 }
765 MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(CgPeepHole1, peephole)
766 #endif
767 
768 } /* namespace maplebe */
769