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