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 ®Opnd, 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 ®Opnd) 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 ¶m); 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