• 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 #ifndef MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_PEEP_H
17 #define MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_PEEP_H
18 
19 #include <vector>
20 #include "peep.h"
21 #include "aarch64_isa.h"
22 #include "cg_ssa.h"
23 #include "optimize_common.h"
24 #include "mir_builder.h"
25 
26 namespace maplebe {
27 class AArch64CGPeepHole : public CGPeepHole {
28 public:
29     /* normal constructor */
AArch64CGPeepHole(CGFunc & f,MemPool * memPool)30     AArch64CGPeepHole(CGFunc &f, MemPool *memPool) : CGPeepHole(f, memPool) {};
31     /* constructor for ssa */
AArch64CGPeepHole(CGFunc & f,MemPool * memPool,CGSSAInfo * cgssaInfo)32     AArch64CGPeepHole(CGFunc &f, MemPool *memPool, CGSSAInfo *cgssaInfo) : CGPeepHole(f, memPool, cgssaInfo) {};
33     ~AArch64CGPeepHole() override = default;
34 
35     void Run() override;
36     bool DoSSAOptimize(BB &bb, Insn &insn) override;
37     void DoNormalOptimize(BB &bb, Insn &insn) override;
38 };
39 
40 /*
41  * i.   cmp     x0, x1
42  *      cset    w0, EQ     ===>   cmp x0, x1
43  *      cmp     w0, #0            cset w0, EQ
44  *      cset    w0, NE
45  *
46  * ii.  cmp     x0, x1
47  *      cset    w0, EQ     ===>   cmp x0, x1
48  *      cmp     w0, #0            cset w0, NE
49  *      cset    w0, EQ
50  */
51 class ContinuousCmpCsetPattern : public CGPeepPattern {
52 public:
ContinuousCmpCsetPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)53     ContinuousCmpCsetPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
54         : CGPeepPattern(cgFunc, currBB, currInsn, info)
55     {
56     }
57     ~ContinuousCmpCsetPattern() override = default;
58     void Run(BB &bb, Insn &insn) override;
59     bool CheckCondition(Insn &insn) override;
GetPatternName()60     std::string GetPatternName() override
61     {
62         return "ContinuousCmpCsetPattern";
63     }
64 
65 private:
66     bool CheckCondCode(const CondOperand &condOpnd) const;
67     Insn *prevCmpInsn = nullptr;
68     Insn *prevCsetInsn1 = nullptr;
69     Insn *prevCmpInsn1 = nullptr;
70     bool reverse = false;
71 };
72 
73 /* Condition: mov_imm1 value is 0(1/-1) && mov_imm value is 1/-1(0)
74  *
75  * Pattern 1: Two mov insn + One csel insn
76  *
77  * Example 1:
78  *   mov w5, #1
79  *   ...
80  *   mov w0, #0
81  *   csel w5, w5, w0, NE    ===> cset   w5, NE
82  *
83  * Example 2:
84  *   mov w5, #0
85  *   ...
86  *   mov w0, #-1
87  *   csel w5, w5, w0, NE    ===> csetm  w5, EQ
88  *
89  * Pattern 2: One mov insn + One csel insn with RZR
90  *
91  * Example 1:
92  *   mov   w0, #4294967295
93  *   ......                       ====>        csetm  w1, EQ
94  *   csel  w1, w0, wzr, EQ
95  *
96  * Example 2:
97  *   mov   w0, #1
98  *   ......                       ====>        cset   w1, LE
99  *   csel  w1, wzr, w0, GT
100  */
101 class CselToCsetPattern : public CGPeepPattern {
102 public:
CselToCsetPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)103     CselToCsetPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
104         : CGPeepPattern(cgFunc, currBB, currInsn, info)
105     {
106     }
CselToCsetPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)107     CselToCsetPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
108     ~CselToCsetPattern() override = default;
109     void Run(BB &bb, Insn &insn) override;
110     bool CheckCondition(Insn &insn) override;
GetPatternName()111     std::string GetPatternName() override
112     {
113         return "CselToCsetPattern";
114     }
115 
116 private:
117     bool IsOpndDefByZero(const Insn &insn) const;
118     bool IsOpndDefByOne(const Insn &insn) const;
119     bool IsOpndDefByAllOnes(const Insn &insn) const;
120     bool CheckZeroCondition(const Insn &insn);
121     Insn *BuildCondSetInsn(const Insn &cselInsn) const;
122     void ZeroRun(BB &bb, Insn &insn);
123     bool isOne = false;
124     bool isAllOnes = false;
125     bool isZeroBefore = false;
126     Insn *prevMovInsn = nullptr;
127     Insn *prevMovInsn1 = nullptr;
128     Insn *prevMovInsn2 = nullptr;
129     RegOperand *useReg = nullptr;
130 };
131 
132 // cmp w2, w3/imm
133 // csel w0, w1, w1, NE   ===> mov w0, w1
134 class CselToMovPattern : public CGPeepPattern {
135 public:
CselToMovPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)136     CselToMovPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
137     ~CselToMovPattern() override = default;
138     void Run(BB &bb, Insn &insn) override;
139     bool CheckCondition(Insn &insn) override;
GetPatternName()140     std::string GetPatternName() override
141     {
142         return "CselToMovPattern";
143     }
144 };
145 
146 /*
147  *  mov w1, #1
148  *  csel w2, w1, w0, EQ    ===> csinc w2, w0, WZR, NE
149  *
150  *  mov w1, #1
151  *  csel w2, w0, w1, EQ     ===> csinc w2, w0, WZR, EQ
152  */
153 class CselToCsincRemoveMovPattern : public CGPeepPattern {
154 public:
CselToCsincRemoveMovPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)155     CselToCsincRemoveMovPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
156         : CGPeepPattern(cgFunc, currBB, currInsn, info)
157     {
158     }
159     ~CselToCsincRemoveMovPattern() override = default;
160     void Run(BB &bb, Insn &insn) override;
161     bool CheckCondition(Insn &insn) override;
GetPatternName()162     std::string GetPatternName() override
163     {
164         return "CselToCsincRemoveMovPattern";
165     }
166 
167 private:
168     bool IsOpndMovOneAndNewOpndOpt(const Insn &curInsn);
169     Insn *prevMovInsn = nullptr;
170     RegOperand *newSecondOpnd = nullptr;
171     CondOperand *cond = nullptr;
172     bool needReverseCond = false;
173 };
174 
175 /*
176  *  cset w0, HS
177  *  add w2, w1, w0    ===> cinc w2, w1, hs
178  *
179  *  cset w0, HS
180  *  add w2, w0, w1    ===> cinc w2, w1, hs
181  */
182 class CsetToCincPattern : public CGPeepPattern {
183 public:
CsetToCincPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)184     CsetToCincPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
185         : CGPeepPattern(cgFunc, currBB, currInsn, info)
186     {
187     }
~CsetToCincPattern()188     ~CsetToCincPattern() override
189     {
190         defInsn = nullptr;
191     }
192     void Run(BB &bb, Insn &insn) override;
193     bool CheckCondition(Insn &insn) override;
194     bool CheckDefInsn(const RegOperand &opnd, Insn &insn);
195     bool CheckRegTyCc(const Insn &tempDefInsn, Insn &insn) const;
GetPatternName()196     std::string GetPatternName() override
197     {
198         return "CsetToCincPattern";
199     }
200 
201 private:
202     Insn *defInsn = nullptr;
203     int32 csetOpnd1 = 0;
204 };
205 
206 /*
207  * combine cset & cbz/cbnz ---> beq/bne
208  * Example 1)
209  *  cset    w0, EQ            or       cset    w0, NE
210  *  cbnz    w0, .label                 cbnz    w0, .label
211  *  ===> beq .label                    ===> bne .label
212  *
213  * Case: same conditon_code
214  *
215  * Example 2)
216  *  cset    w0, EQ            or       cset    w0, NE
217  *  cbz     w0, .label                 cbz    w0, .label
218  *  ===> bne .label                    ===> beq .label
219  *
220  * Case: reversed condition_code
221  */
222 class CsetCbzToBeqPattern : public CGPeepPattern {
223 public:
CsetCbzToBeqPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)224     CsetCbzToBeqPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
225         : CGPeepPattern(cgFunc, currBB, currInsn, info)
226     {
227     }
228     ~CsetCbzToBeqPattern() override = default;
GetPatternName()229     std::string GetPatternName() override
230     {
231         return "CsetCbzToBeqPattern";
232     }
233     bool CheckCondition(Insn &insn) override;
234     void Run(BB &bb, Insn &insn) override;
235 
236 private:
237     MOperator SelectNewMop(ConditionCode condCode, bool inverse) const;
238     Insn *prevInsn = nullptr;
239     LabelOperand *labelOpnd = nullptr;
240 };
241 
242 /*
243  * combine neg & cmp --> cmn
244  * Example 1)
245  *  neg x0, x6
246  *  cmp x2, x0                --->    (currInsn)
247  *  ===> cmn x2, x6
248  *
249  * Example 2)
250  *  neg x0, x6, LSL #5
251  *  cmp x2, x0                --->    (currInsn)
252  *  ===> cmn x2, x6, LSL #5
253  *
254  * Conditions:
255  * 1. neg_amount_val is valid in cmn amount range
256  */
257 class NegCmpToCmnPattern : public CGPeepPattern {
258 public:
NegCmpToCmnPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)259     NegCmpToCmnPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
260         : CGPeepPattern(cgFunc, currBB, currInsn, info)
261     {
262     }
263     ~NegCmpToCmnPattern() override = default;
264     void Run(BB &bb, Insn &insn) override;
265     bool CheckCondition(Insn &insn) override;
GetPatternName()266     std::string GetPatternName() override
267     {
268         return "NegCmpToCmnPattern";
269     }
270 
271 private:
272     Insn *prevInsn = nullptr;
273 };
274 
275 /*
276  * case:
277  * ldr R261(32), [R197, #300]
278  * ldr R262(32), [R208, #12]
279  * cmp (CC) R261, R262
280  * bne lable175.
281  * ldr R264(32), [R197, #304]
282  * ldr R265(32), [R208, #16]
283  * cmp (CC) R264, R265
284  * bne lable175.
285  * ====>
286  * ldr R261(64), [R197, #300]
287  * ldr R262(64), [R208, #12]
288  * cmp (CC) R261, R262
289  * bne lable175.
290  */
291 class LdrCmpPattern : public CGPeepPattern {
292 public:
LdrCmpPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)293     LdrCmpPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~LdrCmpPattern()294     ~LdrCmpPattern() override
295     {
296         prevLdr1 = nullptr;
297         prevLdr2 = nullptr;
298         ldr1 = nullptr;
299         ldr2 = nullptr;
300         prevCmp = nullptr;
301         bne1 = nullptr;
302         bne2 = nullptr;
303     }
304     void Run(BB &bb, Insn &insn) override;
305     bool CheckCondition(Insn &insn) override;
GetPatternName()306     std::string GetPatternName() override
307     {
308         return "LdrCmpPattern";
309     }
310 
311 private:
IsLdr(const Insn * insn)312     bool IsLdr(const Insn *insn) const
313     {
314         if (insn == nullptr) {
315             return false;
316         }
317         return insn->GetMachineOpcode() == MOP_wldr;
318     }
319 
IsCmp(const Insn * insn)320     bool IsCmp(const Insn *insn) const
321     {
322         if (insn == nullptr) {
323             return false;
324         }
325         return insn->GetMachineOpcode() == MOP_wcmprr;
326     }
327 
IsBne(const Insn * insn)328     bool IsBne(const Insn *insn) const
329     {
330         if (insn == nullptr) {
331             return false;
332         }
333         return insn->GetMachineOpcode() == MOP_bne;
334     }
335 
336     bool SetInsns();
337     bool CheckInsns() const;
338     bool MemOffet4Bit(const MemOperand &m1, const MemOperand &m2) const;
339     Insn *prevLdr1 = nullptr;
340     Insn *prevLdr2 = nullptr;
341     Insn *ldr1 = nullptr;
342     Insn *ldr2 = nullptr;
343     Insn *prevCmp = nullptr;
344     Insn *bne1 = nullptr;
345     Insn *bne2 = nullptr;
346 };
347 
348 /*
349  * combine {sxtw / uxtw} & lsl ---> {sbfiz / ubfiz}
350  * sxtw  x1, w0
351  * lsl   x2, x1, #3    ===>   sbfiz x2, x0, #3, #32
352  *
353  * uxtw  x1, w0
354  * lsl   x2, x1, #3    ===>   ubfiz x2, x0, #3, #32
355  */
356 class ExtLslToBitFieldInsertPattern : public CGPeepPattern {
357 public:
ExtLslToBitFieldInsertPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)358     ExtLslToBitFieldInsertPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
359         : CGPeepPattern(cgFunc, currBB, currInsn, info)
360     {
361     }
362     ~ExtLslToBitFieldInsertPattern() override = default;
GetPatternName()363     std::string GetPatternName() override
364     {
365         return "ExtLslToBitFieldInsertPattern";
366     }
367     bool CheckCondition(Insn &insn) override;
368     void Run(BB &bb, Insn &insn) override;
369 
370 private:
371     Insn *prevInsn = nullptr;
372 };
373 
374 /*
375  * Optimize the following patterns:
376  * Example 1)
377  *  and  w0, w6, #1  ====> tbz  w6, #0, .label
378  *  cmp  w0, #1
379  *  bne  .label
380  *
381  *  and  w0, w6, #16  ====> tbz  w6, #4, .label
382  *  cmp  w0, #16
383  *  bne  .label
384  *
385  *  and  w0, w6, #32  ====> tbnz  w6, #5, .label
386  *  cmp  w0, #32
387  *  beq  .label
388  *
389  * Conditions:
390  * 1. cmp_imm value == and_imm value
391  * 2. (and_imm value is (1 << n)) && (cmp_imm value is (1 << n))
392  *
393  * Example 2)
394  *  and  x0, x6, #32  ====> tbz  x6, #5, .label
395  *  cmp  x0, #0
396  *  beq  .label
397  *
398  *  and  x0, x6, #32  ====> tbnz  x6, #5, .label
399  *  cmp  x0, #0
400  *  bne  .labelSimplifyMulArithmeticPattern
401  *
402  * Conditions:
403  * 1. (cmp_imm value is 0) || (cmp_imm == and_imm)
404  * 2. and_imm value is (1 << n)
405  */
406 class AndCmpBranchesToTbzPattern : public CGPeepPattern {
407 public:
AndCmpBranchesToTbzPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)408     AndCmpBranchesToTbzPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
409         : CGPeepPattern(cgFunc, currBB, currInsn, info)
410     {
411     }
412     ~AndCmpBranchesToTbzPattern() override = default;
413     void Run(BB &bb, Insn &insn) override;
414     bool CheckCondition(Insn &insn) override;
GetPatternName()415     std::string GetPatternName() override
416     {
417         return "AndCmpBranchesToTbzPattern";
418     }
419 
420 private:
421     bool CheckAndSelectPattern(const Insn &currInsn);
422     Insn *prevAndInsn = nullptr;
423     Insn *prevCmpInsn = nullptr;
424     MOperator newMop = MOP_undef;
425     int64 tbzImmVal = -1;
426 };
427 
428 /*
429  * optimize the following patterns:
430  * Example 1)
431  * cmp w1, wzr
432  * bge .label        ====> tbz w1, #31, .label
433  *
434  * cmp wzr, w1
435  * ble .label        ====> tbz w1, #31, .label
436  *
437  * cmp w1,wzr
438  * blt .label        ====> tbnz w1, #31, .label
439  *
440  * cmp wzr, w1
441  * bgt .label        ====> tbnz w1, #31, .label
442  *
443  *
444  * Example 2)
445  * cmp w1, #0
446  * bge .label        ====> tbz w1, #31, .label
447  *
448  * cmp w1, #0
449  * blt .label        ====> tbnz w1, #31, .label
450  */
451 class ZeroCmpBranchesToTbzPattern : public CGPeepPattern {
452 public:
ZeroCmpBranchesToTbzPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)453     ZeroCmpBranchesToTbzPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
454         : CGPeepPattern(cgFunc, currBB, currInsn, info)
455     {
456     }
457     ~ZeroCmpBranchesToTbzPattern() override = default;
458     void Run(BB &bb, Insn &insn) override;
459     bool CheckCondition(Insn &insn) override;
GetPatternName()460     std::string GetPatternName() override
461     {
462         return "ZeroCmpBranchesToTbzPattern";
463     }
464 
465 private:
466     bool CheckAndSelectPattern(const Insn &currInsn);
467     Insn *prevInsn = nullptr;
468     MOperator newMop = MOP_undef;
469     RegOperand *regOpnd = nullptr;
470 };
471 
472 /*
473  * mvn  w3, w3          ====> bic  w3, w5, w3
474  * and  w3, w5, w3
475  * ====>
476  * mvn  x3, x3          ====> bic  x3, x5, x3
477  * and  x3, x5, x3
478  */
479 class MvnAndToBicPattern : public CGPeepPattern {
480 public:
MvnAndToBicPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)481     MvnAndToBicPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
482         : CGPeepPattern(cgFunc, currBB, currInsn, info)
483     {
484     }
485     ~MvnAndToBicPattern() override = default;
486     void Run(BB &bb, Insn &insn) override;
487     bool CheckCondition(Insn &insn) override;
GetPatternName()488     std::string GetPatternName() override
489     {
490         return "MvnAndToBicPattern";
491     }
492 
493 private:
494     Insn *prevInsn1 = nullptr;
495     Insn *prevInsn2 = nullptr;
496     bool op1IsMvnDef = false;
497     bool op2IsMvnDef = false;
498 };
499 
500 // redundancy and elimination
501 // and    w9, w8, #65535
502 // rev16  w10, w9                  rev16  w10, w8
503 // strh   w10, [x0,#10]    ===>    strh   w10, [x0,#10]
504 class DeleteAndBeforeRevStrPattern : public CGPeepPattern {
505 public:
DeleteAndBeforeRevStrPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)506     DeleteAndBeforeRevStrPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
507         : CGPeepPattern(cgFunc, currBB, currInsn, info)
508     {
509     }
DeleteAndBeforeRevStrPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)510     DeleteAndBeforeRevStrPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn)
511     {
512     }
~DeleteAndBeforeRevStrPattern()513     ~DeleteAndBeforeRevStrPattern() override {}
514     void Run(BB &bb, Insn &insn) override;
515     bool CheckCondition(Insn &insn) override;
GetPatternName()516     std::string GetPatternName() override
517     {
518         return "DeleteAndBeforeRevStrPattern";
519     }
520 };
521 
522 /*
523  * and r0, r1, #4                  (the imm is n power of 2)
524  * ...
525  * cbz r0, .Label
526  * ===>  tbz r1, #2, .Label
527  *
528  * and r0, r1, #4                  (the imm is n power of 2)
529  * ...
530  * cbnz r0, .Label
531  * ===>  tbnz r1, #2, .Label
532  */
533 class AndCbzToTbzPattern : public CGPeepPattern {
534 public:
AndCbzToTbzPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)535     AndCbzToTbzPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
536         : CGPeepPattern(cgFunc, currBB, currInsn, info)
537     {
538     }
AndCbzToTbzPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)539     AndCbzToTbzPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
540     ~AndCbzToTbzPattern() override = default;
541     void Run(BB &bb, Insn &insn) override;
542     bool CheckCondition(Insn &insn) override;
GetPatternName()543     std::string GetPatternName() override
544     {
545         return "AndCbzToTbzPattern";
546     }
547 
548 private:
549     Insn *prevInsn = nullptr;
550 };
551 
552 /* and r0, r1, #1
553  * ...
554  * tbz r0, #0, .label
555  * ===> tbz r1, #0 .label
556  */
557 class AndTbzPattern : public CGPeepPattern {
558 public:
AndTbzPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)559     AndTbzPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
560         : CGPeepPattern(cgFunc, currBB, currInsn, info)
561     {
562     }
AndTbzPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)563     AndTbzPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~AndTbzPattern()564     ~AndTbzPattern() override
565     {
566         prevInsn = nullptr;
567     }
568     void Run(BB &bb, Insn &insn) override;
569     bool CheckCondition(Insn &insn) override;
GetPatternName()570     std::string GetPatternName() override
571     {
572         return "AndTbzPattern";
573     }
574 
575 private:
576     Insn *prevInsn = nullptr;
577 };
578 
579 /* Norm pattern
580  * combine {rev / rev16} & {tbz / tbnz} ---> {tbz / tbnz}
581  * rev16  w0, w0
582  * tbz    w0, #14    ===>   tbz w0, #6
583  *
584  * rev  w0, w0
585  * tbz  w0, #14    ===>   tbz w0, #22
586  */
587 class NormRevTbzToTbzPattern : public CGPeepPattern {
588 public:
NormRevTbzToTbzPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)589     NormRevTbzToTbzPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
590         : CGPeepPattern(cgFunc, currBB, currInsn, info)
591     {
592     }
NormRevTbzToTbzPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)593     NormRevTbzToTbzPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~NormRevTbzToTbzPattern()594     ~NormRevTbzToTbzPattern() override
595     {
596         tbzInsn = nullptr;
597     }
GetPatternName()598     std::string GetPatternName() override
599     {
600         return "NormRevTbzToTbzPattern";
601     }
602     bool CheckCondition(Insn &insn) override;
603     void Run(BB &bb, Insn &insn) override;
604 
605 private:
606     void SetRev16Value(const uint32 &oldValue, uint32 &revValue) const;
607     void SetWrevValue(const uint32 &oldValue, uint32 &revValue) const;
608     void SetXrevValue(const uint32 &oldValue, uint32 &revValue) const;
609     Insn *tbzInsn = nullptr;
610 };
611 
612 /* Add/Sub & load/store insn mergence pattern:
613  * add  x0, x0, #255
614  * ldr  w1, [x0]        ====>    ldr  w1, [x0, #255]!
615  *
616  * stp  w1, w2, [x0]
617  * sub  x0, x0, #256    ====>    stp  w1, w2, [x0], #-256
618  * If new load/store insn is invalid and should be split, the pattern optimization will not work.
619  */
620 class AddSubMergeLdStPattern : public CGPeepPattern {
621 public:
AddSubMergeLdStPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)622     AddSubMergeLdStPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
623         : CGPeepPattern(cgFunc, currBB, currInsn, info)
624     {
625     }
AddSubMergeLdStPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)626     AddSubMergeLdStPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
627     ~AddSubMergeLdStPattern() override = default;
GetPatternName()628     std::string GetPatternName() override
629     {
630         return "AddSubMergeLdStPattern";
631     }
632     bool CheckCondition(Insn &insn) override;
633     void Run(BB &bb, Insn &insn) override;
634 
635 private:
636     bool CheckIfCanBeMerged(const Insn *adjacentInsn, const Insn &insn);
637     Insn *FindRegInBB(const Insn &insn, bool isAbove) const;
638     Insn *nextInsn = nullptr;
639     Insn *prevInsn = nullptr;
640     Insn *insnToBeReplaced = nullptr;
641     bool isAddSubFront = false;
642     bool isLdStFront = false;
643     bool isInsnAdd = false;
644     RegOperand *insnDefReg = nullptr;
645     RegOperand *insnUseReg = nullptr;
646 };
647 
648 class CombineSameArithmeticPattern : public CGPeepPattern {
649 public:
CombineSameArithmeticPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)650     CombineSameArithmeticPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
651         : CGPeepPattern(cgFunc, currBB, currInsn, info)
652     {
653     }
~CombineSameArithmeticPattern()654     ~CombineSameArithmeticPattern() override
655     {
656         prevInsn = nullptr;
657         newImmOpnd = nullptr;
658     }
659     void Run(BB &bb, Insn &insn) override;
660     bool CheckCondition(Insn &insn) override;
GetPatternName()661     std::string GetPatternName() override
662     {
663         return "CombineSameArithmeticPattern";
664     }
665 
666 private:
667     std::vector<MOperator> validMops = {MOP_wlsrrri5, MOP_xlsrrri6,  MOP_wasrrri5,  MOP_xasrrri6,  MOP_wlslrri5,
668                                         MOP_xlslrri6, MOP_waddrri12, MOP_xaddrri12, MOP_wsubrri12, MOP_xsubrri12};
669     Insn *prevInsn = nullptr;
670     ImmOperand *newImmOpnd = nullptr;
671 };
672 
673 /*
674  * Specific Extension Elimination, includes sxt[b|h|w] & uxt[b|h|w]. There are  scenes:
675  * 1. PrevInsn is mov
676  * Example 1)
677  *  mov    w0, #imm                    or    mov    w0, #imm
678  *  sxt{}  w0, w0                            uxt{}  w0, w0
679  *  ===> mov w0, #imm                        ===> mov w0, #imm
680  *       mov w0, w0                               mov w0, w0
681  *
682  * Example 2)
683  *  mov    w0, R0
684  *  uxt{}  w0, w0
685  *  ===> mov w0, R0
686  *       mov w0, w0
687  *
688  * Conditions:
689  * 1) #imm is not out of range depend on extention valid bits.
690  * 2) [mov w0, R0] is return value of call and return size is not of range
691  * 3) mov.destOpnd.size = ext.destOpnd.size
692  *
693  *
694  * 2. PrevInsn is ldr[b|h|sb|sh]
695  * Example 1)
696  *  ldrb x1, []
697  *  and  x1, x1, #imm
698  *  ===> ldrb x1, []
699  *       mov  x1, x1
700  *
701  * Example 2)
702  *  ldrb x1, []           or   ldrb x1, []          or   ldrsb x1, []          or   ldrsb x1, []          or
703  *  sxtb x1, x1                uxtb x1, x1               sxtb  x1, x1               uxtb  x1, x1
704  *  ===> ldrsb x1, []          ===> ldrb x1, []          ===> ldrsb x1, []          ===> ldrb x1, []
705  *       mov   x1, x1               mov  x1, x1               mov   x1, x1               mov  x1, x1
706  *
707  *  ldrh x1, []           or   ldrh x1, []          or   ldrsh x1, []          or   ldrsh x1, []          or
708  *  sxth x1, x1                uxth x1, x1               sxth  x1, x1               uxth  x1, x1
709  *  ===> ldrsh x1, []          ===> ldrh x1, []          ===> ldrsh x1, []          ===> ldrb x1, []
710  *       mov   x1, x1               mov  x1, x1               mov   x1, x1               mov  x1, x1
711  *
712  *  ldrsw x1, []          or   ldrsw x1, []
713  *  sxtw  x1, x1               uxtw x1, x1
714  *  ===> ldrsw x1, []          ===> no change
715  *       mov   x1, x1
716  *
717  * Example 3)
718  *  ldrb x1, []           or   ldrb x1, []          or   ldrsb x1, []          or   ldrsb x1, []          or
719  *  sxth x1, x1                uxth x1, x1               sxth  x1, x1               uxth  x1, x1
720  *  ===> ldrb x1, []           ===> ldrb x1, []          ===> ldrsb x1, []          ===> no change
721  *       mov  x1, x1                mov  x1, x1               mov   x1, x1
722  *
723  *  ldrb x1, []           or   ldrh x1, []          or   ldrsb x1, []          or   ldrsh x1, []          or
724  *  sxtw x1, x1                sxtw x1, x1               sxtw  x1, x1               sxtw  x1, x1
725  *  ===> ldrb x1, []           ===> ldrh x1, []          ===> ldrsb x1, []          ===> ldrsh x1, []
726  *       mov  x1, x1                mov  x1, x1               mov   x1, x1               mov   x1, x1
727  *
728  *  ldr  x1, []
729  *  sxtw x1, x1
730  *  ===> ldrsw x1, []
731  *       mov   x1, x1
732  *
733  * Cases:
734  * 1) extension size == load size -> change the load type or eliminate the extension
735  * 2) extension size >  load size -> possibly eliminating the extension
736  *
737  *
738  * 3. PrevInsn is same sxt / uxt
739  * Example 1)
740  *  sxth x1, x2
741  *  sxth x3, x1
742  *  ===> sxth x1, x2
743  *       mov  x3, x1
744  *
745  * Example 2)
746  *  sxtb x1, x2          or    uxtb  w0, w0
747  *  sxth x3, x1                uxth  w0, w0
748  *  ===> sxtb x1, x2           ===> uxtb  w0, w0
749  *       mov  x3, x1                mov   x0, x0
750  *
751  * Conditions:
752  * 1) ext1.destOpnd.size == ext2.destOpnd.size
753  * 2) ext1.destOpnd.regNo == ext2.destOpnd.regNo
754  *    === prop ext1.destOpnd to ext2.srcOpnd, transfer ext2 to mov
755  *
756  * Cases:
757  * 1) ext1 type == ext2 type ((sxth32 & sxth32) || (sxth64 & sxth64) || ...)
758  * 2) ext1 type  < ext2 type ((sxtb32 & sxth32) || (sxtb64 & sxth64) || (sxtb64 & sxtw64) ||
759  *                            (sxth64 & sxtw64) || (uxtb32 & uxth32))
760  */
761 class ElimSpecificExtensionPattern : public CGPeepPattern {
762 public:
ElimSpecificExtensionPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)763     ElimSpecificExtensionPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
764         : CGPeepPattern(cgFunc, currBB, currInsn, info)
765     {
766     }
767     ~ElimSpecificExtensionPattern() override = default;
768     void Run(BB &bb, Insn &insn) override;
769     bool CheckCondition(Insn &insn) override;
GetPatternName()770     std::string GetPatternName() override
771     {
772         return "ElimSpecificExtensionPattern";
773     }
774 
775 protected:
776     enum SpecificExtType : uint8 { EXTUNDEF = 0, SXTB, SXTH, SXTW, UXTB, UXTH, UXTW, AND, EXTTYPESIZE };
777     enum OptSceneType : uint8 { kSceneUndef = 0, kSceneMov, kSceneLoad, kSceneSameExt };
778     static constexpr uint8 kPrevLoadPatternNum = 6;
779     static constexpr uint8 kPrevLoadMappingNum = 2;
780     static constexpr uint8 kValueTypeNum = 2;
781     static constexpr uint64 kInvalidValue = 0;
782     static constexpr uint8 kSameExtPatternNum = 4;
783     static constexpr uint8 kSameExtMappingNum = 2;
784     uint64 extValueRangeTable[EXTTYPESIZE][kValueTypeNum] = {
785         /* {minValue, maxValue} */
786         {kInvalidValue, kInvalidValue},      /* UNDEF */
787         {0xFFFFFFFFFFFFFF80, 0x7F},          /* SXTB */
788         {0xFFFFFFFFFFFF8000, 0x7FFF},        /* SXTH */
789         {0xFFFFFFFF80000000, kInvalidValue}, /* SXTW */
790         {0xFFFFFFFFFFFFFF00, kInvalidValue}, /* UXTB */
791         {0xFFFFFFFFFFFF0000, kInvalidValue}, /* UXTH */
792         {kInvalidValue, kInvalidValue},      /* UXTW */
793         {kInvalidValue, kInvalidValue},      /* AND */
794     };
795     MOperator loadMappingTable[EXTTYPESIZE][kPrevLoadPatternNum][kPrevLoadMappingNum] = {
796         /* {prevOrigMop, prevNewMop} */
797         {{MOP_undef, MOP_undef},
798          {MOP_undef, MOP_undef},
799          {MOP_undef, MOP_undef},
800          {MOP_undef, MOP_undef},
801          {MOP_undef, MOP_undef},
802          {MOP_undef, MOP_undef}}, /* UNDEF */
803         {{MOP_wldrb, MOP_wldrsb},
804          {MOP_wldrsb, MOP_wldrsb},
805          {MOP_wldr, MOP_wldrsb},
806          {MOP_undef, MOP_undef},
807          {MOP_undef, MOP_undef},
808          {MOP_undef, MOP_undef}}, /* SXTB */
809         {{MOP_wldrh, MOP_wldrsh},
810          {MOP_wldrb, MOP_wldrb},
811          {MOP_wldrsb, MOP_wldrsb},
812          {MOP_wldrsh, MOP_wldrsh},
813          {MOP_undef, MOP_undef},
814          {MOP_undef, MOP_undef}}, /* SXTH */
815         {{MOP_wldrh, MOP_wldrh},
816          {MOP_wldrsh, MOP_wldrsh},
817          {MOP_wldrb, MOP_wldrb},
818          {MOP_wldrsb, MOP_wldrsb},
819          {MOP_wldr, MOP_xldrsw},
820          {MOP_xldrsw, MOP_xldrsw}}, /* SXTW */
821         {{MOP_wldrb, MOP_wldrb},
822          {MOP_wldrsb, MOP_wldrb},
823          {MOP_undef, MOP_undef},
824          {MOP_undef, MOP_undef},
825          {MOP_undef, MOP_undef},
826          {MOP_undef, MOP_undef}}, /* UXTB */
827         {{MOP_wldrh, MOP_wldrh},
828          {MOP_wldrb, MOP_wldrb},
829          {MOP_wldr, MOP_wldrh},
830          {MOP_wldrsh, MOP_wldrh},
831          {MOP_undef, MOP_undef},
832          {MOP_undef, MOP_undef}}, /* UXTH */
833         {{MOP_wldr, MOP_wldr},
834          {MOP_wldrh, MOP_wldrh},
835          {MOP_wldrb, MOP_wldrb},
836          {MOP_undef, MOP_undef},
837          {MOP_undef, MOP_undef},
838          {MOP_undef, MOP_undef}}, /* UXTW */
839         {{MOP_wldrb, MOP_wldrb},
840          {MOP_wldrsh, MOP_wldrb},
841          {MOP_wldrh, MOP_wldrb},
842          {MOP_xldrsw, MOP_wldrb},
843          {MOP_wldr, MOP_wldrb},
844          {MOP_undef, MOP_undef},
845          }};
846     MOperator sameExtMappingTable[EXTTYPESIZE][kSameExtPatternNum][kSameExtMappingNum] = {
847         /* {prevMop, currMop} */
848         {{MOP_undef, MOP_undef}, {MOP_undef, MOP_undef}, {MOP_undef, MOP_undef}, {MOP_undef, MOP_undef}}, /* UNDEF */
849         {{MOP_xsxtb32, MOP_xsxtb32},
850          {MOP_xsxtb64, MOP_xsxtb64},
851          {MOP_undef, MOP_undef},
852          {MOP_undef, MOP_undef}}, /* SXTB */
853         {{MOP_xsxtb32, MOP_xsxth32},
854          {MOP_xsxtb64, MOP_xsxth64},
855          {MOP_xsxth32, MOP_xsxth32},
856          {MOP_xsxth64, MOP_xsxth64}}, /* SXTH */
857         {{MOP_xsxtb64, MOP_xsxtw64},
858          {MOP_xsxth64, MOP_xsxtw64},
859          {MOP_xsxtw64, MOP_xsxtw64},
860          {MOP_undef, MOP_undef}},                                                                             /* SXTW */
861         {{MOP_xuxtb32, MOP_xuxtb32}, {MOP_undef, MOP_undef}, {MOP_undef, MOP_undef}, {MOP_undef, MOP_undef}}, /* UXTB */
862         {{MOP_xuxtb32, MOP_xuxth32},
863          {MOP_xuxth32, MOP_xuxth32},
864          {MOP_undef, MOP_undef},
865          {MOP_undef, MOP_undef}},                                                                             /* UXTH */
866         {{MOP_xuxtw64, MOP_xuxtw64}, {MOP_undef, MOP_undef}, {MOP_undef, MOP_undef}, {MOP_undef, MOP_undef}}, /* UXTW */
867         {{MOP_undef, MOP_undef}, {MOP_undef, MOP_undef}, {MOP_undef, MOP_undef}, {MOP_undef, MOP_undef}},     /* AND */
868     };
869 
870 private:
871     void SetSpecificExtType(const Insn &currInsn);
872     void SetOptSceneType();
873     bool IsValidLoadExtPattern(MOperator oldMop, MOperator newMop) const;
874     MOperator SelectNewLoadMopByBitSize(MOperator lowBitMop) const;
875     void ElimExtensionAfterLoad(Insn &insn);
876     void ElimExtensionAfterMov(Insn &insn);
877     void ElimExtensionAfterSameExt(Insn &insn);
878     void ReplaceExtWithMov(Insn &currInsn);
879     Insn *prevInsn = nullptr;
880     SpecificExtType extTypeIdx = EXTUNDEF;
881     OptSceneType sceneType = kSceneUndef;
882     bool is64Bits = false;
883 };
884 
885 /*
886  * We optimize the following pattern in this function:
887  * if w0's valid bits is one
888  * uxtb w0, w0
889  * eor w0, w0, #1
890  * cbz w0, .label
891  * =>
892  * tbnz w0, .label
893  * if there exists uxtb w0, w0 and w0's valid bits is
894  * less than 8, eliminate it.
895  */
896 class OneHoleBranchPattern : public CGPeepPattern {
897 public:
OneHoleBranchPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)898     explicit OneHoleBranchPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
899         : CGPeepPattern(cgFunc, currBB, currInsn, info)
900     {
901     }
902     ~OneHoleBranchPattern() override = default;
903     void Run(BB &bb, Insn &insn) override;
904     bool CheckCondition(Insn &insn) override;
GetPatternName()905     std::string GetPatternName() override
906     {
907         return "OneHoleBranchPattern";
908     }
909 
910 private:
911     void FindNewMop(const BB &bb, const Insn &insn);
912     bool CheckPrePrevInsn();
913     Insn *prevInsn = nullptr;
914     Insn *prePrevInsn = nullptr;
915     MOperator newOp = MOP_undef;
916 };
917 
918 /*
919  * Combine logical shift and orr to [extr wd, wn, wm, #lsb  /  extr xd, xn, xm, #lsb]
920  * Example 1)
921  *  lsr w5, w6, #16
922  *  lsl w4, w7, #16
923  *  orr w5, w5, w4                  --->        (currInsn)
924  *  ===> extr w5, w6, w7, #16
925  *
926  * Example 2)
927  *  lsr w5, w6, #16
928  *  orr w5, w5, w4, LSL #16         --->        (currInsn)
929  *  ===> extr w5, w6, w4, #16
930  *
931  * Example 3)
932  *  lsl w4, w7, #16
933  *  orr w5, w4, w5, LSR #16         --->        (currInsn)
934  *  ===> extr w5, w5, w7, #16
935  *
936  * Conditions:
937  *  1. (def[wn] is lsl) & (def[wm] is lsr)
938  *  2. lsl_imm + lsr_imm == curr type size (32 or 64)
939  *  3. is64bits ? (extr_imm in range [0, 63]) : (extr_imm in range [0, 31])
940  *  4. extr_imm = lsr_imm
941  */
942 class LogicShiftAndOrrToExtrPattern : public CGPeepPattern {
943 public:
LogicShiftAndOrrToExtrPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)944     LogicShiftAndOrrToExtrPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
945         : CGPeepPattern(cgFunc, currBB, currInsn, info)
946     {
947     }
948     ~LogicShiftAndOrrToExtrPattern() override = default;
949     void Run(BB &bb, Insn &insn) override;
950     bool CheckCondition(Insn &insn) override;
GetPatternName()951     std::string GetPatternName() override
952     {
953         return "LogicShiftAndOrrToExtrPattern";
954     }
955 
956 private:
957     Insn *prevLsrInsn = nullptr;
958     Insn *prevLslInsn = nullptr;
959     int64 shiftValue = 0;
960     bool is64Bits = false;
961 };
962 
963 /*
964  * Simplify Mul and Basic Arithmetic. There are three scenes:
965  * 1. currInsn is add:
966  * Example 1)
967  *  mul   x1, x1, x2           or     mul   x0, x1, x2
968  *  add   x0, x0, x1                  add   x0, x0, x1
969  *  ===> madd x0, x1, x2, x0          ===> madd x0, x1, x2, x1
970  *
971  * Example 2)
972  *  fmul  d1, d1, d2           or     fmul  d0, d1, d2
973  *  fadd  d0, d0, d1                  fadd  d0, d0, d1
974  *  ===> fmadd d0, d1, d2, d0         ===> fmadd d0, d1, d2, d1
975  *
976  * cases: addInsn second opnd || addInsn third opnd
977  *
978  *
979  * 2. currInsn is sub:
980  * Example 1)                         Example 2)
981  *  mul   x1, x1, x2                   fmul  d1, d1, d2
982  *  sub   x0, x0, x1                   fsub  d0, d0, d1
983  *  ===> msub x0, x1, x2, x0           ===> fmsub d0, d1, d2, d0
984  *
985  * cases: subInsn third opnd
986  *
987  * 3. currInsn is neg:
988  * Example 1)                         Example 2)
989  *  mul   x1, x1, x2                   fmul     d1, d1, d2
990  *  neg   x0, x1                       fneg     d0, d1
991  *  ===> mneg x0, x1, x2               ===> fnmul d0, d1, d2
992  *
993  * cases: negInsn second opnd
994  */
995 class SimplifyMulArithmeticPattern : public CGPeepPattern {
996 public:
SimplifyMulArithmeticPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)997     SimplifyMulArithmeticPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
998         : CGPeepPattern(cgFunc, currBB, currInsn, info)
999     {
1000     }
1001     ~SimplifyMulArithmeticPattern() override = default;
1002     void Run(BB &bb, Insn &insn) override;
1003     bool CheckCondition(Insn &insn) override;
GetPatternName()1004     std::string GetPatternName() override
1005     {
1006         return "SimplifyMulArithmeticPattern";
1007     }
1008 
1009 protected:
1010     enum ArithmeticType : uint8 { kUndef = 0, kAdd, kFAdd, kSub, kFSub, kNeg, kFNeg, kArithmeticTypeSize };
1011     static constexpr uint8 kNewMopNum = 2;
1012     MOperator curMop2NewMopTable[kArithmeticTypeSize][kNewMopNum] = {
1013         /* {32bit_mop, 64bit_mop} */
1014         {MOP_undef, MOP_undef},         /* kUndef  */
1015         {MOP_wmaddrrrr, MOP_xmaddrrrr}, /* kAdd    */
1016         {MOP_smadd, MOP_dmadd},         /* kFAdd   */
1017         {MOP_wmsubrrrr, MOP_xmsubrrrr}, /* kSub    */
1018         {MOP_smsub, MOP_dmsub},         /* kFSub   */
1019         {MOP_wmnegrrr, MOP_xmnegrrr},   /* kNeg    */
1020         {MOP_snmul, MOP_dnmul}          /* kFNeg   */
1021     };
1022 
1023 private:
1024     void SetArithType(const Insn &currInsn);
1025     void DoOptimize(BB &currBB, Insn &currInsn);
1026     ArithmeticType arithType = kUndef;
1027     int32 validOpndIdx = -1;
1028     Insn *prevInsn = nullptr;
1029     bool isFloat = false;
1030 };
1031 
1032 /*
1033  * Example 1)
1034  *  lsr w0, w1, #6
1035  *  and w0, w0, #1                 --->        (currInsn)
1036  *  ===> ubfx w0, w1, #6, #1
1037  *
1038  * Conditions:
1039  * 1. and_imm value is (1 << n -1)
1040  * 2. is64bits ? (ubfx_imm_lsb in range [0, 63]) : (ubfx_imm_lsb in range [0, 31])
1041  * 3. is64bits ? ((ubfx_imm_lsb + ubfx_imm_width) in range [1, 32]) : ((ubfx_imm_lsb + ubfx_imm_width) in range [1, 64])
1042  */
1043 class LsrAndToUbfxPattern : public CGPeepPattern {
1044 public:
LsrAndToUbfxPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)1045     LsrAndToUbfxPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
1046         : CGPeepPattern(cgFunc, currBB, currInsn, info)
1047     {
1048     }
1049     ~LsrAndToUbfxPattern() override = default;
1050     void Run(BB &bb, Insn &insn) override;
1051     bool CheckCondition(Insn &insn) override;
1052     bool CheckIntersectedCondition(const Insn &insn);
GetPatternName()1053     std::string GetPatternName() override
1054     {
1055         return "LsrAndToUbfxPattern";
1056     }
1057 
1058 private:
1059     Insn *prevInsn = nullptr;
1060     bool isWXSumOutOfRange = false;
1061 };
1062 
1063 /*
1064  * lsl w1, w2, #m
1065  * and w3, w1, #[(2^n-1 << m) ~ (2^n-1)]    --->    if n > m : ubfiz w3, w2, #m, #n-m
1066  *
1067  * and w1, w2, #2^n-1    --->    ubfiz w3, w2, #m, #n
1068  * lsl w3, w1, #m
1069  * Exclude the scenarios that can be optimized by prop.
1070  */
1071 class LslAndToUbfizPattern : public CGPeepPattern {
1072 public:
LslAndToUbfizPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)1073     LslAndToUbfizPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
1074         : CGPeepPattern(cgFunc, currBB, currInsn, info)
1075     {
1076     }
~LslAndToUbfizPattern()1077     ~LslAndToUbfizPattern() override
1078     {
1079         defInsn = nullptr;
1080     }
1081     void Run(BB &bb, Insn &insn) override;
1082     bool CheckCondition(Insn &insn) override;
1083     Insn *BuildNewInsn(const Insn &andInsn, const Insn &lslInsn, const Insn &useInsn) const;
1084     bool CheckUseInsnMop(const Insn &useInsn) const;
GetPatternName()1085     std::string GetPatternName() override
1086     {
1087         return "LslAndToUbfizPattern";
1088     }
1089 
1090 private:
1091     Insn *defInsn = nullptr;
1092 };
1093 
1094 /*
1095  * Optimize the following patterns:
1096  *  orr  w21, w0, #0  ====> mov  w21, w0
1097  *  orr  w21, #0, w0  ====> mov  w21, w0
1098  */
1099 class OrrToMovPattern : public CGPeepPattern {
1100 public:
OrrToMovPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)1101     explicit OrrToMovPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
1102         : CGPeepPattern(cgFunc, currBB, currInsn, info)
1103     {
1104     }
1105     ~OrrToMovPattern() override = default;
1106     void Run(BB &bb, Insn &insn) override;
1107     bool CheckCondition(Insn &insn) override;
GetPatternName()1108     std::string GetPatternName() override
1109     {
1110         return "OrrToMovPattern";
1111     }
1112 
1113 private:
1114     MOperator newMop = MOP_undef;
1115     RegOperand *reg2 = nullptr;
1116 };
1117 
1118 /*
1119  * Optimize the following patterns:
1120  * ubfx  x201, x202, #0, #32
1121  * ====>
1122  * uxtw x201, w202
1123  */
1124 class UbfxToUxtwPattern : public CGPeepPattern {
1125 public:
UbfxToUxtwPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1126     UbfxToUxtwPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
1127     ~UbfxToUxtwPattern() override = default;
1128     void Run(BB &bb, Insn &insn) override;
1129     bool CheckCondition(Insn &insn) override;
GetPatternName()1130     std::string GetPatternName() override
1131     {
1132         return "UbfxToUxtwPattern";
1133     }
1134 };
1135 
1136 /*
1137  * Optimize the following patterns:
1138  * ubfx  w0, w0, #2, #1
1139  * cbz   w0, .L.3434__292    ====>    tbz w0, #2, .L.3434__292
1140  * -------------------------------
1141  * ubfx  w0, w0, #2, #1
1142  * cnbz   w0, .L.3434__292    ====>    tbnz w0, #2, .L.3434__292
1143  * -------------------------------
1144  * ubfx  x0, x0, #2, #1
1145  * cbz   x0, .L.3434__292    ====>    tbz x0, #2, .L.3434__292
1146  * -------------------------------
1147  * ubfx  x0, x0, #2, #1
1148  * cnbz  x0, .L.3434__292    ====>    tbnz x0, #2, .L.3434__292
1149  */
1150 class UbfxAndCbzToTbzPattern : public CGPeepPattern {
1151 public:
UbfxAndCbzToTbzPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)1152     UbfxAndCbzToTbzPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
1153         : CGPeepPattern(cgFunc, currBB, currInsn, info)
1154     {
1155     }
UbfxAndCbzToTbzPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1156     UbfxAndCbzToTbzPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~UbfxAndCbzToTbzPattern()1157     ~UbfxAndCbzToTbzPattern() override
1158     {
1159         useInsn = nullptr;
1160     }
1161     void Run(BB &bb, Insn &insn) override;
1162     bool CheckCondition(Insn &insn) override;
GetPatternName()1163     std::string GetPatternName() override
1164     {
1165         return "UbfxAndCbzToTbzPattern";
1166     }
1167 
1168 private:
1169     Insn *useInsn = nullptr;
1170     MOperator newMop = MOP_undef;
1171 };
1172 
1173 /* ubfx R1 R0 a b
1174  * ubfx R2 R1 c d => ubfx R2 R0 a + c, min(b -c, d)
1175  * ---------------------------------------------------
1176  * for example:
1177  * ubfx R1 R0 3 5
1178  * ubfx R2 R1 2 8 => ubfx R2 R0 5 (2+3), 3 (min(3, 8))
1179  */
1180 class UbfxAndMergetPattern : public CGPeepPattern {
1181 public:
UbfxAndMergetPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)1182     UbfxAndMergetPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
1183         : CGPeepPattern(cgFunc, currBB, currInsn, info)
1184     {
1185     }
UbfxAndMergetPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1186     UbfxAndMergetPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~UbfxAndMergetPattern()1187     ~UbfxAndMergetPattern() override
1188     {
1189         prevSrc = nullptr;
1190     }
1191     void Run(BB &bb, Insn &insn) override;
1192     bool CheckCondition(Insn &insn) override;
GetPatternName()1193     std::string GetPatternName() override
1194     {
1195         return "UbfxAndMergetPattern";
1196     }
1197 
1198 private:
1199     bool IsAllOneToMSB(int64 val) const;
1200     int32 GetMSB(int64 val) const;
1201     int64 prevLsb = -1;
1202     int64 prevWidth = -1;
1203     int64 currLsb = -1;
1204     int64 currWidth = -1;
1205     MOperator newMop = MOP_undef;
1206     RegOperand *prevSrc = nullptr;
1207 };
1208 
1209 /* Find up identical two mem insns in local bb to eliminate redundancy, as following:
1210  * 1. str[BOI] + str[BOI] :
1211  *    Remove first str insn when the [MEM] operand is exactly same, and the [srcOpnd] of two str don't need to be same,
1212  *    and there is no redefinition of [srcOpnd] between two strs.
1213  * 2. str[BOI] + ldr[BOI] :
1214  *    Remove ldr insn when the [MEM] operand is exactly same and the [srcOpnd] of str
1215  *    is same as the [destOpnd] of ldr, and there is no redefinition of [srcOpnd] and [destOpnd] between two insns.
1216  * 3. ldr[BOI] + ldr[BOI] :
1217  *    Remove second ldr insn
1218  */
1219 class RemoveIdenticalLoadAndStorePattern : public CGPeepPattern {
1220 public:
RemoveIdenticalLoadAndStorePattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1221     RemoveIdenticalLoadAndStorePattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn)
1222         : CGPeepPattern(cgFunc, currBB, currInsn)
1223     {
1224     }
~RemoveIdenticalLoadAndStorePattern()1225     ~RemoveIdenticalLoadAndStorePattern() override
1226     {
1227         prevIdenticalInsn = nullptr;
1228     }
1229     void Run(BB &bb, Insn &insn) override;
1230     bool CheckCondition(Insn &insn) override;
GetPatternName()1231     std::string GetPatternName() override
1232     {
1233         return "RemoveIdenticalLoadAndStorePattern";
1234     }
1235 
1236 private:
1237     bool IsIdenticalMemOpcode(const Insn &curInsn, const Insn &checkedInsn) const;
1238     Insn *FindPrevIdenticalMemInsn(const Insn &curInsn) const;
1239     bool HasImplictSizeUse(const Insn &curInsn) const;
1240     bool HasMemReferenceBetweenTwoInsns(const Insn &curInsn) const;
1241     Insn *prevIdenticalInsn = nullptr;
1242 };
1243 
1244 /* ======== CGPeepPattern End ======== */
1245 /*
1246  * Looking for identical mem insn to eliminate.
1247  * If two back-to-back is:
1248  * 1. str + str
1249  * 2. str + ldr
1250  * And the [MEM] is pattern of [base + offset]
1251  * 1. The [MEM] operand is exactly same then first
1252  *    str can be eliminate.
1253  * 2. The [MEM] operand is exactly same and src opnd
1254  *    of str is same as the dest opnd of ldr then
1255  *    ldr can be eliminate
1256  */
1257 class RemoveIdenticalLoadAndStoreAArch64 : public PeepPattern {
1258 public:
RemoveIdenticalLoadAndStoreAArch64(CGFunc & cgFunc)1259     explicit RemoveIdenticalLoadAndStoreAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1260     ~RemoveIdenticalLoadAndStoreAArch64() override = default;
1261     void Run(BB &bb, Insn &insn) override;
1262 
1263 private:
1264     bool IsMemOperandsIdentical(const Insn &insn1, const Insn &insn2) const;
1265 };
1266 
1267 /* Remove redundant mov which src and dest opnd is exactly same */
1268 class RemoveMovingtoSameRegPattern : public CGPeepPattern {
1269 public:
RemoveMovingtoSameRegPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1270     RemoveMovingtoSameRegPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn)
1271     {
1272     }
1273     ~RemoveMovingtoSameRegPattern() override = default;
1274     void Run(BB &bb, Insn &insn) override;
1275     bool CheckCondition(Insn &insn) override;
GetPatternName()1276     std::string GetPatternName() override
1277     {
1278         return "RemoveMovingtoSameRegPattern";
1279     }
1280 };
1281 
1282 /* Remove redundant mov which src and dest opnd is exactly same */
1283 class RemoveMovingtoSameRegAArch64 : public PeepPattern {
1284 public:
RemoveMovingtoSameRegAArch64(CGFunc & cgFunc)1285     explicit RemoveMovingtoSameRegAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1286     ~RemoveMovingtoSameRegAArch64() override = default;
1287     void Run(BB &bb, Insn &insn) override;
1288 };
1289 
1290 /*
1291  *  mov dest1, imm
1292  *  mul dest2, reg1, dest1
1293  *  ===> if imm is 2^n
1294  *  mov        dest1, imm
1295  *  lsl dest2, reg1, n
1296  */
1297 class MulImmToShiftPattern : public CGPeepPattern {
1298 public:
MulImmToShiftPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)1299     MulImmToShiftPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
1300         : CGPeepPattern(cgFunc, currBB, currInsn, info)
1301     {
1302     }
~MulImmToShiftPattern()1303     ~MulImmToShiftPattern() override
1304     {
1305         movInsn = nullptr;
1306     }
GetPatternName()1307     std::string GetPatternName() override
1308     {
1309         return "MulImmToShiftPattern";
1310     }
1311     bool CheckCondition(Insn &insn) override;
1312     void Run(BB &bb, Insn &insn) override;
1313 
1314 private:
1315     Insn *movInsn = nullptr;
1316     uint32 shiftVal = 0;
1317     MOperator newMop = MOP_undef;
1318 };
1319 
1320 /*
1321  * Combining {2 str into 1 stp || 2 ldr into 1 ldp || 2 strb into 1 strh || 2 strh into 1 str},
1322  * when they are back to back and the [MEM] they access is conjoined.
1323  */
1324 class CombineContiLoadAndStorePattern : public CGPeepPattern {
1325 public:
CombineContiLoadAndStorePattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1326     CombineContiLoadAndStorePattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn)
1327         : CGPeepPattern(cgFunc, currBB, currInsn)
1328     {
1329         doAggressiveCombine = cgFunc.GetMirModule().IsCModule();
1330     }
1331     ~CombineContiLoadAndStorePattern() override = default;
1332     void Run(BB &bb, Insn &insn) override;
1333     bool CheckCondition(Insn &insn) override;
GetPatternName()1334     std::string GetPatternName() override
1335     {
1336         return "CombineContiLoadAndStorePattern";
1337     }
1338 
1339 private:
1340     std::vector<Insn *> FindPrevStrLdr(Insn &insn, regno_t destRegNO, regno_t memBaseRegNO, int64 baseOfst) const;
1341     /*
1342      * avoid the following situation:
1343      * str x2, [x19, #8]
1344      * mov x0, x19
1345      * bl foo (change memory)
1346      * str x21, [x19, #16]
1347      */
1348     bool IsRegNotSameMemUseInInsn(const Insn &checkInsn, const Insn &curInsn, regno_t curBaseRegNO, bool isCurStore,
1349                                   int64 curBaseOfst, int64 curMemRange) const;
1350     bool IsValidNormalLoadOrStorePattern(const Insn &insn, const Insn &prevInsn, const MemOperand &memOpnd,
1351                                          int64 curOfstVal, int64 prevOfstVal);
1352     bool IsValidStackArgLoadOrStorePattern(const Insn &curInsn, const Insn &prevInsn, const MemOperand &curMemOpnd,
1353                                            const MemOperand &prevMemOpnd, int64 curOfstVal, int64 prevOfstVal) const;
1354     Insn *GenerateMemPairInsn(MOperator newMop, RegOperand &curDestOpnd, RegOperand &prevDestOpnd,
1355                               MemOperand &combineMemOpnd, bool isCurDestFirst);
1356     bool FindUseX16AfterInsn(const Insn &curInsn) const;
1357     void RemoveInsnAndKeepComment(BB &bb, Insn &insn, Insn &prevInsn) const;
1358 
1359     bool doAggressiveCombine = false;
1360     bool isPairAfterCombine = true;
1361 };
1362 
1363 /*
1364  * add xt, xn, #imm               add  xt, xn, xm
1365  * ldr xd, [xt]                   ldr xd, [xt]
1366  * =====================>
1367  * ldr xd, [xn, #imm]             ldr xd, [xn, xm]
1368  *
1369  * load/store can do extend shift as well
1370  */
1371 class EnhanceStrLdrAArch64 : public PeepPattern {
1372 public:
EnhanceStrLdrAArch64(CGFunc & cgFunc)1373     explicit EnhanceStrLdrAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1374     ~EnhanceStrLdrAArch64() override = default;
1375     void Run(BB &bb, Insn &insn) override;
1376 
1377 private:
1378     ImmOperand *GetInsnAddOrSubNewOffset(Insn &insn, ImmOperand &offset);
1379     void OptimizeAddrBOI(Insn &insn, MemOperand &memOpnd, Insn &prevInsn);
1380     void OptimizeAddrBOrX(Insn &insn, MemOperand &memOpnd, Insn &prevInsn);
1381     void OptimizeAddrBOrXShiftExtend(Insn &insn, MemOperand &memOpnd, Insn &shiftExtendInsn);
1382     void OptimizeWithAddrrrs(Insn &insn, MemOperand &memOpnd, Insn &addInsn);
1383     bool CheckOperandIsDeadFromInsn(const RegOperand &regOpnd, Insn &insn);
1384 };
1385 
1386 /* Eliminate the sxt[b|h|w] w0, w0;, when w0 is satisify following:
1387  * i)  mov w0, #imm (#imm is not out of range)
1388  * ii) ldrs[b|h] w0, [MEM]
1389  */
1390 class EliminateSpecifcSXTAArch64 : public PeepPattern {
1391 public:
EliminateSpecifcSXTAArch64(CGFunc & cgFunc)1392     explicit EliminateSpecifcSXTAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1393     ~EliminateSpecifcSXTAArch64() override = default;
1394     void Run(BB &bb, Insn &insn) override;
1395 };
1396 
1397 class EliminateSpecifcSXTPattern : public CGPeepPattern {
1398 public:
EliminateSpecifcSXTPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1399     EliminateSpecifcSXTPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~EliminateSpecifcSXTPattern()1400     ~EliminateSpecifcSXTPattern() override
1401     {
1402         prevInsn = nullptr;
1403     }
1404     void Run(BB &bb, Insn &insn) override;
1405     bool CheckCondition(Insn &insn) override;
GetPatternName()1406     std::string GetPatternName() override
1407     {
1408         return "EliminateSpecifcSXTPattern";
1409     }
1410 
1411 private:
1412     Insn *prevInsn = nullptr;
1413 };
1414 
1415 /* Eliminate the uxt[b|h|w] w0, w0;when w0 is satisify following:
1416  * i)  mov w0, #imm (#imm is not out of range)
1417  * ii) mov w0, R0(Is return value of call and return size is not of range)
1418  * iii)w0 is defined and used by special load insn and uxt[] pattern
1419  */
1420 class EliminateSpecifcUXTAArch64 : public PeepPattern {
1421 public:
EliminateSpecifcUXTAArch64(CGFunc & cgFunc)1422     explicit EliminateSpecifcUXTAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1423     ~EliminateSpecifcUXTAArch64() override = default;
1424     void Run(BB &bb, Insn &insn) override;
1425 };
1426 
1427 class EliminateSpecifcUXTPattern : public CGPeepPattern {
1428 public:
EliminateSpecifcUXTPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1429     EliminateSpecifcUXTPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~EliminateSpecifcUXTPattern()1430     ~EliminateSpecifcUXTPattern() override
1431     {
1432         prevInsn = nullptr;
1433     }
1434     void Run(BB &bb, Insn &insn) override;
1435     bool CheckCondition(Insn &insn) override;
GetPatternName()1436     std::string GetPatternName() override
1437     {
1438         return "EliminateSpecifcUXTPattern";
1439     }
1440 
1441 private:
1442     Insn *prevInsn = nullptr;
1443 };
1444 
1445 /* fmov ireg1 <- freg1   previous insn
1446  * fmov ireg2 <- freg1   current insn
1447  * use  ireg2            may or may not be present
1448  * =>
1449  * fmov ireg1 <- freg1   previous insn
1450  * mov  ireg2 <- ireg1   current insn
1451  * use  ireg1            may or may not be present
1452  */
1453 class FmovRegPattern : public CGPeepPattern {
1454 public:
FmovRegPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1455     FmovRegPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~FmovRegPattern()1456     ~FmovRegPattern() override
1457     {
1458         prevInsn = nullptr;
1459         nextInsn = nullptr;
1460     }
1461     void Run(BB &bb, Insn &insn) override;
1462     bool CheckCondition(Insn &insn) override;
GetPatternName()1463     std::string GetPatternName() override
1464     {
1465         return "FmovRegPattern";
1466     }
1467 
1468 private:
1469     Insn *prevInsn = nullptr;
1470     Insn *nextInsn = nullptr;
1471 };
1472 
1473 /* sbfx ireg1, ireg2, 0, 32
1474  * use  ireg1.32
1475  * =>
1476  * sbfx ireg1, ireg2, 0, 32
1477  * use  ireg2.32
1478  */
1479 class SbfxOptPattern : public CGPeepPattern {
1480 public:
SbfxOptPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1481     SbfxOptPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~SbfxOptPattern()1482     ~SbfxOptPattern() override
1483     {
1484         nextInsn = nullptr;
1485     }
1486     void Run(BB &bb, Insn &insn) override;
1487     bool CheckCondition(Insn &insn) override;
GetPatternName()1488     std::string GetPatternName() override
1489     {
1490         return "SbfxOptPattern";
1491     }
1492 
1493 private:
1494     Insn *nextInsn = nullptr;
1495     bool toRemove = false;
1496     std::vector<uint32> cands;
1497 };
1498 
1499 /* cbnz x0, labelA
1500  * mov x0, 0
1501  * b  return-bb
1502  * labelA:
1503  * =>
1504  * cbz x0, return-bb
1505  * labelA:
1506  */
1507 class CbnzToCbzPattern : public CGPeepPattern {
1508 public:
CbnzToCbzPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1509     CbnzToCbzPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~CbnzToCbzPattern()1510     ~CbnzToCbzPattern() override
1511     {
1512         nextBB = nullptr;
1513         movInsn = nullptr;
1514         brInsn = nullptr;
1515     }
1516     void Run(BB &bb, Insn &insn) override;
1517     bool CheckCondition(Insn &insn) override;
GetPatternName()1518     std::string GetPatternName() override
1519     {
1520         return "CbnzToCbzPattern";
1521     }
1522 
1523 private:
1524     BB *nextBB = nullptr;
1525     Insn *movInsn = nullptr;
1526     Insn *brInsn = nullptr;
1527 };
1528 
1529 /* i.   cset    w0, EQ
1530  *      cbnz    w0, .label    ===> beq .label
1531  *
1532  * ii.  cset    w0, EQ
1533  *      cbz    w0, .label     ===> bne .label
1534  *
1535  * iii. cset    w0, NE
1536  *      cbnz    w0, .label    ===> bne .label
1537  *
1538  * iiii.cset    w0, NE
1539  *      cbz    w0, .label     ===> beq .label
1540  * ... ...
1541  */
1542 class CsetCbzToBeqOptAArch64 : public PeepPattern {
1543 public:
CsetCbzToBeqOptAArch64(CGFunc & cgFunc)1544     explicit CsetCbzToBeqOptAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1545     ~CsetCbzToBeqOptAArch64() override = default;
1546     void Run(BB &bb, Insn &insn) override;
1547     MOperator SelectMOperator(ConditionCode condCode, bool inverse) const;
1548 };
1549 
1550 /* When exist load after load or load after store, and [MEM] is
1551  * totally same. Then optimize them.
1552  */
1553 class ContiLDRorSTRToSameMEMPattern : public CGPeepPattern {
1554 public:
ContiLDRorSTRToSameMEMPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1555     ContiLDRorSTRToSameMEMPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn)
1556     {
1557     }
~ContiLDRorSTRToSameMEMPattern()1558     ~ContiLDRorSTRToSameMEMPattern() override
1559     {
1560         prevInsn = nullptr;
1561     }
1562     void Run(BB &bb, Insn &insn) override;
1563     bool HasImplicitSizeUse(const Insn &insn) const;
1564     bool CheckCondition(Insn &insn) override;
GetPatternName()1565     std::string GetPatternName() override
1566     {
1567         return "ContiLDRorSTRToSameMEMPattern";
1568     }
1569 
1570 private:
1571     Insn *prevInsn = nullptr;
1572     bool loadAfterStore = false;
1573     bool loadAfterLoad = false;
1574 };
1575 
1576 /*
1577  *  Remove following patterns:
1578  *  mov     x1, x0
1579  *  bl      MCC_IncDecRef_NaiveRCFast
1580  */
1581 class RemoveIncDecRefPattern : public CGPeepPattern {
1582 public:
RemoveIncDecRefPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1583     RemoveIncDecRefPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~RemoveIncDecRefPattern()1584     ~RemoveIncDecRefPattern() override
1585     {
1586         prevInsn = nullptr;
1587     }
1588     void Run(BB &bb, Insn &insn) override;
1589     bool CheckCondition(Insn &insn) override;
GetPatternName()1590     std::string GetPatternName() override
1591     {
1592         return "RemoveIncDecRefPattern";
1593     }
1594 
1595 private:
1596     Insn *prevInsn = nullptr;
1597 };
1598 
1599 /*
1600  * When GCONLY is enabled, the read barriers can be inlined.
1601  * we optimize it with the following pattern:
1602  * #if USE_32BIT_REF
1603  *   bl MCC_LoadRefField             ->  ldr  w0, [x1]
1604  *   bl MCC_LoadVolatileField        ->  ldar w0, [x1]
1605  *   bl MCC_LoadRefStatic            ->  ldr  w0, [x0]
1606  *   bl MCC_LoadVolatileStaticField  ->  ldar w0, [x0]
1607  *   bl MCC_Dummy                    ->  omitted
1608  * #else
1609  *   bl MCC_LoadRefField             ->  ldr  x0, [x1]
1610  *   bl MCC_LoadVolatileField        ->  ldar x0, [x1]
1611  *   bl MCC_LoadRefStatic            ->  ldr  x0, [x0]
1612  *   bl MCC_LoadVolatileStaticField  ->  ldar x0, [x0]
1613  *   bl MCC_Dummy                    ->  omitted
1614  * #endif
1615  *
1616  * if we encounter a tail call optimized read barrier call,
1617  * such as:
1618  *   b MCC_LoadRefField
1619  * a return instruction will be added just after the load:
1620  *   ldr w0, [x1]
1621  *   ret
1622  */
1623 class InlineReadBarriersPattern : public CGPeepPattern {
1624 public:
InlineReadBarriersPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1625     InlineReadBarriersPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
1626     ~InlineReadBarriersPattern() override = default;
1627     void Run(BB &bb, Insn &insn) override;
1628     bool CheckCondition(Insn &insn) override;
GetPatternName()1629     std::string GetPatternName() override
1630     {
1631         return "InlineReadBarriersPattern";
1632     }
1633 };
1634 
1635 /*
1636  *    mov     w1, #34464
1637  *    movk    w1, #1,  LSL #16
1638  *    sdiv    w2, w0, w1
1639  *  ========>
1640  *    mov     w1, #34464         // may deleted if w1 not live anymore.
1641  *    movk    w1, #1,  LSL #16   // may deleted if w1 not live anymore.
1642  *    mov     w16, #0x588f
1643  *    movk    w16, #0x4f8b, LSL #16
1644  *    smull   x16, w0, w16
1645  *    asr     x16, x16, #32
1646  *    add     x16, x16, w0, SXTW
1647  *    asr     x16, x16, #17
1648  *    add     x2, x16, x0, LSR #31
1649  */
1650 class ReplaceDivToMultiPattern : public CGPeepPattern {
1651 public:
ReplaceDivToMultiPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1652     ReplaceDivToMultiPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~ReplaceDivToMultiPattern()1653     ~ReplaceDivToMultiPattern() override
1654     {
1655         prevInsn = nullptr;
1656         prePrevInsn = nullptr;
1657     }
1658     void Run(BB &bb, Insn &insn) override;
1659     bool CheckCondition(Insn &insn) override;
GetPatternName()1660     std::string GetPatternName() override
1661     {
1662         return "ReplaceDivToMultiPattern";
1663     }
1664 
1665 private:
1666     Insn *prevInsn = nullptr;
1667     Insn *prePrevInsn = nullptr;
1668 };
1669 
1670 /*
1671  * Optimize the following patterns:
1672  *  and  w0, w0, #imm  ====> tst  w0, #imm
1673  *  cmp  w0, #0              beq/bne  .label
1674  *  beq/bne  .label
1675  *
1676  *  and  x0, x0, #imm  ====> tst  x0, #imm
1677  *  cmp  x0, #0              beq/bne  .label
1678  *  beq/bne  .label
1679  */
1680 class AndCmpBranchesToTstAArch64 : public PeepPattern {
1681 public:
AndCmpBranchesToTstAArch64(CGFunc & cgFunc)1682     explicit AndCmpBranchesToTstAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1683     ~AndCmpBranchesToTstAArch64() override = default;
1684     void Run(BB &bb, Insn &insn) override;
1685 };
1686 
1687 /*
1688  * Optimize the following patterns:
1689  *  and  w0, w0, #imm  ====> tst  w0, #imm
1690  *  cbz/cbnz  .label         beq/bne  .label
1691  */
1692 class AndCbzBranchesToTstAArch64 : public PeepPattern {
1693 public:
AndCbzBranchesToTstAArch64(CGFunc & cgFunc)1694     explicit AndCbzBranchesToTstAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1695     ~AndCbzBranchesToTstAArch64() override = default;
1696     void Run(BB &bb, Insn &insn) override;
1697 };
1698 
1699 class AndCbzBranchesToTstPattern : public CGPeepPattern {
1700 public:
AndCbzBranchesToTstPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1701     AndCbzBranchesToTstPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
1702     ~AndCbzBranchesToTstPattern() override = default;
1703     void Run(BB &bb, Insn &insn) override;
1704     bool CheckCondition(Insn &insn) override;
GetPatternName()1705     std::string GetPatternName() override
1706     {
1707         return "AndCbzBranchesToTstPattern";
1708     }
1709 };
1710 
1711 /*
1712  * Optimize the following patterns:
1713  *  and  w0, w0, #1  ====> and  w0, w0, #1
1714  *  cmp  w0, #1
1715  *  cset w0, EQ
1716  *
1717  *  and  w0, w0, #1  ====> and  w0, w0, #1
1718  *  cmp  w0, #0
1719  *  cset w0, NE
1720  *  ---------------------------------------------------
1721  *  and  w0, w0, #imm  ====> ubfx  w0, w0, pos, size
1722  *  cmp  w0, #imm
1723  *  cset w0, EQ
1724  *
1725  *  and  w0, w0, #imm  ====> ubfx  w0, w0, pos, size
1726  *  cmp  w0, #0
1727  *  cset w0, NE
1728  *  conditions:
1729  *  imm is pos power of 2
1730  *
1731  *  ---------------------------------------------------
1732  *  and  w0, w0, #1  ====> and  wn, w0, #1
1733  *  cmp  w0, #1
1734  *  cset wn, EQ        # wn != w0 && w0 is not live after cset
1735  *
1736  *  and  w0, w0, #1  ====> and  wn, w0, #1
1737  *  cmp  w0, #0
1738  *  cset wn, NE        # wn != w0 && w0 is not live after cset
1739  *  ---------------------------------------------------
1740  *  and  w0, w0, #imm  ====> ubfx  wn, w0, pos, size
1741  *  cmp  w0, #imm
1742  *  cset wn, EQ        # wn != w0 && w0 is not live after cset
1743  *
1744  *  and  w0, w0, #imm  ====> ubfx  wn, w0, pos, size
1745  *  cmp  w0, #0
1746  *  cset wn, NE        # wn != w0 && w0 is not live after cset
1747  *  conditions:
1748  *  imm is pos power of 2 and w0 is not live after cset
1749  */
1750 class AndCmpBranchesToCsetAArch64 : public PeepPattern {
1751 public:
AndCmpBranchesToCsetAArch64(CGFunc & cgFunc)1752     explicit AndCmpBranchesToCsetAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1753     ~AndCmpBranchesToCsetAArch64() override = default;
1754     void Run(BB &bb, Insn &insn) override;
1755 
1756 private:
1757     Insn *FindPreviousCmp(Insn &insn) const;
1758 };
1759 
1760 class AndCmpBranchesToCsetPattern : public CGPeepPattern {
1761 public:
AndCmpBranchesToCsetPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)1762     AndCmpBranchesToCsetPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
1763         : CGPeepPattern(cgFunc, currBB, currInsn, info)
1764     {
1765     }
~AndCmpBranchesToCsetPattern()1766     ~AndCmpBranchesToCsetPattern() override
1767     {
1768         prevCmpInsn = nullptr;
1769     }
1770     void Run(BB &bb, Insn &insn) override;
1771     bool CheckCondition(Insn &insn) override;
GetPatternName()1772     std::string GetPatternName() override
1773     {
1774         return "AndCmpBranchesToCsetPattern";
1775     }
1776 
1777 private:
1778     Insn *prevAndInsn = nullptr;
1779     Insn *prevCmpInsn = nullptr;
1780 };
1781 
1782 /*
1783  * We optimize the following pattern in this function:
1784  * cmp w[0-9]*, wzr  ====> tbz w[0-9]*, #31, .label
1785  * bge .label
1786  *
1787  * cmp wzr, w[0-9]*  ====> tbz w[0-9]*, #31, .label
1788  * ble .label
1789  *
1790  * cmp w[0-9]*,wzr   ====> tbnz w[0-9]*, #31, .label
1791  * blt .label
1792  *
1793  * cmp wzr, w[0-9]*  ====> tbnz w[0-9]*, #31, .label
1794  * bgt .label
1795  *
1796  * cmp w[0-9]*, #0   ====> tbz w[0-9]*, #31, .label
1797  * bge .label
1798  *
1799  * cmp w[0-9]*, #0   ====> tbnz w[0-9]*, #31, .label
1800  * blt .label
1801  */
1802 class ZeroCmpBranchesAArch64 : public PeepPattern {
1803 public:
ZeroCmpBranchesAArch64(CGFunc & cgFunc)1804     explicit ZeroCmpBranchesAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1805     ~ZeroCmpBranchesAArch64() override = default;
1806     void Run(BB &bb, Insn &insn) override;
1807 };
1808 
1809 /*
1810  * and	x0, x0, #281474976710655    ====> eor	x0, x0, x1
1811  * and	x1, x1, #281474976710655          tst	x0, 281474976710655
1812  * cmp	x0, x1                            bne	.L.5187__150
1813  * bne	.L.5187__150
1814  */
1815 class AndAndCmpBranchesToTstPattern : public CGPeepPattern {
1816 public:
AndAndCmpBranchesToTstPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)1817     AndAndCmpBranchesToTstPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
1818         : CGPeepPattern(cgFunc, currBB, currInsn, info)
1819     {
1820     }
~AndAndCmpBranchesToTstPattern()1821     ~AndAndCmpBranchesToTstPattern() override
1822     {
1823         prevCmpInsn = nullptr;
1824     }
1825 
1826     void Run(BB &bb, Insn &insn) override;
1827     bool CheckCondition(Insn &insn) override;
GetPatternName()1828     std::string GetPatternName() override
1829     {
1830         return "AndAndCmpBranchesToCsetPattern";
1831     }
1832 
1833 private:
1834     bool CheckCondInsn(const Insn &insn);
1835     Insn *CheckAndGetPrevAndDefInsn(const RegOperand &regOpnd) const;
1836     bool CheckAndSelectPattern();
1837     RegOperand *ccReg = nullptr;
1838     Insn *prevPrevAndInsn = nullptr;
1839     Insn *prevAndInsn = nullptr;
1840     Insn *prevCmpInsn = nullptr;
1841     MOperator newTstMop = MOP_undef;
1842     MOperator newEorMop = MOP_undef;
1843     int64 tstImmVal = -1;
1844 };
1845 
1846 /*
1847  * Look for duplicate or overlapping zero or sign extensions.
1848  * Examples:
1849  *   sxth x1, x2   ====> sxth x1, x2
1850  *   sxth x3, x1         mov  x3, x1
1851  *
1852  *   sxtb x1, x2   ====> sxtb x1, x2
1853  *   sxth x3, x1         mov  x3, x1
1854  */
1855 class ElimDuplicateExtensionAArch64 : public PeepPattern {
1856 public:
ElimDuplicateExtensionAArch64(CGFunc & cgFunc)1857     explicit ElimDuplicateExtensionAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1858     ~ElimDuplicateExtensionAArch64() override = default;
1859     void Run(BB &bb, Insn &insn) override;
1860 };
1861 
1862 /*
1863  *  cmp  w0, #0
1864  *  cset w1, NE --> mov w1, w0
1865  *
1866  *  cmp  w0, #0
1867  *  cset w1, EQ --> eor w1, w0, 1
1868  *
1869  *  cmp  w0, #1
1870  *  cset w1, NE --> eor w1, w0, 1
1871  *
1872  *  cmp  w0, #1
1873  *  cset w1, EQ --> mov w1, w0
1874  *
1875  *  cmp w0,  #0
1876  *  cset w0, NE -->null
1877  *
1878  *  cmp w0, #1
1879  *  cset w0, EQ -->null
1880  *
1881  *  condition:
1882  *    1. the first operand of cmp instruction must has only one valid bit
1883  *    2. the second operand of cmp instruction must be 0 or 1
1884  *    3. flag register of cmp isntruction must not be used later
1885  */
1886 class CmpCsetAArch64 : public PeepPattern {
1887 public:
CmpCsetAArch64(CGFunc & cgFunc)1888     explicit CmpCsetAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1889     ~CmpCsetAArch64() override = default;
1890     void Run(BB &bb, Insn &insn) override;
1891 
1892 private:
1893     bool CheckOpndDefPoints(Insn &checkInsn, int opndIdx);
1894     const Insn *DefInsnOfOperandInBB(const Insn &startInsn, const Insn &checkInsn, int opndIdx) const;
1895     bool OpndDefByOneValidBit(const Insn &defInsn) const;
1896     bool FlagUsedLaterInCurBB(const BB &bb, Insn &startInsn) const;
1897 };
1898 
1899 /*
1900  *  add     x0, x1, x0
1901  *  ldr     x2, [x0]
1902  *  ==>
1903  *  ldr     x2, [x1, x0]
1904  */
1905 class ComplexMemOperandAddAArch64 : public PeepPattern {
1906 public:
ComplexMemOperandAddAArch64(CGFunc & cgFunc)1907     explicit ComplexMemOperandAddAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1908     ~ComplexMemOperandAddAArch64() override = default;
1909     void Run(BB &bb, Insn &insn) override;
1910 
1911 private:
1912     bool IsExpandBaseOpnd(const Insn &insn, const Insn &prevInsn) const;
1913 };
1914 
1915 /*
1916  * cbnz w0, @label
1917  * ....
1918  * mov  w0, #0 (elseBB)        -->this instruction can be deleted
1919  *
1920  * cbz  w0, @label
1921  * ....
1922  * mov  w0, #0 (ifBB)          -->this instruction can be deleted
1923  *
1924  * condition:
1925  *  1.there is not predefine points of w0 in elseBB(ifBB)
1926  *  2.the first opearnd of cbnz insn is same as the first Operand of mov insn
1927  *  3.w0 is defined by move 0
1928  *  4.all preds of elseBB(ifBB) end with cbnz or cbz
1929  *
1930  *  NOTE: if there are multiple preds and there is not define point of w0 in one pred,
1931  *        (mov w0, 0) can't be deleted, avoiding use before def.
1932  */
1933 class DeleteMovAfterCbzOrCbnzAArch64 : public PeepPattern {
1934 public:
DeleteMovAfterCbzOrCbnzAArch64(CGFunc & cgFunc)1935     explicit DeleteMovAfterCbzOrCbnzAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc)
1936     {
1937         cgcfg = cgFunc.GetTheCFG();
1938         cgcfg->InitInsnVisitor(cgFunc);
1939     }
1940     ~DeleteMovAfterCbzOrCbnzAArch64() override = default;
1941     void Run(BB &bb, Insn &insn) override;
1942 
1943 private:
1944     bool PredBBCheck(BB &bb, bool checkCbz, const Operand &opnd, bool is64BitOnly) const;
1945     bool OpndDefByMovZero(const Insn &insn) const;
1946     bool NoPreDefine(Insn &testInsn) const;
1947     void ProcessBBHandle(BB *processBB, const BB &bb, const Insn &insn) const;
1948     bool NoMoreThan32BitUse(Insn &testInsn) const;
1949     CGCFG *cgcfg;
1950 };
1951 
1952 /* we optimize the following scenarios in this pattern:
1953  * for example 1:
1954  * mov     w1, #9
1955  * cmp     w0, #1              =>               cmp     w0, #1
1956  * mov     w2, #8                               csel    w0, w0, wzr, EQ
1957  * csel    w0, w1, w2, EQ                       add     w0, w0, #8
1958  * for example 2:
1959  * mov     w1, #8
1960  * cmp     w0, #1              =>               cmp     w0, #1
1961  * mov     w2, #9                               cset    w0, NE
1962  * csel    w0, w1, w2, EQ                       add     w0, w0, #8
1963  * for example 3:
1964  * mov     w1, #3
1965  * cmp     w0, #4              =>               cmp     w0, #4
1966  * mov     w2, #7                               csel    w0, w0, wzr, EQ
1967  * csel    w0, w1, w2, NE                       add     w0, w0, #3
1968  * condition:
1969  *  1. The source operand of the two mov instructions are immediate operand;
1970  *  2. The difference value between two immediates is equal to the value being compared in the cmp insn;
1971  *  3. The reg w1 and w2 are not used in the instructions after csel;
1972  *  4. The condOpnd in csel insn must be CC_NE or CC_EQ;
1973  *  5. If the value in w1 is less than value in w2, condition in csel must be CC_NE, otherwise,
1974  *     the difference between them must be one;
1975  *  6. If the value in w1 is more than value in w2, condition in csel must be CC_EQ, otherwise,
1976  *     the difference between them must be one.
1977  */
1978 class CombineMovInsnBeforeCSelPattern : public CGPeepPattern {
1979 public:
CombineMovInsnBeforeCSelPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1980     CombineMovInsnBeforeCSelPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn)
1981         : CGPeepPattern(cgFunc, currBB, currInsn)
1982     {
1983     }
~CombineMovInsnBeforeCSelPattern()1984     ~CombineMovInsnBeforeCSelPattern() override
1985     {
1986         insnMov2 = nullptr;
1987         insnMov1 = nullptr;
1988         cmpInsn = nullptr;
1989     }
1990     void Run(BB &bb, Insn &insn) override;
1991     bool CheckCondition(Insn &insn) override;
GetPatternName()1992     std::string GetPatternName() override
1993     {
1994         return "CombineMovInsnBeforeCSelPattern";
1995     }
1996 
1997 private:
1998     Insn *FindPrevMovInsn(const Insn &insn, regno_t regNo) const;
1999     Insn *FindPrevCmpInsn(const Insn &insn) const;
2000     Insn *insnMov2 = nullptr;
2001     Insn *insnMov1 = nullptr;
2002     Insn *cmpInsn = nullptr;
2003     bool needReverseCond = false;
2004     bool needCsetInsn = false;
2005 };
2006 
2007 /*
2008  * We optimize the following pattern in this function:
2009  * if w0's valid bits is one
2010  * uxtb w0, w0
2011  * eor w0, w0, #1
2012  * cbz w0, .label
2013  * =>
2014  * tbnz w0, .label
2015  * &&
2016  * if there exists uxtb w0, w0 and w0's valid bits is
2017  * less than 8, eliminate it.
2018  */
2019 class OneHoleBranchesPreAArch64 : public PeepPattern {
2020 public:
OneHoleBranchesPreAArch64(CGFunc & cgFunc)2021     explicit OneHoleBranchesPreAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
2022     ~OneHoleBranchesPreAArch64() override = default;
2023     void Run(BB &bb, Insn &insn) override;
2024 
2025 private:
2026     MOperator FindNewMop(const BB &bb, const Insn &insn) const;
2027 };
2028 
2029 /*
2030  * We optimize the following pattern in this function:
2031  * movz x0, #11544, LSL #0
2032  * movk x0, #21572, LSL #16
2033  * movk x0, #8699, LSL #32
2034  * movk x0, #16393, LSL #48
2035  * =>
2036  * ldr x0, label_of_constant_1
2037  */
2038 class LoadFloatPointPattern : public CGPeepPattern {
2039 public:
LoadFloatPointPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)2040     LoadFloatPointPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
2041     ~LoadFloatPointPattern() override = default;
2042     void Run(BB &bb, Insn &insn) override;
2043     bool CheckCondition(Insn &insn) override;
GetPatternName()2044     std::string GetPatternName() override
2045     {
2046         return "LoadFloatPointPattern";
2047     }
2048 
2049 private:
2050     bool FindLoadFloatPoint(Insn &insn);
2051     bool IsPatternMatch();
2052     std::vector<Insn *> optInsn;
2053 };
2054 
2055 /*
2056  * Optimize the following patterns:
2057  *  orr  w21, w0, #0  ====> mov  w21, w0
2058  *  orr  w21, #0, w0  ====> mov  w21, w0
2059  */
2060 class ReplaceOrrToMovAArch64 : public PeepPattern {
2061 public:
ReplaceOrrToMovAArch64(CGFunc & cgFunc)2062     explicit ReplaceOrrToMovAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
2063     ~ReplaceOrrToMovAArch64() override = default;
2064     void Run(BB &bb, Insn &insn) override;
2065 };
2066 
2067 /*
2068  * Optimize the following patterns:
2069  *  ldr  w0, [x21,#68]        ldr  w0, [x21,#68]
2070  *  mov  w1, #-1              mov  w1, #-1
2071  *  cmp  w0, w1     ====>     cmn  w0, #-1
2072  */
2073 class ReplaceCmpToCmnAArch64 : public PeepPattern {
2074 public:
ReplaceCmpToCmnAArch64(CGFunc & cgFunc)2075     explicit ReplaceCmpToCmnAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
2076     ~ReplaceCmpToCmnAArch64() override = default;
2077     void Run(BB &bb, Insn &insn) override;
2078 };
2079 
2080 /*
2081  * Remove following patterns:
2082  *   mov x0, XX
2083  *   mov x1, XX
2084  *   bl  MCC_IncDecRef_NaiveRCFast
2085  */
2086 class RemoveIncRefPattern : public CGPeepPattern {
2087 public:
RemoveIncRefPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)2088     RemoveIncRefPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~RemoveIncRefPattern()2089     ~RemoveIncRefPattern() override
2090     {
2091         insnMov2 = nullptr;
2092         insnMov1 = nullptr;
2093     }
2094     void Run(BB &bb, Insn &insn) override;
2095     bool CheckCondition(Insn &insn) override;
GetPatternName()2096     std::string GetPatternName() override
2097     {
2098         return "RemoveIncRefPattern";
2099     }
2100 
2101 private:
2102     Insn *insnMov2 = nullptr;
2103     Insn *insnMov1 = nullptr;
2104 };
2105 
2106 /*
2107  * opt long int compare with 0
2108  *  *cmp x0, #0
2109  *  csinv w0, wzr, wzr, GE
2110  *  csinc w0, w0, wzr, LE
2111  *  cmp w0, #0
2112  *  =>
2113  *  cmp x0, #0
2114  */
2115 class LongIntCompareWithZPattern : public CGPeepPattern {
2116 public:
LongIntCompareWithZPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)2117     LongIntCompareWithZPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
2118     ~LongIntCompareWithZPattern() override = default;
2119     void Run(BB &bb, Insn &insn) override;
2120     bool CheckCondition(Insn &insn) override;
GetPatternName()2121     std::string GetPatternName() override
2122     {
2123         return "LongIntCompareWithZPattern";
2124     }
2125 
2126 private:
2127     bool FindLondIntCmpWithZ(Insn &insn);
2128     bool IsPatternMatch();
2129     std::vector<Insn *> optInsn;
2130 };
2131 
2132 // pattern1 :
2133 // -----------------------------------------------------
2134 // lsr(304)  R327 R324 8
2135 // strb(462) R327 [R164, 10]    rev16 R327 R324
2136 // strb(462) R324 [R164, 11] => strh  R327 [R164 10]
2137 // pattern2 :
2138 // ldrb(362) R369 R163 7
2139 // ldrb(362) R371 R163 6           ldrh   R369 R163 6
2140 // add(157)  R374 R369 R371 LSL => rev16  R374 R369
2141 
2142 class LdrStrRevPattern : public CGPeepPattern {
2143 public:
LdrStrRevPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)2144     LdrStrRevPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~LdrStrRevPattern()2145     ~LdrStrRevPattern() override
2146     {
2147         lsrInsn = nullptr;
2148         adjacentInsn = nullptr;
2149         curMemOpnd = nullptr;
2150         adjacentMemOpnd = nullptr;
2151     }
2152     void Run(BB &bb, Insn &insn) override;
2153     bool CheckCondition(Insn &insn) override;
GetPatternName()2154     std::string GetPatternName() override
2155     {
2156         return "LdrStrRevPattern";
2157     }
2158 
2159 private:
2160     bool IsAdjacentMem(const MemOperand &memOperandLow, const MemOperand &memOperandHigh) const;
2161     Insn *lsrInsn = nullptr;
2162     Insn *adjacentInsn = nullptr;
2163     MemOperand *curMemOpnd = nullptr;
2164     MemOperand *adjacentMemOpnd = nullptr;
2165     bool isStrInsn = false;
2166 };
2167 
2168 class ComplexMemOperandAArch64 : public PeepPattern {
2169 public:
ComplexMemOperandAArch64(CGFunc & cgFunc)2170     explicit ComplexMemOperandAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
2171     ~ComplexMemOperandAArch64() override = default;
2172     void Run(BB &bb, Insn &insn) override;
2173 };
2174 
2175 /*
2176  *  add     x0, x1, x0
2177  *  ldr     x2, [x0]
2178  *  ==>
2179  *  ldr     x2, [x1, x0]
2180  */
2181 class ComplexMemOperandPreAddAArch64 : public PeepPattern {
2182 public:
ComplexMemOperandPreAddAArch64(CGFunc & cgFunc)2183     explicit ComplexMemOperandPreAddAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
2184     ~ComplexMemOperandPreAddAArch64() override = default;
2185     void Run(BB &bb, Insn &insn) override;
2186 };
2187 
2188 /*
2189  * add     x0, x0, x1, LSL #2
2190  * ldr     x2, [x0]
2191  * ==>
2192  * ldr     x2, [x0,x1,LSL #2]
2193  */
2194 class ComplexMemOperandLSLAArch64 : public PeepPattern {
2195 public:
ComplexMemOperandLSLAArch64(CGFunc & cgFunc)2196     explicit ComplexMemOperandLSLAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
2197     ~ComplexMemOperandLSLAArch64() override = default;
2198     bool CheckShiftValid(const Insn &insn, const BitShiftOperand &lsl) const;
2199     void Run(BB &bb, Insn &insn) override;
2200 };
2201 
2202 /*
2203  * ldr     x0, label_of_constant_1
2204  * fmov    d4, x0
2205  * ==>
2206  * ldr     d4, label_of_constant_1
2207  */
2208 class ComplexMemOperandLabelAArch64 : public PeepPattern {
2209 public:
ComplexMemOperandLabelAArch64(CGFunc & cgFunc)2210     explicit ComplexMemOperandLabelAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
2211     ~ComplexMemOperandLabelAArch64() override = default;
2212     void Run(BB &bb, Insn &insn) override;
2213 };
2214 
2215 /*
2216  * mov R0, vreg1 / R0         mov R0, vreg1
2217  * add vreg2, vreg1, #imm1    add vreg2, vreg1, #imm1
2218  * mov R1, vreg2              mov R1, vreg2
2219  * mov R2, vreg3              mov R2, vreg3
2220  * ...                        ...
2221  * mov R0, vreg1
2222  * add vreg4, vreg1, #imm2 -> str vreg5, [vreg1, #imm2]
2223  * mov R1, vreg4
2224  * mov R2, vreg5
2225  */
2226 class WriteFieldCallPattern : public CGPeepPattern {
2227 public:
2228     struct WriteRefFieldParam {
2229         Operand *objOpnd = nullptr;
2230         RegOperand *fieldBaseOpnd = nullptr;
2231         int64 fieldOffset = 0;
2232         Operand *fieldValue = nullptr;
2233     };
WriteFieldCallPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)2234     WriteFieldCallPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~WriteFieldCallPattern()2235     ~WriteFieldCallPattern() override
2236     {
2237         prevCallInsn = nullptr;
2238         nextInsn = nullptr;
2239     }
2240     void Run(BB &bb, Insn &insn) override;
2241     bool CheckCondition(Insn &insn) override;
GetPatternName()2242     std::string GetPatternName() override
2243     {
2244         return "WriteFieldCallPattern";
2245     }
2246 
2247 private:
2248     bool hasWriteFieldCall = false;
2249     Insn *prevCallInsn = nullptr;
2250     Insn *nextInsn = nullptr;
2251     WriteRefFieldParam firstCallParam;
2252     WriteRefFieldParam currentCallParam;
2253     std::vector<Insn *> paramDefInsns;
2254     bool WriteFieldCallOptPatternMatch(const Insn &writeFieldCallInsn, WriteRefFieldParam &param);
2255     bool IsWriteRefFieldCallInsn(const Insn &insn) const;
2256 };
2257 
2258 /*
2259  * Remove following patterns:
2260  *     mov     x0, xzr/#0
2261  *     bl      MCC_DecRef_NaiveRCFast
2262  */
2263 class RemoveDecRefPattern : public CGPeepPattern {
2264 public:
RemoveDecRefPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)2265     RemoveDecRefPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~RemoveDecRefPattern()2266     ~RemoveDecRefPattern() override
2267     {
2268         prevInsn = nullptr;
2269     }
2270     void Run(BB &bb, Insn &insn) override;
2271     bool CheckCondition(Insn &insn) override;
GetPatternName()2272     std::string GetPatternName() override
2273     {
2274         return "RemoveDecRefPattern";
2275     }
2276 
2277 private:
2278     Insn *prevInsn = nullptr;
2279 };
2280 
2281 /*
2282  * We optimize the following pattern in this function:
2283  * and x1, x1, #imm (is n power of 2)
2284  * cbz/cbnz x1, .label
2285  * =>
2286  * and x1, x1, #imm (is n power of 2)
2287  * tbnz/tbz x1, #n, .label
2288  */
2289 class OneHoleBranchesAArch64 : public PeepPattern {
2290 public:
OneHoleBranchesAArch64(CGFunc & cgFunc)2291     explicit OneHoleBranchesAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
2292     ~OneHoleBranchesAArch64() override = default;
2293     void Run(BB &bb, Insn &insn) override;
2294 };
2295 
2296 /*
2297  * Replace following pattern:
2298  * mov x1, xzr
2299  * bl MCC_IncDecRef_NaiveRCFast
2300  * =>
2301  * bl MCC_IncRef_NaiveRCFast
2302  */
2303 class ReplaceIncDecWithIncPattern : public CGPeepPattern {
2304 public:
ReplaceIncDecWithIncPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)2305     ReplaceIncDecWithIncPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~ReplaceIncDecWithIncPattern()2306     ~ReplaceIncDecWithIncPattern() override
2307     {
2308         prevInsn = nullptr;
2309         target = nullptr;
2310     }
2311     void Run(BB &bb, Insn &insn) override;
2312     bool CheckCondition(Insn &insn) override;
GetPatternName()2313     std::string GetPatternName() override
2314     {
2315         return "ReplaceIncDecWithIncPattern";
2316     }
2317 
2318 private:
2319     Insn *prevInsn = nullptr;
2320     FuncNameOperand *target = nullptr;
2321 };
2322 
2323 /*
2324  * Replace following patterns:
2325  *
2326  * add   w1, w0, w1
2327  * cmp   w1, #0       ====>  adds w1, w0, w1
2328  *       EQ
2329  *
2330  * add   x1, x0, x1
2331  * cmp   x1, #0       ====>  adds x1, x0, x1
2332  *.......EQ
2333  *
2334  * ....
2335  */
2336 class AddCmpZeroPattern : public CGPeepPattern {
2337 public:
AddCmpZeroPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)2338     AddCmpZeroPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~AddCmpZeroPattern()2339     ~AddCmpZeroPattern() override
2340     {
2341         prevInsn = nullptr;
2342     }
2343     void Run(BB &bb, Insn &insn) override;
2344     bool CheckCondition(Insn &insn) override;
GetPatternName()2345     std::string GetPatternName() override
2346     {
2347         return "AddCmpZeroPattern";
2348     }
2349 
2350 private:
2351     bool CheckAddCmpZeroCheckAdd(const Insn &insn) const;
2352     bool CheckAddCmpZeroContinue(const Insn &insn, const RegOperand &opnd) const;
2353     bool CheckAddCmpZeroCheckCond(const Insn &insn) const;
2354     Insn *prevInsn = nullptr;
2355 };
2356 
2357 /*
2358  * Replace following pattern:
2359  * sxtw  x1, w0
2360  * lsl   x2, x1, #3  ====>  sbfiz x2, x0, #3, #32
2361  *
2362  * uxtw  x1, w0
2363  * lsl   x2, x1, #3  ====>  ubfiz x2, x0, #3, #32
2364  */
2365 class ComplexExtendWordLslAArch64 : public PeepPattern {
2366 public:
ComplexExtendWordLslAArch64(CGFunc & cgFunc)2367     explicit ComplexExtendWordLslAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
2368     ~ComplexExtendWordLslAArch64() override = default;
2369     void Run(BB &bb, Insn &insn) override;
2370 
2371 private:
2372     bool IsExtendWordLslPattern(const Insn &insn) const;
2373 };
2374 
2375 class ComplexExtendWordLslPattern : public CGPeepPattern {
2376 public:
ComplexExtendWordLslPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)2377     ComplexExtendWordLslPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~ComplexExtendWordLslPattern()2378     ~ComplexExtendWordLslPattern() override
2379     {
2380         useInsn = nullptr;
2381     }
2382     void Run(BB &bb, Insn &insn) override;
2383     bool CheckCondition(Insn &insn) override;
GetPatternName()2384     std::string GetPatternName() override
2385     {
2386         return "ComplexExtendWordLslPattern";
2387     }
2388 
2389 private:
2390     Insn *useInsn = nullptr;
2391 };
2392 
2393 /*
2394  * Replace following patterns:
2395  *
2396  * add   w1, w0, w1
2397  * cmp   w1, #0       ====>  adds w1, w0, w1
2398  *       EQ
2399  *
2400  * add   x1, x0, x1
2401  * cmp   x1, #0       ====>  adds x1, x0, x1
2402  *       EQ
2403  *
2404  * ....
2405  */
2406 class AddCmpZeroPatternSSA : public CGPeepPattern {
2407 public:
AddCmpZeroPatternSSA(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)2408     AddCmpZeroPatternSSA(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
2409         : CGPeepPattern(cgFunc, currBB, currInsn, info)
2410     {
2411     }
~AddCmpZeroPatternSSA()2412     ~AddCmpZeroPatternSSA() override
2413     {
2414         prevAddInsn = nullptr;
2415     }
2416     void Run(BB &bb, Insn &insn) override;
2417     bool CheckCondition(Insn &insn) override;
GetPatternName()2418     std::string GetPatternName() override
2419     {
2420         return "AddCmpZeroPatternSSA";
2421     }
2422 
2423 private:
2424     Insn *prevAddInsn = nullptr;
2425 };
2426 
2427 /*
2428  * Optimize the following patterns:
2429  *  and  w0, w6, #1  ====> tbz  w6, 0, .label
2430  *  cmp  w0, #1
2431  *  bne  .label
2432  *
2433  *  and  w0, w6, #16  ====> tbz  w6, 4, .label
2434  *  cmp  w0, #16
2435  *  bne  .label
2436  *
2437  *  and  w0, w6, #32  ====> tbnz  w6, 5, .label
2438  *  cmp  w0, #32
2439  *  beq  .label
2440  *
2441  *  and  x0, x6, #32  ====> tbz  x6, 5, .label
2442  *  cmp  x0, #0
2443  *  beq  .label
2444  *
2445  *  and  x0, x6, #32  ====> tbnz  x6, 5, .label
2446  *  cmp  x0, #0
2447  *  bne  .label
2448  */
2449 class AndCmpBranchesToTbzAArch64 : public PeepPattern {
2450 public:
AndCmpBranchesToTbzAArch64(CGFunc & cgFunc)2451     explicit AndCmpBranchesToTbzAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
2452     ~AndCmpBranchesToTbzAArch64() override = default;
2453     void Run(BB &bb, Insn &insn) override;
2454 };
2455 
2456 /*
2457  * Optimize the following patterns:
2458  * sxth  r4, r4         ====> strh r4, [r0, r3]
2459  * strh  r4, [r0, r3]
2460  *
2461  * sxtb  r4, r4         ====> strb r4, [r0, r3]
2462  * strb  r4, [r0, r3]
2463  */
2464 class RemoveSxtBeforeStrAArch64 : public PeepPattern {
2465 public:
RemoveSxtBeforeStrAArch64(CGFunc & cgFunc)2466     explicit RemoveSxtBeforeStrAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
2467     ~RemoveSxtBeforeStrAArch64() override = default;
2468     void Run(BB &bb, Insn &insn) override;
2469 };
2470 
2471 /*
2472  * Optimize the following patterns:
2473  * mov x1, #1
2474  * csel  x22, xzr, x1, LS   ====> cset x22, HI
2475  *
2476  * mov x1, #1
2477  * csel  x22, x1, xzr, LS   ====> cset x22, LS
2478  */
2479 class CselZeroOneToCsetOpt : public PeepPattern {
2480 public:
CselZeroOneToCsetOpt(CGFunc & cgFunc)2481     explicit CselZeroOneToCsetOpt(CGFunc &cgFunc) : PeepPattern(cgFunc), cgFunc(&cgFunc) {}
2482     ~CselZeroOneToCsetOpt() override = default;
2483     void Run(BB &bb, Insn &insn) override;
2484 
2485 private:
2486     Insn *trueMovInsn = nullptr;
2487     Insn *falseMovInsn = nullptr;
2488     Insn *FindFixedValue(Operand &opnd, BB &bb, Operand *&tempOp, const Insn &insn) const;
2489 
2490 protected:
2491     CGFunc *cgFunc;
2492 };
2493 
2494 /*
2495  * Optimize the following patterns:
2496  * and w0, w0, #0x1
2497  * cmp w0, #0x0
2498  * cset w0, eq
2499  * eor w0, w0, #0x1
2500  * cbz w0, label
2501  * ====>
2502  * tbz w0, 0, label
2503  */
2504 class AndCmpCsetEorCbzOpt : public PeepPattern {
2505 public:
AndCmpCsetEorCbzOpt(CGFunc & cgFunc)2506     explicit AndCmpCsetEorCbzOpt(CGFunc &cgFunc) : PeepPattern(cgFunc), cgFunc(&cgFunc) {}
2507     ~AndCmpCsetEorCbzOpt() override = default;
2508     void Run(BB &bb, Insn &insn) override;
2509 
2510 private:
2511     CGFunc *cgFunc;
2512 };
2513 
2514 /*
2515  * Optimize the following patterns:
2516  * add x0, x0, x1
2517  * ldr w0, [x0]
2518  * ====>
2519  * ldr w0, [x0, x1]
2520  */
2521 class AddLdrOpt : public PeepPattern {
2522 public:
AddLdrOpt(CGFunc & cgFunc)2523     explicit AddLdrOpt(CGFunc &cgFunc) : PeepPattern(cgFunc), cgFunc(&cgFunc) {}
2524     ~AddLdrOpt() override = default;
2525     void Run(BB &bb, Insn &insn) override;
2526 
2527 private:
2528     CGFunc *cgFunc;
2529 };
2530 
2531 /*
2532  * Optimize the following patterns:
2533  * cset x0, eq
2534  * eor x0, x0, 0x1
2535  * ====>
2536  * cset x0, ne
2537  */
2538 class CsetEorOpt : public PeepPattern {
2539 public:
CsetEorOpt(CGFunc & cgFunc)2540     explicit CsetEorOpt(CGFunc &cgFunc) : PeepPattern(cgFunc), cgFunc(&cgFunc) {}
2541     ~CsetEorOpt() override = default;
2542     void Run(BB &bb, Insn &insn) override;
2543 
2544 private:
2545     CGFunc *cgFunc;
2546 };
2547 
2548 /*
2549  * Optimize the following patterns:
2550  * mov x1, #0x5
2551  * cmp x0, x1
2552  * ====>
2553  * cmp x0, #0x5
2554  */
2555 class MoveCmpOpt : public PeepPattern {
2556 public:
MoveCmpOpt(CGFunc & cgFunc)2557     explicit MoveCmpOpt(CGFunc &cgFunc) : PeepPattern(cgFunc), cgFunc(&cgFunc) {}
2558     ~MoveCmpOpt() override = default;
2559     void Run(BB &bb, Insn &insn) override;
2560 
2561 private:
2562     CGFunc *cgFunc;
2563 };
2564 
2565 /*
2566  * Optimize the following patterns:
2567  * add x0, x0, #0x0         add x0, x1, #0x0
2568  * ====>
2569  * ---                      mov x0, x1
2570  */
2571 class AddImmZeroToMov : public PeepPattern {
2572 public:
AddImmZeroToMov(CGFunc & cgFunc)2573     explicit AddImmZeroToMov(CGFunc &cgFunc) : PeepPattern(cgFunc), cgFunc(&cgFunc) {}
2574     ~AddImmZeroToMov() override = default;
2575     void Run(BB &bb, Insn &insn) override;
2576 
2577 private:
2578     CGFunc *cgFunc;
2579 };
2580 
2581 class AArch64PeepHole : public PeepPatternMatch {
2582 public:
AArch64PeepHole(CGFunc & oneCGFunc,MemPool * memPool)2583     AArch64PeepHole(CGFunc &oneCGFunc, MemPool *memPool) : PeepPatternMatch(oneCGFunc, memPool) {}
2584     ~AArch64PeepHole() override = default;
2585     void InitOpts() override;
2586     void Run(BB &bb, Insn &insn) override;
2587 
2588 private:
2589     enum PeepholeOpts : int32 {
2590         kRemoveIdenticalLoadAndStoreOpt = 0,
2591         kRemoveMovingtoSameRegOpt,
2592         kCombineContiLoadAndStoreOpt,
2593         kEliminateSpecifcSXTOpt,
2594         kEliminateSpecifcUXTOpt,
2595         kFmovRegOpt,
2596         kCbnzToCbzOpt,
2597         kCsetCbzToBeqOpt,
2598         kContiLDRorSTRToSameMEMOpt,
2599         kRemoveIncDecRefOpt,
2600         kInlineReadBarriersOpt,
2601         kReplaceDivToMultiOpt,
2602         kAndCmpBranchesToCsetOpt,
2603         kAndCmpBranchesToTstOpt,
2604         kAndCbzBranchesToTstOpt,
2605         kZeroCmpBranchesOpt,
2606         kCselZeroOneToCsetOpt,
2607         kAndCmpCsetEorCbzOpt,
2608         kAddLdrOpt,
2609         kCsetEorOpt,
2610         kMoveCmpOpt,
2611         kPeepholeOptsNum
2612     };
2613 };
2614 
2615 class AArch64PeepHole0 : public PeepPatternMatch {
2616 public:
AArch64PeepHole0(CGFunc & oneCGFunc,MemPool * memPool)2617     AArch64PeepHole0(CGFunc &oneCGFunc, MemPool *memPool) : PeepPatternMatch(oneCGFunc, memPool) {}
2618     ~AArch64PeepHole0() override = default;
2619     void InitOpts() override;
2620     void Run(BB &bb, Insn &insn) override;
2621 
2622 private:
2623     enum PeepholeOpts : int32 {
2624         kRemoveIdenticalLoadAndStoreOpt = 0,
2625         kCmpCsetOpt,
2626         kComplexMemOperandOptAdd,
2627         kDeleteMovAfterCbzOrCbnzOpt,
2628         kRemoveSxtBeforeStrOpt,
2629         kRemoveMovingtoSameRegOpt,
2630         kEnhanceStrLdrAArch64Opt,
2631         kAddImmZeroToMov,
2632         kPeepholeOptsNum
2633     };
2634 };
2635 
2636 class AArch64PrePeepHole : public PeepPatternMatch {
2637 public:
AArch64PrePeepHole(CGFunc & oneCGFunc,MemPool * memPool)2638     AArch64PrePeepHole(CGFunc &oneCGFunc, MemPool *memPool) : PeepPatternMatch(oneCGFunc, memPool) {}
2639     ~AArch64PrePeepHole() override = default;
2640     void InitOpts() override;
2641     void Run(BB &bb, Insn &insn) override;
2642 
2643 private:
2644     enum PeepholeOpts : int32 {
2645         kOneHoleBranchesPreOpt = 0,
2646         kLoadFloatPointOpt,
2647         kReplaceOrrToMovOpt,
2648         kReplaceCmpToCmnOpt,
2649         kRemoveIncRefOpt,
2650         kLongIntCompareWithZOpt,
2651         kComplexMemOperandOpt,
2652         kComplexMemOperandPreOptAdd,
2653         kComplexMemOperandOptLSL,
2654         kComplexMemOperandOptLabel,
2655         kWriteFieldCallOpt,
2656         kDuplicateExtensionOpt,
2657         kEnhanceStrLdrAArch64Opt,
2658         kUbfxToUxtw,
2659         kPeepholeOptsNum
2660     };
2661 };
2662 
2663 class AArch64PrePeepHole1 : public PeepPatternMatch {
2664 public:
AArch64PrePeepHole1(CGFunc & oneCGFunc,MemPool * memPool)2665     AArch64PrePeepHole1(CGFunc &oneCGFunc, MemPool *memPool) : PeepPatternMatch(oneCGFunc, memPool) {}
2666     ~AArch64PrePeepHole1() override = default;
2667     void InitOpts() override;
2668     void Run(BB &bb, Insn &insn) override;
2669 
2670 private:
2671     enum PeepholeOpts : int32 {
2672         kRemoveDecRefOpt = 0,
2673         kComputationTreeOpt,
2674         kOneHoleBranchesOpt,
2675         kReplaceIncDecWithIncOpt,
2676         kAndCmpBranchesToTbzOpt,
2677         kComplexExtendWordLslOpt,
2678         kPeepholeOptsNum
2679     };
2680 };
2681 } /* namespace maplebe */
2682 #endif /* MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_PEEP_H */
2683