• 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_cg.h"
22 #include "optimize_common.h"
23 #include "mir_builder.h"
24 
25 namespace maplebe {
26 class AArch64CGPeepHole : CGPeepHole {
27 public:
28     /* normal constructor */
AArch64CGPeepHole(CGFunc & f,MemPool * memPool)29     AArch64CGPeepHole(CGFunc &f, MemPool *memPool) : CGPeepHole(f, memPool) {};
30     /* constructor for ssa */
AArch64CGPeepHole(CGFunc & f,MemPool * memPool,CGSSAInfo * cgssaInfo)31     AArch64CGPeepHole(CGFunc &f, MemPool *memPool, CGSSAInfo *cgssaInfo) : CGPeepHole(f, memPool, cgssaInfo) {};
32     ~AArch64CGPeepHole() = default;
33 
34     void Run() override;
35     bool DoSSAOptimize(BB &bb, Insn &insn) override;
36     void DoNormalOptimize(BB &bb, Insn &insn) override;
37 };
38 
39 /*
40  * i.   cmp     x0, x1
41  *      cset    w0, EQ     ===>   cmp x0, x1
42  *      cmp     w0, #0            cset w0, EQ
43  *      cset    w0, NE
44  *
45  * ii.  cmp     x0, x1
46  *      cset    w0, EQ     ===>   cmp x0, x1
47  *      cmp     w0, #0            cset w0, NE
48  *      cset    w0, EQ
49  */
50 class ContinuousCmpCsetPattern : public CGPeepPattern {
51 public:
ContinuousCmpCsetPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)52     ContinuousCmpCsetPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
53         : CGPeepPattern(cgFunc, currBB, currInsn, info)
54     {
55     }
56     ~ContinuousCmpCsetPattern() override = default;
57     void Run(BB &bb, Insn &insn) override;
58     bool CheckCondition(Insn &insn) override;
GetPatternName()59     std::string GetPatternName() override
60     {
61         return "ContinuousCmpCsetPattern";
62     }
63 
64 private:
65     bool CheckCondCode(const CondOperand &condOpnd) const;
66     Insn *prevCmpInsn = nullptr;
67     Insn *prevCsetInsn1 = nullptr;
68     Insn *prevCmpInsn1 = nullptr;
69     bool reverse = false;
70 };
71 
72 /*
73  * Example 1)
74  *  mov w5, #1
75  *   ...
76  *  mov w0, #0
77  *  csel w5, w5, w0, NE    ===> cset w5, NE
78  *
79  * Example 2)
80  *  mov w5, #0
81  *   ...
82  *  mov w0, #1
83  *  csel w5, w5, w0, NE    ===> cset w5,EQ
84  *
85  * conditions:
86  * 1. mov_imm1 value is 0(1) && mov_imm value is 1(0)
87  */
88 class CselToCsetPattern : public CGPeepPattern {
89 public:
CselToCsetPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)90     CselToCsetPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
91         : CGPeepPattern(cgFunc, currBB, currInsn, info)
92     {
93     }
94     ~CselToCsetPattern() override = default;
95     void Run(BB &bb, Insn &insn) override;
96     bool CheckCondition(Insn &insn) override;
GetPatternName()97     std::string GetPatternName() override
98     {
99         return "CselToCsetPattern";
100     }
101 
102 private:
103     bool IsOpndDefByZero(const Insn &insn) const;
104     bool IsOpndDefByOne(const Insn &insn) const;
105     Insn *prevMovInsn1 = nullptr;
106     Insn *prevMovInsn2 = nullptr;
107 };
108 
109 /*
110  * combine cset & cbz/cbnz ---> beq/bne
111  * Example 1)
112  *  cset    w0, EQ            or       cset    w0, NE
113  *  cbnz    w0, .label                 cbnz    w0, .label
114  *  ===> beq .label                    ===> bne .label
115  *
116  * Case: same conditon_code
117  *
118  * Example 2)
119  *  cset    w0, EQ            or       cset    w0, NE
120  *  cbz     w0, .label                 cbz    w0, .label
121  *  ===> bne .label                    ===> beq .label
122  *
123  * Case: reversed condition_code
124  */
125 class CsetCbzToBeqPattern : public CGPeepPattern {
126 public:
CsetCbzToBeqPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)127     CsetCbzToBeqPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
128         : CGPeepPattern(cgFunc, currBB, currInsn, info)
129     {
130     }
131     ~CsetCbzToBeqPattern() override = default;
GetPatternName()132     std::string GetPatternName() override
133     {
134         return "CsetCbzToBeqPattern";
135     }
136     bool CheckCondition(Insn &insn) override;
137     void Run(BB &bb, Insn &insn) override;
138 
139 private:
140     MOperator SelectNewMop(ConditionCode condCode, bool inverse) const;
141     Insn *prevInsn = nullptr;
142 };
143 
144 /*
145  * combine neg & cmp --> cmn
146  * Example 1)
147  *  neg x0, x6
148  *  cmp x2, x0                --->    (currInsn)
149  *  ===> cmn x2, x6
150  *
151  * Example 2)
152  *  neg x0, x6, LSL #5
153  *  cmp x2, x0                --->    (currInsn)
154  *  ===> cmn x2, x6, LSL #5
155  *
156  * Conditions:
157  * 1. neg_amount_val is valid in cmn amount range
158  */
159 class NegCmpToCmnPattern : public CGPeepPattern {
160 public:
NegCmpToCmnPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)161     NegCmpToCmnPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
162         : CGPeepPattern(cgFunc, currBB, currInsn, info)
163     {
164     }
165     ~NegCmpToCmnPattern() override = default;
166     void Run(BB &bb, Insn &insn) override;
167     bool CheckCondition(Insn &insn) override;
GetPatternName()168     std::string GetPatternName() override
169     {
170         return "NegCmpToCmnPattern";
171     }
172 
173 private:
174     Insn *prevInsn = nullptr;
175 };
176 
177 /*
178  * combine {sxtw / uxtw} & lsl ---> {sbfiz / ubfiz}
179  * sxtw  x1, w0
180  * lsl   x2, x1, #3    ===>   sbfiz x2, x0, #3, #32
181  *
182  * uxtw  x1, w0
183  * lsl   x2, x1, #3    ===>   ubfiz x2, x0, #3, #32
184  */
185 class ExtLslToBitFieldInsertPattern : public CGPeepPattern {
186 public:
ExtLslToBitFieldInsertPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)187     ExtLslToBitFieldInsertPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
188         : CGPeepPattern(cgFunc, currBB, currInsn, info)
189     {
190     }
191     ~ExtLslToBitFieldInsertPattern() override = default;
GetPatternName()192     std::string GetPatternName() override
193     {
194         return "ExtLslToBitFieldInsertPattern";
195     }
196     bool CheckCondition(Insn &insn) override;
197     void Run(BB &bb, Insn &insn) override;
198 
199 private:
200     Insn *prevInsn = nullptr;
201 };
202 
203 /*
204  * Optimize the following patterns:
205  * Example 1)
206  *  and  w0, w6, #1  ====> tbz  w6, #0, .label
207  *  cmp  w0, #1
208  *  bne  .label
209  *
210  *  and  w0, w6, #16  ====> tbz  w6, #4, .label
211  *  cmp  w0, #16
212  *  bne  .label
213  *
214  *  and  w0, w6, #32  ====> tbnz  w6, #5, .label
215  *  cmp  w0, #32
216  *  beq  .label
217  *
218  * Conditions:
219  * 1. cmp_imm value == and_imm value
220  * 2. (and_imm value is (1 << n)) && (cmp_imm value is (1 << n))
221  *
222  * Example 2)
223  *  and  x0, x6, #32  ====> tbz  x6, #5, .label
224  *  cmp  x0, #0
225  *  beq  .label
226  *
227  *  and  x0, x6, #32  ====> tbnz  x6, #5, .label
228  *  cmp  x0, #0
229  *  bne  .labelSimplifyMulArithmeticPattern
230  *
231  * Conditions:
232  * 1. (cmp_imm value is 0) || (cmp_imm == and_imm)
233  * 2. and_imm value is (1 << n)
234  */
235 class AndCmpBranchesToTbzPattern : public CGPeepPattern {
236 public:
AndCmpBranchesToTbzPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)237     AndCmpBranchesToTbzPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
238         : CGPeepPattern(cgFunc, currBB, currInsn, info)
239     {
240     }
241     ~AndCmpBranchesToTbzPattern() override = default;
242     void Run(BB &bb, Insn &insn) override;
243     bool CheckCondition(Insn &insn) override;
GetPatternName()244     std::string GetPatternName() override
245     {
246         return "AndCmpBranchesToTbzPattern";
247     }
248 
249 private:
250     bool CheckAndSelectPattern(const Insn &currInsn);
251     Insn *prevAndInsn = nullptr;
252     Insn *prevCmpInsn = nullptr;
253     MOperator newMop = MOP_undef;
254     int64 tbzImmVal = -1;
255 };
256 
257 /*
258  * optimize the following patterns:
259  * Example 1)
260  * cmp w1, wzr
261  * bge .label        ====> tbz w1, #31, .label
262  *
263  * cmp wzr, w1
264  * ble .label        ====> tbz w1, #31, .label
265  *
266  * cmp w1,wzr
267  * blt .label        ====> tbnz w1, #31, .label
268  *
269  * cmp wzr, w1
270  * bgt .label        ====> tbnz w1, #31, .label
271  *
272  *
273  * Example 2)
274  * cmp w1, #0
275  * bge .label        ====> tbz w1, #31, .label
276  *
277  * cmp w1, #0
278  * blt .label        ====> tbnz w1, #31, .label
279  */
280 class ZeroCmpBranchesToTbzPattern : public CGPeepPattern {
281 public:
ZeroCmpBranchesToTbzPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)282     ZeroCmpBranchesToTbzPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
283         : CGPeepPattern(cgFunc, currBB, currInsn, info)
284     {
285     }
286     ~ZeroCmpBranchesToTbzPattern() override = default;
287     void Run(BB &bb, Insn &insn) override;
288     bool CheckCondition(Insn &insn) override;
GetPatternName()289     std::string GetPatternName() override
290     {
291         return "ZeroCmpBranchesToTbzPattern";
292     }
293 
294 private:
295     bool CheckAndSelectPattern(const Insn &currInsn);
296     Insn *prevInsn = nullptr;
297     MOperator newMop = MOP_undef;
298     RegOperand *regOpnd = nullptr;
299 };
300 
301 /*
302  * mvn  w3, w3          ====> bic  w3, w5, w3
303  * and  w3, w5, w3
304  * ====>
305  * mvn  x3, x3          ====> bic  x3, x5, x3
306  * and  x3, x5, x3
307  */
308 class MvnAndToBicPattern : public CGPeepPattern {
309 public:
MvnAndToBicPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)310     MvnAndToBicPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
311         : CGPeepPattern(cgFunc, currBB, currInsn, info)
312     {
313     }
314     ~MvnAndToBicPattern() override = default;
315     void Run(BB &bb, Insn &insn) override;
316     bool CheckCondition(Insn &insn) override;
GetPatternName()317     std::string GetPatternName() override
318     {
319         return "MvnAndToBicPattern";
320     }
321 
322 private:
323     Insn *prevInsn1 = nullptr;
324     Insn *prevInsn2 = nullptr;
325     bool op1IsMvnDef = false;
326     bool op2IsMvnDef = false;
327 };
328 
329 /*
330  * and r0, r1, #4                  (the imm is n power of 2)
331  * ...
332  * cbz r0, .Label
333  * ===>  tbz r1, #2, .Label
334  *
335  * and r0, r1, #4                  (the imm is n power of 2)
336  * ...
337  * cbnz r0, .Label
338  * ===>  tbnz r1, #2, .Label
339  */
340 class AndCbzToTbzPattern : public CGPeepPattern {
341 public:
AndCbzToTbzPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)342     AndCbzToTbzPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
343         : CGPeepPattern(cgFunc, currBB, currInsn, info)
344     {
345     }
AndCbzToTbzPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)346     AndCbzToTbzPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
347     ~AndCbzToTbzPattern() override = default;
348     void Run(BB &bb, Insn &insn) override;
349     bool CheckCondition(Insn &insn) override;
GetPatternName()350     std::string GetPatternName() override
351     {
352         return "AndCbzToTbzPattern";
353     }
354 
355 private:
356     Insn *prevInsn = nullptr;
357 };
358 
359 class CombineSameArithmeticPattern : public CGPeepPattern {
360 public:
CombineSameArithmeticPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)361     CombineSameArithmeticPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
362         : CGPeepPattern(cgFunc, currBB, currInsn, info)
363     {
364     }
~CombineSameArithmeticPattern()365     ~CombineSameArithmeticPattern() override
366     {
367         prevInsn = nullptr;
368         newImmOpnd = nullptr;
369     }
370     void Run(BB &bb, Insn &insn) override;
371     bool CheckCondition(Insn &insn) override;
GetPatternName()372     std::string GetPatternName() override
373     {
374         return "CombineSameArithmeticPattern";
375     }
376 
377 private:
378     std::vector<MOperator> validMops = {MOP_wlsrrri5, MOP_xlsrrri6,  MOP_wasrrri5,  MOP_xasrrri6,  MOP_wlslrri5,
379                                         MOP_xlslrri6, MOP_waddrri12, MOP_xaddrri12, MOP_wsubrri12, MOP_xsubrri12};
380     Insn *prevInsn = nullptr;
381     ImmOperand *newImmOpnd = nullptr;
382 };
383 
384 /*
385  * Specific Extension Elimination, includes sxt[b|h|w] & uxt[b|h|w]. There are  scenes:
386  * 1. PrevInsn is mov
387  * Example 1)
388  *  mov    w0, #imm                    or    mov    w0, #imm
389  *  sxt{}  w0, w0                            uxt{}  w0, w0
390  *  ===> mov w0, #imm                        ===> mov w0, #imm
391  *       mov w0, w0                               mov w0, w0
392  *
393  * Example 2)
394  *  mov    w0, R0
395  *  uxt{}  w0, w0
396  *  ===> mov w0, R0
397  *       mov w0, w0
398  *
399  * Conditions:
400  * 1) #imm is not out of range depend on extention valid bits.
401  * 2) [mov w0, R0] is return value of call and return size is not of range
402  * 3) mov.destOpnd.size = ext.destOpnd.size
403  *
404  *
405  * 2. PrevInsn is ldr[b|h|sb|sh]
406  * Example 1)
407  *  ldrb x1, []
408  *  and  x1, x1, #imm
409  *  ===> ldrb x1, []
410  *       mov  x1, x1
411  *
412  * Example 2)
413  *  ldrb x1, []           or   ldrb x1, []          or   ldrsb x1, []          or   ldrsb x1, []          or
414  *  sxtb x1, x1                uxtb x1, x1               sxtb  x1, x1               uxtb  x1, x1
415  *  ===> ldrsb x1, []          ===> ldrb x1, []          ===> ldrsb x1, []          ===> ldrb x1, []
416  *       mov   x1, x1               mov  x1, x1               mov   x1, x1               mov  x1, x1
417  *
418  *  ldrh x1, []           or   ldrh x1, []          or   ldrsh x1, []          or   ldrsh x1, []          or
419  *  sxth x1, x1                uxth x1, x1               sxth  x1, x1               uxth  x1, x1
420  *  ===> ldrsh x1, []          ===> ldrh x1, []          ===> ldrsh x1, []          ===> ldrb x1, []
421  *       mov   x1, x1               mov  x1, x1               mov   x1, x1               mov  x1, x1
422  *
423  *  ldrsw x1, []          or   ldrsw x1, []
424  *  sxtw  x1, x1               uxtw x1, x1
425  *  ===> ldrsw x1, []          ===> no change
426  *       mov   x1, x1
427  *
428  * Example 3)
429  *  ldrb x1, []           or   ldrb x1, []          or   ldrsb x1, []          or   ldrsb x1, []          or
430  *  sxth x1, x1                uxth x1, x1               sxth  x1, x1               uxth  x1, x1
431  *  ===> ldrb x1, []           ===> ldrb x1, []          ===> ldrsb x1, []          ===> no change
432  *       mov  x1, x1                mov  x1, x1               mov   x1, x1
433  *
434  *  ldrb x1, []           or   ldrh x1, []          or   ldrsb x1, []          or   ldrsh x1, []          or
435  *  sxtw x1, x1                sxtw x1, x1               sxtw  x1, x1               sxtw  x1, x1
436  *  ===> ldrb x1, []           ===> ldrh x1, []          ===> ldrsb x1, []          ===> ldrsh x1, []
437  *       mov  x1, x1                mov  x1, x1               mov   x1, x1               mov   x1, x1
438  *
439  *  ldr  x1, []
440  *  sxtw x1, x1
441  *  ===> ldrsw x1, []
442  *       mov   x1, x1
443  *
444  * Cases:
445  * 1) extension size == load size -> change the load type or eliminate the extension
446  * 2) extension size >  load size -> possibly eliminating the extension
447  *
448  *
449  * 3. PrevInsn is same sxt / uxt
450  * Example 1)
451  *  sxth x1, x2
452  *  sxth x3, x1
453  *  ===> sxth x1, x2
454  *       mov  x3, x1
455  *
456  * Example 2)
457  *  sxtb x1, x2          or    uxtb  w0, w0
458  *  sxth x3, x1                uxth  w0, w0
459  *  ===> sxtb x1, x2           ===> uxtb  w0, w0
460  *       mov  x3, x1                mov   x0, x0
461  *
462  * Conditions:
463  * 1) ext1.destOpnd.size == ext2.destOpnd.size
464  * 2) ext1.destOpnd.regNo == ext2.destOpnd.regNo
465  *    === prop ext1.destOpnd to ext2.srcOpnd, transfer ext2 to mov
466  *
467  * Cases:
468  * 1) ext1 type == ext2 type ((sxth32 & sxth32) || (sxth64 & sxth64) || ...)
469  * 2) ext1 type  < ext2 type ((sxtb32 & sxth32) || (sxtb64 & sxth64) || (sxtb64 & sxtw64) ||
470  *                            (sxth64 & sxtw64) || (uxtb32 & uxth32))
471  */
472 class ElimSpecificExtensionPattern : public CGPeepPattern {
473 public:
ElimSpecificExtensionPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)474     ElimSpecificExtensionPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
475         : CGPeepPattern(cgFunc, currBB, currInsn, info)
476     {
477     }
478     ~ElimSpecificExtensionPattern() override = default;
479     void Run(BB &bb, Insn &insn) override;
480     bool CheckCondition(Insn &insn) override;
GetPatternName()481     std::string GetPatternName() override
482     {
483         return "ElimSpecificExtensionPattern";
484     }
485 
486 protected:
487     enum SpecificExtType : uint8 { EXTUNDEF = 0, SXTB, SXTH, SXTW, UXTB, UXTH, UXTW, SpecificExtTypeSize };
488     enum OptSceneType : uint8 { kSceneUndef = 0, kSceneMov, kSceneLoad, kSceneSameExt };
489     static constexpr uint8 kPrevLoadPatternNum = 6;
490     static constexpr uint8 kPrevLoadMappingNum = 2;
491     static constexpr uint8 kValueTypeNum = 2;
492     static constexpr uint64 kInvalidValue = 0;
493     static constexpr uint8 kSameExtPatternNum = 4;
494     static constexpr uint8 kSameExtMappingNum = 2;
495     uint64 extValueRangeTable[SpecificExtTypeSize][kValueTypeNum] = {
496         /* {minValue, maxValue} */
497         {kInvalidValue, kInvalidValue},      /* UNDEF */
498         {0xFFFFFFFFFFFFFF80, 0x7F},          /* SXTB */
499         {0xFFFFFFFFFFFF8000, 0x7FFF},        /* SXTH */
500         {0xFFFFFFFF80000000, kInvalidValue}, /* SXTW */
501         {0xFFFFFFFFFFFFFF00, kInvalidValue}, /* UXTB */
502         {0xFFFFFFFFFFFF0000, kInvalidValue}, /* UXTH */
503         {kInvalidValue, kInvalidValue}       /* UXTW */
504     };
505     MOperator loadMappingTable[SpecificExtTypeSize][kPrevLoadPatternNum][kPrevLoadMappingNum] = {
506         /* {prevOrigMop, prevNewMop} */
507         {{MOP_undef, MOP_undef},
508          {MOP_undef, MOP_undef},
509          {MOP_undef, MOP_undef},
510          {MOP_undef, MOP_undef},
511          {MOP_undef, MOP_undef},
512          {MOP_undef, MOP_undef}}, /* UNDEF */
513         {{MOP_wldrb, MOP_wldrsb},
514          {MOP_wldrsb, MOP_wldrsb},
515          {MOP_wldr, MOP_wldrsb},
516          {MOP_undef, MOP_undef},
517          {MOP_undef, MOP_undef},
518          {MOP_undef, MOP_undef}}, /* SXTB */
519         {{MOP_wldrh, MOP_wldrsh},
520          {MOP_wldrb, MOP_wldrb},
521          {MOP_wldrsb, MOP_wldrsb},
522          {MOP_wldrsh, MOP_wldrsh},
523          {MOP_undef, MOP_undef},
524          {MOP_undef, MOP_undef}}, /* SXTH */
525         {{MOP_wldrh, MOP_wldrh},
526          {MOP_wldrsh, MOP_wldrsh},
527          {MOP_wldrb, MOP_wldrb},
528          {MOP_wldrsb, MOP_wldrsb},
529          {MOP_wldr, MOP_xldrsw},
530          {MOP_xldrsw, MOP_xldrsw}}, /* SXTW */
531         {{MOP_wldrb, MOP_wldrb},
532          {MOP_wldrsb, MOP_wldrb},
533          {MOP_undef, MOP_undef},
534          {MOP_undef, MOP_undef},
535          {MOP_undef, MOP_undef},
536          {MOP_undef, MOP_undef}}, /* UXTB */
537         {{MOP_wldrh, MOP_wldrh},
538          {MOP_wldrb, MOP_wldrb},
539          {MOP_wldr, MOP_wldrh},
540          {MOP_undef, MOP_undef},
541          {MOP_undef, MOP_undef},
542          {MOP_undef, MOP_undef}}, /* UXTH */
543         {{MOP_wldr, MOP_wldr},
544          {MOP_wldrh, MOP_wldrh},
545          {MOP_wldrb, MOP_wldrb},
546          {MOP_undef, MOP_undef},
547          {MOP_undef, MOP_undef},
548          {MOP_undef, MOP_undef}} /* UXTW */
549     };
550     MOperator sameExtMappingTable[SpecificExtTypeSize][kSameExtPatternNum][kSameExtMappingNum] = {
551         /* {prevMop, currMop} */
552         {{MOP_undef, MOP_undef}, {MOP_undef, MOP_undef}, {MOP_undef, MOP_undef}, {MOP_undef, MOP_undef}}, /* UNDEF */
553         {{MOP_xsxtb32, MOP_xsxtb32},
554          {MOP_xsxtb64, MOP_xsxtb64},
555          {MOP_undef, MOP_undef},
556          {MOP_undef, MOP_undef}}, /* SXTB */
557         {{MOP_xsxtb32, MOP_xsxth32},
558          {MOP_xsxtb64, MOP_xsxth64},
559          {MOP_xsxth32, MOP_xsxth32},
560          {MOP_xsxth64, MOP_xsxth64}}, /* SXTH */
561         {{MOP_xsxtb64, MOP_xsxtw64},
562          {MOP_xsxth64, MOP_xsxtw64},
563          {MOP_xsxtw64, MOP_xsxtw64},
564          {MOP_undef, MOP_undef}},                                                                             /* SXTW */
565         {{MOP_xuxtb32, MOP_xuxtb32}, {MOP_undef, MOP_undef}, {MOP_undef, MOP_undef}, {MOP_undef, MOP_undef}}, /* UXTB */
566         {{MOP_xuxtb32, MOP_xuxth32},
567          {MOP_xuxth32, MOP_xuxth32},
568          {MOP_undef, MOP_undef},
569          {MOP_undef, MOP_undef}},                                                                            /* UXTH */
570         {{MOP_xuxtw64, MOP_xuxtw64}, {MOP_undef, MOP_undef}, {MOP_undef, MOP_undef}, {MOP_undef, MOP_undef}} /* UXTW */
571     };
572 
573 private:
574     void SetSpecificExtType(const Insn &currInsn);
575     void SetOptSceneType();
576     bool IsValidLoadExtPattern(Insn &currInsn, MOperator oldMop, MOperator newMop) const;
577     MOperator SelectNewLoadMopByBitSize(MOperator lowBitMop) const;
578     void ElimExtensionAfterLoad(Insn &currInsn);
579     void ElimExtensionAfterMov(Insn &currInsn);
580     void ElimExtensionAfterSameExt(Insn &currInsn);
581     void ReplaceExtWithMov(Insn &currInsn);
582     Insn *prevInsn = nullptr;
583     SpecificExtType extTypeIdx = EXTUNDEF;
584     OptSceneType sceneType = kSceneUndef;
585     bool is64Bits = false;
586 };
587 
588 /*
589  * We optimize the following pattern in this function:
590  * if w0's valid bits is one
591  * uxtb w0, w0
592  * eor w0, w0, #1
593  * cbz w0, .label
594  * =>
595  * tbnz w0, .label
596  * if there exists uxtb w0, w0 and w0's valid bits is
597  * less than 8, eliminate it.
598  */
599 class OneHoleBranchPattern : public CGPeepPattern {
600 public:
OneHoleBranchPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)601     explicit OneHoleBranchPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
602         : CGPeepPattern(cgFunc, currBB, currInsn, info)
603     {
604     }
605     ~OneHoleBranchPattern() override = default;
606     void Run(BB &bb, Insn &insn) override;
607     bool CheckCondition(Insn &insn) override;
GetPatternName()608     std::string GetPatternName() override
609     {
610         return "OneHoleBranchPattern";
611     }
612 
613 private:
614     void FindNewMop(const BB &bb, const Insn &insn);
615     bool CheckPrePrevInsn();
616     Insn *prevInsn = nullptr;
617     Insn *prePrevInsn = nullptr;
618     MOperator newOp = MOP_undef;
619 };
620 
621 /*
622  * Combine logical shift and orr to [extr wd, wn, wm, #lsb  /  extr xd, xn, xm, #lsb]
623  * Example 1)
624  *  lsr w5, w6, #16
625  *  lsl w4, w7, #16
626  *  orr w5, w5, w4                  --->        (currInsn)
627  *  ===> extr w5, w6, w7, #16
628  *
629  * Example 2)
630  *  lsr w5, w6, #16
631  *  orr w5, w5, w4, LSL #16         --->        (currInsn)
632  *  ===> extr w5, w6, w4, #16
633  *
634  * Example 3)
635  *  lsl w4, w7, #16
636  *  orr w5, w4, w5, LSR #16         --->        (currInsn)
637  *  ===> extr w5, w5, w7, #16
638  *
639  * Conditions:
640  *  1. (def[wn] is lsl) & (def[wm] is lsr)
641  *  2. lsl_imm + lsr_imm == curr type size (32 or 64)
642  *  3. is64bits ? (extr_imm in range [0, 63]) : (extr_imm in range [0, 31])
643  *  4. extr_imm = lsr_imm
644  */
645 class LogicShiftAndOrrToExtrPattern : public CGPeepPattern {
646 public:
LogicShiftAndOrrToExtrPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)647     LogicShiftAndOrrToExtrPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
648         : CGPeepPattern(cgFunc, currBB, currInsn, info)
649     {
650     }
651     ~LogicShiftAndOrrToExtrPattern() override = default;
652     void Run(BB &bb, Insn &insn) override;
653     bool CheckCondition(Insn &insn) override;
GetPatternName()654     std::string GetPatternName() override
655     {
656         return "LogicShiftAndOrrToExtrPattern";
657     }
658 
659 private:
660     Insn *prevLsrInsn = nullptr;
661     Insn *prevLslInsn = nullptr;
662     int64 shiftValue = 0;
663     bool is64Bits = false;
664 };
665 
666 /*
667  * Simplify Mul and Basic Arithmetic. There are three scenes:
668  * 1. currInsn is add:
669  * Example 1)
670  *  mul   x1, x1, x2           or     mul   x0, x1, x2
671  *  add   x0, x0, x1                  add   x0, x0, x1
672  *  ===> madd x0, x1, x2, x0          ===> madd x0, x1, x2, x1
673  *
674  * Example 2)
675  *  fmul  d1, d1, d2           or     fmul  d0, d1, d2
676  *  fadd  d0, d0, d1                  fadd  d0, d0, d1
677  *  ===> fmadd d0, d1, d2, d0         ===> fmadd d0, d1, d2, d1
678  *
679  * cases: addInsn second opnd || addInsn third opnd
680  *
681  *
682  * 2. currInsn is sub:
683  * Example 1)                         Example 2)
684  *  mul   x1, x1, x2                   fmul  d1, d1, d2
685  *  sub   x0, x0, x1                   fsub  d0, d0, d1
686  *  ===> msub x0, x1, x2, x0           ===> fmsub d0, d1, d2, d0
687  *
688  * cases: subInsn third opnd
689  *
690  * 3. currInsn is neg:
691  * Example 1)                         Example 2)
692  *  mul   x1, x1, x2                   fmul     d1, d1, d2
693  *  neg   x0, x1                       fneg     d0, d1
694  *  ===> mneg x0, x1, x2               ===> fnmul d0, d1, d2
695  *
696  * cases: negInsn second opnd
697  */
698 class SimplifyMulArithmeticPattern : public CGPeepPattern {
699 public:
SimplifyMulArithmeticPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)700     SimplifyMulArithmeticPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
701         : CGPeepPattern(cgFunc, currBB, currInsn, info)
702     {
703     }
704     ~SimplifyMulArithmeticPattern() override = default;
705     void Run(BB &bb, Insn &insn) override;
706     bool CheckCondition(Insn &insn) override;
GetPatternName()707     std::string GetPatternName() override
708     {
709         return "SimplifyMulArithmeticPattern";
710     }
711 
712 protected:
713     enum ArithmeticType : uint8 { kUndef = 0, kAdd, kFAdd, kSub, kFSub, kNeg, kFNeg, kArithmeticTypeSize };
714     static constexpr uint8 newMopNum = 2;
715     MOperator curMop2NewMopTable[kArithmeticTypeSize][newMopNum] = {
716         /* {32bit_mop, 64bit_mop} */
717         {MOP_undef, MOP_undef},         /* kUndef  */
718         {MOP_wmaddrrrr, MOP_xmaddrrrr}, /* kAdd    */
719         {MOP_smadd, MOP_dmadd},         /* kFAdd   */
720         {MOP_wmsubrrrr, MOP_xmsubrrrr}, /* kSub    */
721         {MOP_smsub, MOP_dmsub},         /* kFSub   */
722         {MOP_wmnegrrr, MOP_xmnegrrr},   /* kNeg    */
723         {MOP_snmul, MOP_dnmul}          /* kFNeg   */
724     };
725 
726 private:
727     void SetArithType(const Insn &currInsn);
728     void DoOptimize(BB &currBB, Insn &currInsn);
729     ArithmeticType arithType = kUndef;
730     int32 validOpndIdx = -1;
731     Insn *prevInsn = nullptr;
732     bool isFloat = false;
733 };
734 
735 /*
736  * Example 1)
737  *  lsr w0, w1, #6
738  *  and w0, w0, #1                 --->        (currInsn)
739  *  ===> ubfx w0, w1, #6, #1
740  *
741  * Conditions:
742  * 1. and_imm value is (1 << n -1)
743  * 2. is64bits ? (ubfx_imm_lsb in range [0, 63]) : (ubfx_imm_lsb in range [0, 31])
744  * 3. is64bits ? ((ubfx_imm_lsb + ubfx_imm_width) in range [1, 32]) : ((ubfx_imm_lsb + ubfx_imm_width) in range [1, 64])
745  */
746 class LsrAndToUbfxPattern : public CGPeepPattern {
747 public:
LsrAndToUbfxPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)748     LsrAndToUbfxPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
749         : CGPeepPattern(cgFunc, currBB, currInsn, info)
750     {
751     }
752     ~LsrAndToUbfxPattern() override = default;
753     void Run(BB &bb, Insn &insn) override;
754     bool CheckCondition(Insn &insn) override;
GetPatternName()755     std::string GetPatternName() override
756     {
757         return "LsrAndToUbfxPattern";
758     }
759 
760 private:
761     Insn *prevInsn = nullptr;
762 };
763 
764 /*
765  * Optimize the following patterns:
766  *  orr  w21, w0, #0  ====> mov  w21, w0
767  *  orr  w21, #0, w0  ====> mov  w21, w0
768  */
769 class OrrToMovPattern : public CGPeepPattern {
770 public:
OrrToMovPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)771     explicit OrrToMovPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
772         : CGPeepPattern(cgFunc, currBB, currInsn, info)
773     {
774     }
775     ~OrrToMovPattern() override = default;
776     void Run(BB &bb, Insn &insn) override;
777     bool CheckCondition(Insn &insn) override;
GetPatternName()778     std::string GetPatternName() override
779     {
780         return "OrrToMovPattern";
781     }
782 
783 private:
784     MOperator newMop = MOP_undef;
785     RegOperand *reg2 = nullptr;
786 };
787 
788 /*
789  * Optimize the following patterns:
790  * ubfx  x201, x202, #0, #32
791  * ====>
792  * uxtw x201, w202
793  */
794 class UbfxToUxtwPattern : public CGPeepPattern {
795 public:
UbfxToUxtwPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)796     UbfxToUxtwPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
797     ~UbfxToUxtwPattern() override = default;
798     void Run(BB &bb, Insn &insn) override;
799     bool CheckCondition(Insn &insn) override;
GetPatternName()800     std::string GetPatternName() override
801     {
802         return "UbfxToUxtwPattern";
803     }
804 };
805 
806 /*
807  * Optimize the following patterns:
808  * ubfx  w0, w0, #2, #1
809  * cbz   w0, .L.3434__292    ====>    tbz w0, #2, .L.3434__292
810  * -------------------------------
811  * ubfx  w0, w0, #2, #1
812  * cnbz   w0, .L.3434__292    ====>    tbnz w0, #2, .L.3434__292
813  * -------------------------------
814  * ubfx  x0, x0, #2, #1
815  * cbz   x0, .L.3434__292    ====>    tbz x0, #2, .L.3434__292
816  * -------------------------------
817  * ubfx  x0, x0, #2, #1
818  * cnbz  x0, .L.3434__292    ====>    tbnz x0, #2, .L.3434__292
819  */
820 class UbfxAndCbzToTbzPattern : public CGPeepPattern {
821 public:
UbfxAndCbzToTbzPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn,CGSSAInfo & info)822     UbfxAndCbzToTbzPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn, CGSSAInfo &info)
823         : CGPeepPattern(cgFunc, currBB, currInsn, info)
824     {
825     }
~UbfxAndCbzToTbzPattern()826     ~UbfxAndCbzToTbzPattern() override
827     {
828         useInsn = nullptr;
829     }
830     void Run(BB &bb, Insn &insn) override;
831     bool CheckCondition(Insn &insn) override;
GetPatternName()832     std::string GetPatternName() override
833     {
834         return "UbfxAndCbzToTbzPattern";
835     }
836 
837 private:
838     Insn *useInsn = nullptr;
839     MOperator newMop = MOP_undef;
840 };
841 
842 /*
843  * Looking for identical mem insn to eliminate.
844  * If two back-to-back is:
845  * 1. str + str
846  * 2. str + ldr
847  * And the [MEM] is pattern of [base + offset]
848  * 1. The [MEM] operand is exactly same then first
849  *    str can be eliminate.
850  * 2. The [MEM] operand is exactly same and src opnd
851  *    of str is same as the dest opnd of ldr then
852  *    ldr can be eliminate
853  */
854 class RemoveIdenticalLoadAndStorePattern : public CGPeepPattern {
855 public:
RemoveIdenticalLoadAndStorePattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)856     RemoveIdenticalLoadAndStorePattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn)
857         : CGPeepPattern(cgFunc, currBB, currInsn)
858     {
859     }
~RemoveIdenticalLoadAndStorePattern()860     ~RemoveIdenticalLoadAndStorePattern() override
861     {
862         nextInsn = nullptr;
863     }
864     void Run(BB &bb, Insn &insn) override;
865     bool CheckCondition(Insn &insn) override;
GetPatternName()866     std::string GetPatternName() override
867     {
868         return "RemoveIdenticalLoadAndStorePattern";
869     }
870 
871 private:
872     bool IsMemOperandsIdentical(const Insn &insn1, const Insn &insn2) const;
873     Insn *nextInsn = nullptr;
874 };
875 
876 /* ======== CGPeepPattern End ======== */
877 /*
878  * Looking for identical mem insn to eliminate.
879  * If two back-to-back is:
880  * 1. str + str
881  * 2. str + ldr
882  * And the [MEM] is pattern of [base + offset]
883  * 1. The [MEM] operand is exactly same then first
884  *    str can be eliminate.
885  * 2. The [MEM] operand is exactly same and src opnd
886  *    of str is same as the dest opnd of ldr then
887  *    ldr can be eliminate
888  */
889 class RemoveIdenticalLoadAndStoreAArch64 : public PeepPattern {
890 public:
RemoveIdenticalLoadAndStoreAArch64(CGFunc & cgFunc)891     explicit RemoveIdenticalLoadAndStoreAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
892     ~RemoveIdenticalLoadAndStoreAArch64() override = default;
893     void Run(BB &bb, Insn &insn) override;
894 
895 private:
896     bool IsMemOperandsIdentical(const Insn &insn1, const Insn &insn2) const;
897 };
898 
899 /* Remove redundant mov which src and dest opnd is exactly same */
900 class RemoveMovingtoSameRegPattern : public CGPeepPattern {
901 public:
RemoveMovingtoSameRegPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)902     RemoveMovingtoSameRegPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn)
903     {
904     }
905     ~RemoveMovingtoSameRegPattern() override = default;
906     void Run(BB &bb, Insn &insn) override;
907     bool CheckCondition(Insn &insn) override;
GetPatternName()908     std::string GetPatternName() override
909     {
910         return "RemoveMovingtoSameRegPattern";
911     }
912 };
913 
914 /* Remove redundant mov which src and dest opnd is exactly same */
915 class RemoveMovingtoSameRegAArch64 : public PeepPattern {
916 public:
RemoveMovingtoSameRegAArch64(CGFunc & cgFunc)917     explicit RemoveMovingtoSameRegAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
918     ~RemoveMovingtoSameRegAArch64() override = default;
919     void Run(BB &bb, Insn &insn) override;
920 };
921 
922 /*
923  * Combining 2 STRs into 1 stp or 2 LDRs into 1 ldp, when they are
924  * back to back and the [MEM] they access is conjointed.
925  */
926 class CombineContiLoadAndStorePattern : public CGPeepPattern {
927 public:
CombineContiLoadAndStorePattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)928     CombineContiLoadAndStorePattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn)
929         : CGPeepPattern(cgFunc, currBB, currInsn)
930     {
931         doAggressiveCombine = cgFunc.GetMirModule().IsCModule();
932     }
~CombineContiLoadAndStorePattern()933     ~CombineContiLoadAndStorePattern() override
934     {
935         memOpnd = nullptr;
936     }
937     void Run(BB &bb, Insn &insn) override;
938     bool CheckCondition(Insn &insn) override;
GetPatternName()939     std::string GetPatternName() override
940     {
941         return "CombineContiLoadAndStorePattern";
942     }
943 
944 private:
945     std::vector<Insn *> FindPrevStrLdr(Insn &insn, regno_t destRegNO, regno_t memBaseRegNO, int64 baseOfst);
946     /*
947      * avoid the following situation:
948      * str x2, [x19, #8]
949      * mov x0, x19
950      * bl foo (change memory)
951      * str x21, [x19, #16]
952      */
953     bool IsRegNotSameMemUseInInsn(const Insn &insn, regno_t regNO, bool isStore, int64 baseOfst) const;
954     void RemoveInsnAndKeepComment(BB &bb, Insn &insn, Insn &prevInsn) const;
955     MOperator GetMopHigherByte(MOperator mop) const;
956     bool SplitOfstWithAddToCombine(const Insn &curInsn, Insn &combineInsn, const MemOperand &memOperand) const;
957     Insn *FindValidSplitAddInsn(Insn &curInsn, RegOperand &baseOpnd) const;
958     bool PlaceSplitAddInsn(const Insn &curInsn, Insn &combineInsn, const MemOperand &memOpnd, RegOperand &baseOpnd,
959                            uint32 bitLen) const;
960     bool doAggressiveCombine = false;
961     MemOperand *memOpnd = nullptr;
962 };
963 
964 /*
965  * mov  x0, x1
966  * ldr	x0, [x0]        --> ldr x0, [x1]
967  *
968  * add	x0, x0, #64
969  * ldr	x0, [x0]        --> ldr x0, [x0, #64]
970  *
971  * add	x0, x7, x0
972  * ldr	x11, [x0]       --> ldr x11, [x0, x7]
973  *
974  * lsl	x1, x4, #3
975  * add	x0, x0, x1
976  * ldr	d1, [x0]        --> ldr d1, [x0, x4, lsl #3]
977  */
978 class EnhanceStrLdrAArch64 : public PeepPattern {
979 public:
EnhanceStrLdrAArch64(CGFunc & cgFunc)980     explicit EnhanceStrLdrAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
981     ~EnhanceStrLdrAArch64() override = default;
982     void Run(BB &bb, Insn &insn) override;
983 
984 private:
985     ImmOperand *GetInsnAddOrSubNewOffset(Insn &insn, ImmOperand &offset);
986     void OptimizeAddrBOI(Insn &insn, MemOperand &memOpnd, Insn &prevInsn);
987     void OptimizeAddrBOrX(Insn &insn, MemOperand &memOpnd, Insn &prevInsn);
988     void OptimizeAddrBOrXShiftExtend(Insn &insn, MemOperand &memOpnd, Insn &shiftExtendInsn);
989     void OptimizeWithAddrrrs(Insn &insn, MemOperand &memOpnd, Insn &addInsn);
990     bool CheckOperandIsDeadFromInsn(const RegOperand &regOpnd, Insn &insn);
991 };
992 
993 /* Eliminate the sxt[b|h|w] w0, w0;, when w0 is satisify following:
994  * i)  mov w0, #imm (#imm is not out of range)
995  * ii) ldrs[b|h] w0, [MEM]
996  */
997 class EliminateSpecifcSXTAArch64 : public PeepPattern {
998 public:
EliminateSpecifcSXTAArch64(CGFunc & cgFunc)999     explicit EliminateSpecifcSXTAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1000     ~EliminateSpecifcSXTAArch64() override = default;
1001     void Run(BB &bb, Insn &insn) override;
1002 };
1003 
1004 /* Eliminate the uxt[b|h|w] w0, w0;when w0 is satisify following:
1005  * i)  mov w0, #imm (#imm is not out of range)
1006  * ii) mov w0, R0(Is return value of call and return size is not of range)
1007  * iii)w0 is defined and used by special load insn and uxt[] pattern
1008  */
1009 class EliminateSpecifcUXTAArch64 : public PeepPattern {
1010 public:
EliminateSpecifcUXTAArch64(CGFunc & cgFunc)1011     explicit EliminateSpecifcUXTAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1012     ~EliminateSpecifcUXTAArch64() override = default;
1013     void Run(BB &bb, Insn &insn) override;
1014 };
1015 
1016 /* fmov ireg1 <- freg1   previous insn
1017  * fmov ireg2 <- freg1   current insn
1018  * use  ireg2            may or may not be present
1019  * =>
1020  * fmov ireg1 <- freg1   previous insn
1021  * mov  ireg2 <- ireg1   current insn
1022  * use  ireg1            may or may not be present
1023  */
1024 class FmovRegPattern : public CGPeepPattern {
1025 public:
FmovRegPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1026     FmovRegPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~FmovRegPattern()1027     ~FmovRegPattern() override
1028     {
1029         prevInsn = nullptr;
1030         nextInsn = nullptr;
1031     }
1032     void Run(BB &bb, Insn &insn) override;
1033     bool CheckCondition(Insn &insn) override;
GetPatternName()1034     std::string GetPatternName() override
1035     {
1036         return "FmovRegPattern";
1037     }
1038 
1039 private:
1040     Insn *prevInsn = nullptr;
1041     Insn *nextInsn = nullptr;
1042 };
1043 
1044 /* sbfx ireg1, ireg2, 0, 32
1045  * use  ireg1.32
1046  * =>
1047  * sbfx ireg1, ireg2, 0, 32
1048  * use  ireg2.32
1049  */
1050 class SbfxOptPattern : public CGPeepPattern {
1051 public:
SbfxOptPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1052     SbfxOptPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~SbfxOptPattern()1053     ~SbfxOptPattern() override
1054     {
1055         nextInsn = nullptr;
1056     }
1057     void Run(BB &bb, Insn &insn) override;
1058     bool CheckCondition(Insn &insn) override;
GetPatternName()1059     std::string GetPatternName() override
1060     {
1061         return "SbfxOptPattern";
1062     }
1063 
1064 private:
1065     Insn *nextInsn = nullptr;
1066     bool toRemove = false;
1067     std::vector<uint32> cands;
1068 };
1069 
1070 /* cbnz x0, labelA
1071  * mov x0, 0
1072  * b  return-bb
1073  * labelA:
1074  * =>
1075  * cbz x0, return-bb
1076  * labelA:
1077  */
1078 class CbnzToCbzPattern : public CGPeepPattern {
1079 public:
CbnzToCbzPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1080     CbnzToCbzPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~CbnzToCbzPattern()1081     ~CbnzToCbzPattern() override
1082     {
1083         nextBB = nullptr;
1084         movInsn = nullptr;
1085         brInsn = nullptr;
1086     }
1087     void Run(BB &bb, Insn &insn) override;
1088     bool CheckCondition(Insn &insn) override;
GetPatternName()1089     std::string GetPatternName() override
1090     {
1091         return "CbnzToCbzPattern";
1092     }
1093 
1094 private:
1095     BB *nextBB = nullptr;
1096     Insn *movInsn = nullptr;
1097     Insn *brInsn = nullptr;
1098 };
1099 
1100 /* i.   cset    w0, EQ
1101  *      cbnz    w0, .label    ===> beq .label
1102  *
1103  * ii.  cset    w0, EQ
1104  *      cbz    w0, .label     ===> bne .label
1105  *
1106  * iii. cset    w0, NE
1107  *      cbnz    w0, .label    ===> bne .label
1108  *
1109  * iiii.cset    w0, NE
1110  *      cbz    w0, .label     ===> beq .label
1111  * ... ...
1112  */
1113 class CsetCbzToBeqOptAArch64 : public PeepPattern {
1114 public:
CsetCbzToBeqOptAArch64(CGFunc & cgFunc)1115     explicit CsetCbzToBeqOptAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1116     ~CsetCbzToBeqOptAArch64() override = default;
1117     void Run(BB &bb, Insn &insn) override;
1118     MOperator SelectMOperator(ConditionCode condCode, bool inverse) const;
1119 };
1120 
1121 /* When exist load after load or load after store, and [MEM] is
1122  * totally same. Then optimize them.
1123  */
1124 class ContiLDRorSTRToSameMEMPattern : public CGPeepPattern {
1125 public:
ContiLDRorSTRToSameMEMPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1126     ContiLDRorSTRToSameMEMPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn)
1127     {
1128     }
~ContiLDRorSTRToSameMEMPattern()1129     ~ContiLDRorSTRToSameMEMPattern() override
1130     {
1131         prevInsn = nullptr;
1132     }
1133     void Run(BB &bb, Insn &insn) override;
1134     bool CheckCondition(Insn &insn) override;
GetPatternName()1135     std::string GetPatternName() override
1136     {
1137         return "ContiLDRorSTRToSameMEMPattern";
1138     }
1139 
1140 private:
1141     Insn *prevInsn = nullptr;
1142     bool loadAfterStore = false;
1143     bool loadAfterLoad = false;
1144 };
1145 
1146 /*
1147  *  Remove following patterns:
1148  *  mov     x1, x0
1149  *  bl      MCC_IncDecRef_NaiveRCFast
1150  */
1151 class RemoveIncDecRefPattern : public CGPeepPattern {
1152 public:
RemoveIncDecRefPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1153     RemoveIncDecRefPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~RemoveIncDecRefPattern()1154     ~RemoveIncDecRefPattern() override
1155     {
1156         prevInsn = nullptr;
1157     }
1158     void Run(BB &bb, Insn &insn) override;
1159     bool CheckCondition(Insn &insn) override;
GetPatternName()1160     std::string GetPatternName() override
1161     {
1162         return "RemoveIncDecRefPattern";
1163     }
1164 
1165 private:
1166     Insn *prevInsn = nullptr;
1167 };
1168 
1169 /*
1170  * When GCONLY is enabled, the read barriers can be inlined.
1171  * we optimize it with the following pattern:
1172  * #if USE_32BIT_REF
1173  *   bl MCC_LoadRefField             ->  ldr  w0, [x1]
1174  *   bl MCC_LoadVolatileField        ->  ldar w0, [x1]
1175  *   bl MCC_LoadRefStatic            ->  ldr  w0, [x0]
1176  *   bl MCC_LoadVolatileStaticField  ->  ldar w0, [x0]
1177  *   bl MCC_Dummy                    ->  omitted
1178  * #else
1179  *   bl MCC_LoadRefField             ->  ldr  x0, [x1]
1180  *   bl MCC_LoadVolatileField        ->  ldar x0, [x1]
1181  *   bl MCC_LoadRefStatic            ->  ldr  x0, [x0]
1182  *   bl MCC_LoadVolatileStaticField  ->  ldar x0, [x0]
1183  *   bl MCC_Dummy                    ->  omitted
1184  * #endif
1185  *
1186  * if we encounter a tail call optimized read barrier call,
1187  * such as:
1188  *   b MCC_LoadRefField
1189  * a return instruction will be added just after the load:
1190  *   ldr w0, [x1]
1191  *   ret
1192  */
1193 class InlineReadBarriersPattern : public CGPeepPattern {
1194 public:
InlineReadBarriersPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1195     InlineReadBarriersPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
1196     ~InlineReadBarriersPattern() override = default;
1197     void Run(BB &bb, Insn &insn) override;
1198     bool CheckCondition(Insn &insn) override;
GetPatternName()1199     std::string GetPatternName() override
1200     {
1201         return "InlineReadBarriersPattern";
1202     }
1203 };
1204 
1205 /*
1206  *    mov     w1, #34464
1207  *    movk    w1, #1,  LSL #16
1208  *    sdiv    w2, w0, w1
1209  *  ========>
1210  *    mov     w1, #34464         // may deleted if w1 not live anymore.
1211  *    movk    w1, #1,  LSL #16   // may deleted if w1 not live anymore.
1212  *    mov     w16, #0x588f
1213  *    movk    w16, #0x4f8b, LSL #16
1214  *    smull   x16, w0, w16
1215  *    asr     x16, x16, #32
1216  *    add     x16, x16, w0, SXTW
1217  *    asr     x16, x16, #17
1218  *    add     x2, x16, x0, LSR #31
1219  */
1220 class ReplaceDivToMultiPattern : public CGPeepPattern {
1221 public:
ReplaceDivToMultiPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1222     ReplaceDivToMultiPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~ReplaceDivToMultiPattern()1223     ~ReplaceDivToMultiPattern() override
1224     {
1225         prevInsn = nullptr;
1226         prePrevInsn = nullptr;
1227     }
1228     void Run(BB &bb, Insn &insn) override;
1229     bool CheckCondition(Insn &insn) override;
GetPatternName()1230     std::string GetPatternName() override
1231     {
1232         return "ReplaceDivToMultiPattern";
1233     }
1234 
1235 private:
1236     Insn *prevInsn = nullptr;
1237     Insn *prePrevInsn = nullptr;
1238 };
1239 
1240 /*
1241  * Optimize the following patterns:
1242  *  and  w0, w0, #imm  ====> tst  w0, #imm
1243  *  cmp  w0, #0              beq/bne  .label
1244  *  beq/bne  .label
1245  *
1246  *  and  x0, x0, #imm  ====> tst  x0, #imm
1247  *  cmp  x0, #0              beq/bne  .label
1248  *  beq/bne  .label
1249  */
1250 class AndCmpBranchesToTstAArch64 : public PeepPattern {
1251 public:
AndCmpBranchesToTstAArch64(CGFunc & cgFunc)1252     explicit AndCmpBranchesToTstAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1253     ~AndCmpBranchesToTstAArch64() override = default;
1254     void Run(BB &bb, Insn &insn) override;
1255 };
1256 
1257 /*
1258  * Optimize the following patterns:
1259  *  and  w0, w0, #imm  ====> tst  w0, #imm
1260  *  cbz/cbnz  .label         beq/bne  .label
1261  */
1262 class AndCbzBranchesToTstAArch64 : public PeepPattern {
1263 public:
AndCbzBranchesToTstAArch64(CGFunc & cgFunc)1264     explicit AndCbzBranchesToTstAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1265     ~AndCbzBranchesToTstAArch64() override = default;
1266     void Run(BB &bb, Insn &insn) override;
1267 };
1268 
1269 /*
1270  * Optimize the following patterns:
1271  *  and  w0, w0, #1  ====> and  w0, w0, #1
1272  *  cmp  w0, #1
1273  *  cset w0, EQ
1274  *
1275  *  and  w0, w0, #1  ====> and  w0, w0, #1
1276  *  cmp  w0, #0
1277  *  cset w0, NE
1278  *  ---------------------------------------------------
1279  *  and  w0, w0, #imm  ====> ubfx  w0, w0, pos, size
1280  *  cmp  w0, #imm
1281  *  cset w0, EQ
1282  *
1283  *  and  w0, w0, #imm  ====> ubfx  w0, w0, pos, size
1284  *  cmp  w0, #0
1285  *  cset w0, NE
1286  *  conditions:
1287  *  imm is pos power of 2
1288  *
1289  *  ---------------------------------------------------
1290  *  and  w0, w0, #1  ====> and  wn, w0, #1
1291  *  cmp  w0, #1
1292  *  cset wn, EQ        # wn != w0 && w0 is not live after cset
1293  *
1294  *  and  w0, w0, #1  ====> and  wn, w0, #1
1295  *  cmp  w0, #0
1296  *  cset wn, NE        # wn != w0 && w0 is not live after cset
1297  *  ---------------------------------------------------
1298  *  and  w0, w0, #imm  ====> ubfx  wn, w0, pos, size
1299  *  cmp  w0, #imm
1300  *  cset wn, EQ        # wn != w0 && w0 is not live after cset
1301  *
1302  *  and  w0, w0, #imm  ====> ubfx  wn, w0, pos, size
1303  *  cmp  w0, #0
1304  *  cset wn, NE        # wn != w0 && w0 is not live after cset
1305  *  conditions:
1306  *  imm is pos power of 2 and w0 is not live after cset
1307  */
1308 class AndCmpBranchesToCsetAArch64 : public PeepPattern {
1309 public:
AndCmpBranchesToCsetAArch64(CGFunc & cgFunc)1310     explicit AndCmpBranchesToCsetAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1311     ~AndCmpBranchesToCsetAArch64() override = default;
1312     void Run(BB &bb, Insn &insn) override;
1313 
1314 private:
1315     Insn *FindPreviousCmp(Insn &insn) const;
1316 };
1317 /*
1318  * We optimize the following pattern in this function:
1319  * cmp w[0-9]*, wzr  ====> tbz w[0-9]*, #31, .label
1320  * bge .label
1321  *
1322  * cmp wzr, w[0-9]*  ====> tbz w[0-9]*, #31, .label
1323  * ble .label
1324  *
1325  * cmp w[0-9]*,wzr   ====> tbnz w[0-9]*, #31, .label
1326  * blt .label
1327  *
1328  * cmp wzr, w[0-9]*  ====> tbnz w[0-9]*, #31, .label
1329  * bgt .label
1330  *
1331  * cmp w[0-9]*, #0   ====> tbz w[0-9]*, #31, .label
1332  * bge .label
1333  *
1334  * cmp w[0-9]*, #0   ====> tbnz w[0-9]*, #31, .label
1335  * blt .label
1336  */
1337 class ZeroCmpBranchesAArch64 : public PeepPattern {
1338 public:
ZeroCmpBranchesAArch64(CGFunc & cgFunc)1339     explicit ZeroCmpBranchesAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1340     ~ZeroCmpBranchesAArch64() override = default;
1341     void Run(BB &bb, Insn &insn) override;
1342 };
1343 
1344 /*
1345  * Look for duplicate or overlapping zero or sign extensions.
1346  * Examples:
1347  *   sxth x1, x2   ====> sxth x1, x2
1348  *   sxth x3, x1         mov  x3, x1
1349  *
1350  *   sxtb x1, x2   ====> sxtb x1, x2
1351  *   sxth x3, x1         mov  x3, x1
1352  */
1353 class ElimDuplicateExtensionAArch64 : public PeepPattern {
1354 public:
ElimDuplicateExtensionAArch64(CGFunc & cgFunc)1355     explicit ElimDuplicateExtensionAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1356     ~ElimDuplicateExtensionAArch64() override = default;
1357     void Run(BB &bb, Insn &insn) override;
1358 };
1359 
1360 /*
1361  *  cmp  w0, #0
1362  *  cset w1, NE --> mov w1, w0
1363  *
1364  *  cmp  w0, #0
1365  *  cset w1, EQ --> eor w1, w0, 1
1366  *
1367  *  cmp  w0, #1
1368  *  cset w1, NE --> eor w1, w0, 1
1369  *
1370  *  cmp  w0, #1
1371  *  cset w1, EQ --> mov w1, w0
1372  *
1373  *  cmp w0,  #0
1374  *  cset w0, NE -->null
1375  *
1376  *  cmp w0, #1
1377  *  cset w0, EQ -->null
1378  *
1379  *  condition:
1380  *    1. the first operand of cmp instruction must has only one valid bit
1381  *    2. the second operand of cmp instruction must be 0 or 1
1382  *    3. flag register of cmp isntruction must not be used later
1383  */
1384 class CmpCsetAArch64 : public PeepPattern {
1385 public:
CmpCsetAArch64(CGFunc & cgFunc)1386     explicit CmpCsetAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1387     ~CmpCsetAArch64() override = default;
1388     void Run(BB &bb, Insn &insn) override;
1389 
1390 private:
1391     bool CheckOpndDefPoints(Insn &checkInsn, int opndIdx);
1392     const Insn *DefInsnOfOperandInBB(const Insn &startInsn, const Insn &checkInsn, int opndIdx) const;
1393     bool OpndDefByOneValidBit(const Insn &defInsn) const;
1394     bool FlagUsedLaterInCurBB(const BB &bb, Insn &startInsn) const;
1395 };
1396 
1397 /*
1398  *  add     x0, x1, x0
1399  *  ldr     x2, [x0]
1400  *  ==>
1401  *  ldr     x2, [x1, x0]
1402  */
1403 class ComplexMemOperandAddAArch64 : public PeepPattern {
1404 public:
ComplexMemOperandAddAArch64(CGFunc & cgFunc)1405     explicit ComplexMemOperandAddAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1406     ~ComplexMemOperandAddAArch64() override = default;
1407     void Run(BB &bb, Insn &insn) override;
1408 
1409 private:
1410     bool IsExpandBaseOpnd(const Insn &insn, const Insn &prevInsn) const;
1411 };
1412 
1413 /*
1414  * cbnz w0, @label
1415  * ....
1416  * mov  w0, #0 (elseBB)        -->this instruction can be deleted
1417  *
1418  * cbz  w0, @label
1419  * ....
1420  * mov  w0, #0 (ifBB)          -->this instruction can be deleted
1421  *
1422  * condition:
1423  *  1.there is not predefine points of w0 in elseBB(ifBB)
1424  *  2.the first opearnd of cbnz insn is same as the first Operand of mov insn
1425  *  3.w0 is defined by move 0
1426  *  4.all preds of elseBB(ifBB) end with cbnz or cbz
1427  *
1428  *  NOTE: if there are multiple preds and there is not define point of w0 in one pred,
1429  *        (mov w0, 0) can't be deleted, avoiding use before def.
1430  */
1431 class DeleteMovAfterCbzOrCbnzAArch64 : public PeepPattern {
1432 public:
DeleteMovAfterCbzOrCbnzAArch64(CGFunc & cgFunc)1433     explicit DeleteMovAfterCbzOrCbnzAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc)
1434     {
1435         cgcfg = cgFunc.GetTheCFG();
1436         cgcfg->InitInsnVisitor(cgFunc);
1437     }
1438     ~DeleteMovAfterCbzOrCbnzAArch64() override = default;
1439     void Run(BB &bb, Insn &insn) override;
1440 
1441 private:
1442     bool PredBBCheck(BB &bb, bool checkCbz, const Operand &opnd) const;
1443     bool OpndDefByMovZero(const Insn &insn) const;
1444     bool NoPreDefine(Insn &testInsn) const;
1445     void ProcessBBHandle(BB *processBB, const BB &bb, const Insn &insn) const;
1446     CGCFG *cgcfg;
1447 };
1448 
1449 /*
1450  * We optimize the following pattern in this function:
1451  * if w0's valid bits is one
1452  * uxtb w0, w0
1453  * eor w0, w0, #1
1454  * cbz w0, .label
1455  * =>
1456  * tbnz w0, .label
1457  * &&
1458  * if there exists uxtb w0, w0 and w0's valid bits is
1459  * less than 8, eliminate it.
1460  */
1461 class OneHoleBranchesPreAArch64 : public PeepPattern {
1462 public:
OneHoleBranchesPreAArch64(CGFunc & cgFunc)1463     explicit OneHoleBranchesPreAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1464     ~OneHoleBranchesPreAArch64() override = default;
1465     void Run(BB &bb, Insn &insn) override;
1466 
1467 private:
1468     MOperator FindNewMop(const BB &bb, const Insn &insn) const;
1469 };
1470 
1471 /*
1472  * We optimize the following pattern in this function:
1473  * movz x0, #11544, LSL #0
1474  * movk x0, #21572, LSL #16
1475  * movk x0, #8699, LSL #32
1476  * movk x0, #16393, LSL #48
1477  * =>
1478  * ldr x0, label_of_constant_1
1479  */
1480 class LoadFloatPointPattern : public CGPeepPattern {
1481 public:
LoadFloatPointPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1482     LoadFloatPointPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
1483     ~LoadFloatPointPattern() override = default;
1484     void Run(BB &bb, Insn &insn) override;
1485     bool CheckCondition(Insn &insn) override;
GetPatternName()1486     std::string GetPatternName() override
1487     {
1488         return "LoadFloatPointPattern";
1489     }
1490 
1491 private:
1492     bool FindLoadFloatPoint(Insn &insn);
1493     bool IsPatternMatch();
1494     std::vector<Insn *> optInsn;
1495 };
1496 
1497 /*
1498  * Optimize the following patterns:
1499  *  orr  w21, w0, #0  ====> mov  w21, w0
1500  *  orr  w21, #0, w0  ====> mov  w21, w0
1501  */
1502 class ReplaceOrrToMovAArch64 : public PeepPattern {
1503 public:
ReplaceOrrToMovAArch64(CGFunc & cgFunc)1504     explicit ReplaceOrrToMovAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1505     ~ReplaceOrrToMovAArch64() override = default;
1506     void Run(BB &bb, Insn &insn) override;
1507 };
1508 
1509 /*
1510  * Optimize the following patterns:
1511  *  ldr  w0, [x21,#68]        ldr  w0, [x21,#68]
1512  *  mov  w1, #-1              mov  w1, #-1
1513  *  cmp  w0, w1     ====>     cmn  w0, #-1
1514  */
1515 class ReplaceCmpToCmnAArch64 : public PeepPattern {
1516 public:
ReplaceCmpToCmnAArch64(CGFunc & cgFunc)1517     explicit ReplaceCmpToCmnAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1518     ~ReplaceCmpToCmnAArch64() override = default;
1519     void Run(BB &bb, Insn &insn) override;
1520 };
1521 
1522 /*
1523  * Remove following patterns:
1524  *   mov x0, XX
1525  *   mov x1, XX
1526  *    bl  MCC_IncDecRef_NaiveRCFast
1527  */
1528 class RemoveIncRefPattern : public CGPeepPattern {
1529 public:
RemoveIncRefPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1530     RemoveIncRefPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~RemoveIncRefPattern()1531     ~RemoveIncRefPattern() override
1532     {
1533         insnMov2 = nullptr;
1534         insnMov1 = nullptr;
1535     }
1536     void Run(BB &bb, Insn &insn) override;
1537     bool CheckCondition(Insn &insn) override;
GetPatternName()1538     std::string GetPatternName() override
1539     {
1540         return "RemoveIncRefPattern";
1541     }
1542 
1543 private:
1544     Insn *insnMov2 = nullptr;
1545     Insn *insnMov1 = nullptr;
1546 };
1547 
1548 /*
1549  * opt long int compare with 0
1550  *  *cmp x0, #0
1551  *  csinv w0, wzr, wzr, GE
1552  *  csinc w0, w0, wzr, LE
1553  *  cmp w0, #0
1554  *  =>
1555  *  cmp x0, #0
1556  */
1557 class LongIntCompareWithZPattern : public CGPeepPattern {
1558 public:
LongIntCompareWithZPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1559     LongIntCompareWithZPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
1560     ~LongIntCompareWithZPattern() override = default;
1561     void Run(BB &bb, Insn &insn) override;
1562     bool CheckCondition(Insn &insn) override;
GetPatternName()1563     std::string GetPatternName() override
1564     {
1565         return "LongIntCompareWithZPattern";
1566     }
1567 
1568 private:
1569     bool FindLondIntCmpWithZ(Insn &insn);
1570     bool IsPatternMatch();
1571     std::vector<Insn *> optInsn;
1572 };
1573 
1574 /*
1575  *  add     x0, x1, #:lo12:Ljava_2Futil_2FLocale_241_3B_7C_24SwitchMap_24java_24util_24Locale_24Category
1576  *  ldr     x2, [x0]
1577  *  ==>
1578  *  ldr     x2, [x1, #:lo12:Ljava_2Futil_2FLocale_241_3B_7C_24SwitchMap_24java_24util_24Locale_24Category]
1579  */
1580 class ComplexMemOperandAArch64 : public PeepPattern {
1581 public:
ComplexMemOperandAArch64(CGFunc & cgFunc)1582     explicit ComplexMemOperandAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1583     ~ComplexMemOperandAArch64() override = default;
1584     void Run(BB &bb, Insn &insn) override;
1585 };
1586 
1587 /*
1588  *  add     x0, x1, x0
1589  *  ldr     x2, [x0]
1590  *  ==>
1591  *  ldr     x2, [x1, x0]
1592  */
1593 class ComplexMemOperandPreAddAArch64 : public PeepPattern {
1594 public:
ComplexMemOperandPreAddAArch64(CGFunc & cgFunc)1595     explicit ComplexMemOperandPreAddAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1596     ~ComplexMemOperandPreAddAArch64() override = default;
1597     void Run(BB &bb, Insn &insn) override;
1598 };
1599 
1600 /*
1601  * add     x0, x0, x1, LSL #2
1602  * ldr     x2, [x0]
1603  * ==>
1604  * ldr     x2, [x0,x1,LSL #2]
1605  */
1606 class ComplexMemOperandLSLAArch64 : public PeepPattern {
1607 public:
ComplexMemOperandLSLAArch64(CGFunc & cgFunc)1608     explicit ComplexMemOperandLSLAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1609     ~ComplexMemOperandLSLAArch64() override = default;
1610     bool CheckShiftValid(const Insn &insn, const BitShiftOperand &lsl) const;
1611     void Run(BB &bb, Insn &insn) override;
1612 };
1613 
1614 /*
1615  * ldr     x0, label_of_constant_1
1616  * fmov    d4, x0
1617  * ==>
1618  * ldr     d4, label_of_constant_1
1619  */
1620 class ComplexMemOperandLabelAArch64 : public PeepPattern {
1621 public:
ComplexMemOperandLabelAArch64(CGFunc & cgFunc)1622     explicit ComplexMemOperandLabelAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1623     ~ComplexMemOperandLabelAArch64() override = default;
1624     void Run(BB &bb, Insn &insn) override;
1625 };
1626 
1627 /*
1628  * mov R0, vreg1 / R0         mov R0, vreg1
1629  * add vreg2, vreg1, #imm1    add vreg2, vreg1, #imm1
1630  * mov R1, vreg2              mov R1, vreg2
1631  * mov R2, vreg3              mov R2, vreg3
1632  * ...                        ...
1633  * mov R0, vreg1
1634  * add vreg4, vreg1, #imm2 -> str vreg5, [vreg1, #imm2]
1635  * mov R1, vreg4
1636  * mov R2, vreg5
1637  */
1638 class WriteFieldCallPattern : public CGPeepPattern {
1639 public:
1640     struct WriteRefFieldParam {
1641         Operand *objOpnd = nullptr;
1642         RegOperand *fieldBaseOpnd = nullptr;
1643         int64 fieldOffset = 0;
1644         Operand *fieldValue = nullptr;
1645     };
WriteFieldCallPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1646     WriteFieldCallPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~WriteFieldCallPattern()1647     ~WriteFieldCallPattern() override
1648     {
1649         prevCallInsn = nullptr;
1650         nextInsn = nullptr;
1651     }
1652     void Run(BB &bb, Insn &insn) override;
1653     bool CheckCondition(Insn &insn) override;
GetPatternName()1654     std::string GetPatternName() override
1655     {
1656         return "WriteFieldCallPattern";
1657     }
1658 
1659 private:
1660     bool hasWriteFieldCall = false;
1661     Insn *prevCallInsn = nullptr;
1662     Insn *nextInsn = nullptr;
1663     WriteRefFieldParam firstCallParam;
1664     WriteRefFieldParam currentCallParam;
1665     std::vector<Insn *> paramDefInsns;
1666     bool WriteFieldCallOptPatternMatch(const Insn &writeFieldCallInsn, WriteRefFieldParam &param);
1667     bool IsWriteRefFieldCallInsn(const Insn &insn) const;
1668 };
1669 
1670 /*
1671  * Remove following patterns:
1672  *     mov     x0, xzr/#0
1673  *     bl      MCC_DecRef_NaiveRCFast
1674  */
1675 class RemoveDecRefPattern : public CGPeepPattern {
1676 public:
RemoveDecRefPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1677     RemoveDecRefPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~RemoveDecRefPattern()1678     ~RemoveDecRefPattern() override
1679     {
1680         prevInsn = nullptr;
1681     }
1682     void Run(BB &bb, Insn &insn) override;
1683     bool CheckCondition(Insn &insn) override;
GetPatternName()1684     std::string GetPatternName() override
1685     {
1686         return "RemoveDecRefPattern";
1687     }
1688 
1689 private:
1690     Insn *prevInsn = nullptr;
1691 };
1692 
1693 /*
1694  * We optimize the following pattern in this function:
1695  * and x1, x1, #imm (is n power of 2)
1696  * cbz/cbnz x1, .label
1697  * =>
1698  * and x1, x1, #imm (is n power of 2)
1699  * tbnz/tbz x1, #n, .label
1700  */
1701 class OneHoleBranchesAArch64 : public PeepPattern {
1702 public:
OneHoleBranchesAArch64(CGFunc & cgFunc)1703     explicit OneHoleBranchesAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1704     ~OneHoleBranchesAArch64() override = default;
1705     void Run(BB &bb, Insn &insn) override;
1706 };
1707 
1708 /*
1709  * Replace following pattern:
1710  * mov x1, xzr
1711  * bl MCC_IncDecRef_NaiveRCFast
1712  * =>
1713  * bl MCC_IncRef_NaiveRCFast
1714  */
1715 class ReplaceIncDecWithIncPattern : public CGPeepPattern {
1716 public:
ReplaceIncDecWithIncPattern(CGFunc & cgFunc,BB & currBB,Insn & currInsn)1717     ReplaceIncDecWithIncPattern(CGFunc &cgFunc, BB &currBB, Insn &currInsn) : CGPeepPattern(cgFunc, currBB, currInsn) {}
~ReplaceIncDecWithIncPattern()1718     ~ReplaceIncDecWithIncPattern() override
1719     {
1720         prevInsn = nullptr;
1721         target = nullptr;
1722     }
1723     void Run(BB &bb, Insn &insn) override;
1724     bool CheckCondition(Insn &insn) override;
GetPatternName()1725     std::string GetPatternName() override
1726     {
1727         return "ReplaceIncDecWithIncPattern";
1728     }
1729 
1730 private:
1731     Insn *prevInsn = nullptr;
1732     FuncNameOperand *target = nullptr;
1733 };
1734 
1735 /*
1736  * Optimize the following patterns:
1737  *  and  w0, w6, #1  ====> tbz  w6, 0, .label
1738  *  cmp  w0, #1
1739  *  bne  .label
1740  *
1741  *  and  w0, w6, #16  ====> tbz  w6, 4, .label
1742  *  cmp  w0, #16
1743  *  bne  .label
1744  *
1745  *  and  w0, w6, #32  ====> tbnz  w6, 5, .label
1746  *  cmp  w0, #32
1747  *  beq  .label
1748  *
1749  *  and  x0, x6, #32  ====> tbz  x6, 5, .label
1750  *  cmp  x0, #0
1751  *  beq  .label
1752  *
1753  *  and  x0, x6, #32  ====> tbnz  x6, 5, .label
1754  *  cmp  x0, #0
1755  *  bne  .label
1756  */
1757 class AndCmpBranchesToTbzAArch64 : public PeepPattern {
1758 public:
AndCmpBranchesToTbzAArch64(CGFunc & cgFunc)1759     explicit AndCmpBranchesToTbzAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1760     ~AndCmpBranchesToTbzAArch64() override = default;
1761     void Run(BB &bb, Insn &insn) override;
1762 };
1763 
1764 /*
1765  * Optimize the following patterns:
1766  * sxth  r4, r4         ====> strh r4, [r0, r3]
1767  * strh  r4, [r0, r3]
1768  *
1769  * sxtb  r4, r4         ====> strb r4, [r0, r3]
1770  * strb  r4, [r0, r3]
1771  */
1772 class RemoveSxtBeforeStrAArch64 : public PeepPattern {
1773 public:
RemoveSxtBeforeStrAArch64(CGFunc & cgFunc)1774     explicit RemoveSxtBeforeStrAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1775     ~RemoveSxtBeforeStrAArch64() override = default;
1776     void Run(BB &bb, Insn &insn) override;
1777 };
1778 
1779 /*
1780  * Optimize the following patterns:
1781  * mov x1, #1
1782  * csel  x22, xzr, x1, LS   ====> cset x22, HI
1783  *
1784  * mov x1, #1
1785  * csel  x22, x1, xzr, LS   ====> cset x22, LS
1786  */
1787 class CselZeroOneToCsetOpt : public PeepPattern {
1788 public:
CselZeroOneToCsetOpt(CGFunc & cgFunc)1789     explicit CselZeroOneToCsetOpt(CGFunc &cgFunc) : PeepPattern(cgFunc), cgFunc(&cgFunc) {}
1790     ~CselZeroOneToCsetOpt() override = default;
1791     void Run(BB &bb, Insn &insn) override;
1792 
1793 private:
1794     Insn *trueMovInsn = nullptr;
1795     Insn *falseMovInsn = nullptr;
1796     Insn *FindFixedValue(Operand &opnd, BB &bb, Operand *&tempOp, const Insn &insn) const;
1797 
1798 protected:
1799     CGFunc *cgFunc;
1800 };
1801 
1802 /*
1803  * Optimize the following patterns:
1804  * and w0, w0, #0x1
1805  * cmp w0, #0x0
1806  * cset w0, eq
1807  * eor w0, w0, #0x1
1808  * cbz w0, label
1809  * ====>
1810  * tbz w0, 0, label
1811  */
1812 class AndCmpCsetEorCbzOpt : public PeepPattern {
1813 public:
AndCmpCsetEorCbzOpt(CGFunc & cgFunc)1814     explicit AndCmpCsetEorCbzOpt(CGFunc &cgFunc) : PeepPattern(cgFunc), cgFunc(&cgFunc) {}
1815     ~AndCmpCsetEorCbzOpt() override = default;
1816     void Run(BB &bb, Insn &insn) override;
1817 private:
1818     CGFunc *cgFunc;
1819 };
1820 
1821 /*
1822  * Optimize the following patterns:
1823  * add x0, x0, x1
1824  * ldr w0, [x0]
1825  * ====>
1826  * ldr w0, [x0, x1]
1827  */
1828 class AddLdrOpt : public PeepPattern {
1829 public:
AddLdrOpt(CGFunc & cgFunc)1830     explicit AddLdrOpt(CGFunc &cgFunc) : PeepPattern(cgFunc), cgFunc(&cgFunc) {}
1831     ~AddLdrOpt() override = default;
1832     void Run(BB &bb, Insn &insn) override;
1833 private:
1834     CGFunc *cgFunc;
1835 };
1836 
1837 /*
1838  * Optimize the following patterns:
1839  * cset x0, eq
1840  * eor x0, x0, 0x1
1841  * ====>
1842  * cset x0, ne
1843  */
1844 class CsetEorOpt : public PeepPattern {
1845 public:
CsetEorOpt(CGFunc & cgFunc)1846     explicit CsetEorOpt(CGFunc &cgFunc) : PeepPattern(cgFunc), cgFunc(&cgFunc) {}
1847     ~CsetEorOpt() override = default;
1848     void Run(BB &bb, Insn &insn) override;
1849 private:
1850     CGFunc *cgFunc;
1851 };
1852 
1853 /*
1854  * Optimize the following patterns:
1855  * mov x1, #0x5
1856  * cmp x0, x1
1857  * ====>
1858  * cmp x0, #0x5
1859  */
1860 class MoveCmpOpt : public PeepPattern {
1861 public:
MoveCmpOpt(CGFunc & cgFunc)1862     explicit MoveCmpOpt(CGFunc &cgFunc) : PeepPattern(cgFunc), cgFunc(&cgFunc) {}
1863     ~MoveCmpOpt() override = default;
1864     void Run(BB &bb, Insn &insn) override;
1865 private:
1866     CGFunc *cgFunc;
1867 };
1868 
1869 /*
1870  * Replace following pattern:
1871  * sxtw  x1, w0
1872  * lsl   x2, x1, #3  ====>  sbfiz x2, x0, #3, #32
1873  *
1874  * uxtw  x1, w0
1875  * lsl   x2, x1, #3  ====>  ubfiz x2, x0, #3, #32
1876  */
1877 class ComplexExtendWordLslAArch64 : public PeepPattern {
1878 public:
ComplexExtendWordLslAArch64(CGFunc & cgFunc)1879     explicit ComplexExtendWordLslAArch64(CGFunc &cgFunc) : PeepPattern(cgFunc) {}
1880     ~ComplexExtendWordLslAArch64() override = default;
1881     void Run(BB &bb, Insn &insn) override;
1882 
1883 private:
1884     bool IsExtendWordLslPattern(const Insn &insn) const;
1885 };
1886 
1887 class AArch64PeepHole : public PeepPatternMatch {
1888 public:
AArch64PeepHole(CGFunc & oneCGFunc,MemPool * memPool)1889     AArch64PeepHole(CGFunc &oneCGFunc, MemPool *memPool) : PeepPatternMatch(oneCGFunc, memPool) {}
1890     ~AArch64PeepHole() override = default;
1891     void InitOpts() override;
1892     void Run(BB &bb, Insn &insn) override;
1893 
1894 private:
1895     enum PeepholeOpts : int32 {
1896         kRemoveIdenticalLoadAndStoreOpt = 0,
1897         kRemoveMovingtoSameRegOpt,
1898         kCombineContiLoadAndStoreOpt,
1899         kEliminateSpecifcSXTOpt,
1900         kEliminateSpecifcUXTOpt,
1901         kFmovRegOpt,
1902         kCbnzToCbzOpt,
1903         kCsetCbzToBeqOpt,
1904         kContiLDRorSTRToSameMEMOpt,
1905         kRemoveIncDecRefOpt,
1906         kInlineReadBarriersOpt,
1907         kReplaceDivToMultiOpt,
1908         kAndCmpBranchesToCsetOpt,
1909         kAndCmpBranchesToTstOpt,
1910         kAndCbzBranchesToTstOpt,
1911         kZeroCmpBranchesOpt,
1912         kCselZeroOneToCsetOpt,
1913         kAndCmpCsetEorCbzOpt,
1914         kAddLdrOpt,
1915         kCsetEorOpt,
1916         kMoveCmpOpt,
1917         kPeepholeOptsNum
1918     };
1919 };
1920 
1921 class AArch64PeepHole0 : public PeepPatternMatch {
1922 public:
AArch64PeepHole0(CGFunc & oneCGFunc,MemPool * memPool)1923     AArch64PeepHole0(CGFunc &oneCGFunc, MemPool *memPool) : PeepPatternMatch(oneCGFunc, memPool) {}
1924     ~AArch64PeepHole0() override = default;
1925     void InitOpts() override;
1926     void Run(BB &bb, Insn &insn) override;
1927 
1928 private:
1929     enum PeepholeOpts : int32 {
1930         kRemoveIdenticalLoadAndStoreOpt = 0,
1931         kCmpCsetOpt,
1932         kComplexMemOperandOptAdd,
1933         kDeleteMovAfterCbzOrCbnzOpt,
1934         kRemoveSxtBeforeStrOpt,
1935         kRemoveMovingtoSameRegOpt,
1936         kEnhanceStrLdrAArch64Opt,
1937         kPeepholeOptsNum
1938     };
1939 };
1940 
1941 class AArch64PrePeepHole : public PeepPatternMatch {
1942 public:
AArch64PrePeepHole(CGFunc & oneCGFunc,MemPool * memPool)1943     AArch64PrePeepHole(CGFunc &oneCGFunc, MemPool *memPool) : PeepPatternMatch(oneCGFunc, memPool) {}
1944     ~AArch64PrePeepHole() override = default;
1945     void InitOpts() override;
1946     void Run(BB &bb, Insn &insn) override;
1947 
1948 private:
1949     enum PeepholeOpts : int32 {
1950         kOneHoleBranchesPreOpt = 0,
1951         kLoadFloatPointOpt,
1952         kReplaceOrrToMovOpt,
1953         kReplaceCmpToCmnOpt,
1954         kRemoveIncRefOpt,
1955         kLongIntCompareWithZOpt,
1956         kComplexMemOperandOpt,
1957         kComplexMemOperandPreOptAdd,
1958         kComplexMemOperandOptLSL,
1959         kComplexMemOperandOptLabel,
1960         kWriteFieldCallOpt,
1961         kDuplicateExtensionOpt,
1962         kEnhanceStrLdrAArch64Opt,
1963         kUbfxToUxtw,
1964         kPeepholeOptsNum
1965     };
1966 };
1967 
1968 class AArch64PrePeepHole1 : public PeepPatternMatch {
1969 public:
AArch64PrePeepHole1(CGFunc & oneCGFunc,MemPool * memPool)1970     AArch64PrePeepHole1(CGFunc &oneCGFunc, MemPool *memPool) : PeepPatternMatch(oneCGFunc, memPool) {}
1971     ~AArch64PrePeepHole1() override = default;
1972     void InitOpts() override;
1973     void Run(BB &bb, Insn &insn) override;
1974 
1975 private:
1976     enum PeepholeOpts : int32 {
1977         kRemoveDecRefOpt = 0,
1978         kComputationTreeOpt,
1979         kOneHoleBranchesOpt,
1980         kReplaceIncDecWithIncOpt,
1981         kAndCmpBranchesToTbzOpt,
1982         kComplexExtendWordLslOpt,
1983         kPeepholeOptsNum
1984     };
1985 };
1986 } /* namespace maplebe */
1987 #endif /* MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_PEEP_H */
1988