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_GLOBAL_H 17 #define MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_GLOBAL_H 18 19 #include "global.h" 20 #include "aarch64_operand.h" 21 22 namespace maplebe { 23 using namespace maple; 24 25 class AArch64GlobalOpt : public GlobalOpt { 26 public: AArch64GlobalOpt(CGFunc & func)27 explicit AArch64GlobalOpt(CGFunc &func) : GlobalOpt(func) {} 28 ~AArch64GlobalOpt() override = default; 29 void Run() override; 30 }; 31 32 class OptimizeManager { 33 public: OptimizeManager(CGFunc & cgFunc)34 explicit OptimizeManager(CGFunc &cgFunc) : cgFunc(cgFunc) {} 35 ~OptimizeManager() = default; 36 template <typename OptimizePattern> Optimize()37 void Optimize() 38 { 39 OptimizePattern optPattern(cgFunc); 40 optPattern.Run(); 41 } 42 43 private: 44 CGFunc &cgFunc; 45 }; 46 47 class OptimizePattern { 48 public: OptimizePattern(CGFunc & cgFunc)49 explicit OptimizePattern(CGFunc &cgFunc) : cgFunc(cgFunc) {} 50 virtual ~OptimizePattern() = default; 51 virtual bool CheckCondition(Insn &insn) = 0; 52 virtual void Optimize(Insn &insn) = 0; 53 virtual void Run() = 0; 54 bool OpndDefByOne(Insn &insn, int32 useIdx) const; 55 bool OpndDefByZero(Insn &insn, int32 useIdx) const; 56 bool OpndDefByOneOrZero(Insn &insn, int32 useIdx) const; 57 void ReplaceAllUsedOpndWithNewOpnd(const InsnSet &useInsnSet, uint32 regNO, Operand &newOpnd, 58 bool updateInfo) const; 59 60 static bool InsnDefOne(const Insn &insn); 61 static bool InsnDefZero(const Insn &insn); 62 static bool InsnDefOneOrZero(const Insn &insn); 63 PhaseName()64 std::string PhaseName() const 65 { 66 return "globalopt"; 67 } 68 69 protected: 70 virtual void Init() = 0; 71 CGFunc &cgFunc; 72 }; 73 74 /* 75 * Do Forward prop when insn is mov 76 * mov xx, x1 77 * ... // BBs and x1 is live 78 * mOp yy, xx 79 * 80 * => 81 * mov x1, x1 82 * ... // BBs and x1 is live 83 * mOp yy, x1 84 */ 85 class ForwardPropPattern : public OptimizePattern { 86 public: ForwardPropPattern(CGFunc & cgFunc)87 explicit ForwardPropPattern(CGFunc &cgFunc) : OptimizePattern(cgFunc) {} 88 ~ForwardPropPattern() override = default; 89 bool CheckCondition(Insn &insn) final; 90 void Optimize(Insn &insn) final; 91 void Run() final; 92 93 protected: 94 void Init() final; 95 96 private: 97 InsnSet firstRegUseInsnSet; 98 void RemoveMopUxtwToMov(Insn &insn); 99 std::set<BB *, BBIdCmp> modifiedBB; 100 }; 101 102 /* 103 * Do back propagate of vreg/preg when encount following insn: 104 * 105 * mov vreg/preg1, vreg2 106 * 107 * back propagate reg1 to all vreg2's use points and def points, when all of them is in same bb 108 */ 109 class BackPropPattern : public OptimizePattern { 110 public: BackPropPattern(CGFunc & cgFunc)111 explicit BackPropPattern(CGFunc &cgFunc) : OptimizePattern(cgFunc) {} ~BackPropPattern()112 ~BackPropPattern() override 113 { 114 firstRegOpnd = nullptr; 115 secondRegOpnd = nullptr; 116 defInsnForSecondOpnd = nullptr; 117 } 118 bool CheckCondition(Insn &insn) final; 119 void Optimize(Insn &insn) final; 120 void Run() final; 121 122 protected: 123 void Init() final; 124 125 private: 126 bool CheckAndGetOpnd(const Insn &insn); 127 bool DestOpndHasUseInsns(Insn &insn); 128 bool DestOpndLiveOutToEHSuccs(Insn &insn) const; 129 bool CheckSrcOpndDefAndUseInsns(Insn &insn); 130 bool CheckSrcOpndDefAndUseInsnsGlobal(Insn &insn); 131 bool CheckPredefineInsn(Insn &insn); 132 bool CheckRedefineInsn(Insn &insn); 133 bool CheckReplacedUseInsn(Insn &insn); 134 RegOperand *firstRegOpnd = nullptr; 135 RegOperand *secondRegOpnd = nullptr; 136 uint32 firstRegNO = 0; 137 uint32 secondRegNO = 0; 138 InsnSet srcOpndUseInsnSet; 139 Insn *defInsnForSecondOpnd = nullptr; 140 bool globalProp = false; 141 }; 142 143 /* 144 * when w0 has only one valid bit, these tranformation will be done 145 * cmp w0, #0 146 * cset w1, NE --> mov w1, w0 147 * 148 * cmp w0, #0 149 * cset w1, EQ --> eor w1, w0, 1 150 * 151 * cmp w0, #1 152 * cset w1, NE --> eor w1, w0, 1 153 * 154 * cmp w0, #1 155 * cset w1, EQ --> mov w1, w0 156 * 157 * cmp w0, #0 158 * cset w0, NE -->null 159 * 160 * cmp w0, #1 161 * cset w0, EQ -->null 162 * 163 * condition: 164 * 1. the first operand of cmp instruction must has only one valid bit 165 * 2. the second operand of cmp instruction must be 0 or 1 166 * 3. flag register of cmp isntruction must not be used later 167 */ 168 class CmpCsetPattern : public OptimizePattern { 169 public: CmpCsetPattern(CGFunc & cgFunc)170 explicit CmpCsetPattern(CGFunc &cgFunc) : OptimizePattern(cgFunc) {} ~CmpCsetPattern()171 ~CmpCsetPattern() override 172 { 173 nextInsn = nullptr; 174 cmpFirstOpnd = nullptr; 175 cmpSecondOpnd = nullptr; 176 csetFirstOpnd = nullptr; 177 } 178 bool CheckCondition(Insn &insn) final; 179 void Optimize(Insn &insn) final; 180 void Run() final; 181 182 protected: 183 void Init() final; 184 185 private: 186 Insn *nextInsn = nullptr; 187 int64 cmpConstVal = 0; 188 Operand *cmpFirstOpnd = nullptr; 189 Operand *cmpSecondOpnd = nullptr; 190 Operand *csetFirstOpnd = nullptr; 191 }; 192 193 /* 194 * mov w5, #1 195 * ... --> cset w5, NE 196 * mov w0, #0 197 * csel w5, w5, w0, NE 198 * 199 * mov w5, #0 200 * ... --> cset w5,EQ 201 * mov w0, #1 202 * csel w5, w5, w0, NE 203 * 204 * condition: 205 * 1.all define points of w5 are defined by: mov w5, #1(#0) 206 * 2.all define points of w0 are defined by: mov w0, #0(#1) 207 * 3.w0 will not be used after: csel w5, w5, w0, NE(EQ) 208 */ 209 class CselPattern : public OptimizePattern { 210 public: CselPattern(CGFunc & cgFunc)211 explicit CselPattern(CGFunc &cgFunc) : OptimizePattern(cgFunc) {} 212 ~CselPattern() override = default; 213 bool CheckCondition(Insn &insn) final; 214 void Optimize(Insn &insn) final; 215 void Run() final; 216 217 protected: Init()218 void Init() final {} 219 }; 220 221 /* 222 * uxtb w0, w0 --> null 223 * uxth w0, w0 --> null 224 * 225 * condition: 226 * 1. validbits(w0)<=8,16,32 227 * 2. the first operand is same as the second operand 228 * 229 * uxtb w0, w1 --> null 230 * uxth w0, w1 --> null 231 * 232 * condition: 233 * 1. validbits(w1)<=8,16,32 234 * 2. the use points of w0 has only one define point, that is uxt w0, w1 235 */ 236 class RedundantUxtPattern : public OptimizePattern { 237 public: RedundantUxtPattern(CGFunc & cgFunc)238 explicit RedundantUxtPattern(CGFunc &cgFunc) : OptimizePattern(cgFunc) {} ~RedundantUxtPattern()239 ~RedundantUxtPattern() override 240 { 241 secondOpnd = nullptr; 242 } 243 bool CheckCondition(Insn &insn) final; 244 void Optimize(Insn &insn) final; 245 void Run() final; 246 247 protected: 248 void Init() final; 249 250 private: 251 uint32 GetMaximumValidBit(Insn &insn, uint8 udIdx, InsnSet &insnChecked) const; 252 static uint32 GetInsnValidBit(const Insn &insn); 253 InsnSet useInsnSet; 254 uint32 firstRegNO = 0; 255 Operand *secondOpnd = nullptr; 256 }; 257 258 /* 259 * bl MCC_NewObj_flexible_cname bl MCC_NewObj_flexible_cname 260 * mov x21, x0 // [R203] 261 * str x0, [x29,#16] // local var: Reg0_R6340 [R203] --> str x0, [x29,#16] // local var: Reg0_R6340 [R203] 262 * ... (has call) ... (has call) 263 * mov x2, x21 // use of x21 ldr x2, [x29, #16] 264 * bl *** bl *** 265 */ 266 class LocalVarSaveInsnPattern : public OptimizePattern { 267 public: LocalVarSaveInsnPattern(CGFunc & cgFunc)268 explicit LocalVarSaveInsnPattern(CGFunc &cgFunc) : OptimizePattern(cgFunc) {} ~LocalVarSaveInsnPattern()269 ~LocalVarSaveInsnPattern() override 270 { 271 firstInsnSrcOpnd = nullptr; 272 firstInsnDestOpnd = nullptr; 273 secondInsnSrcOpnd = nullptr; 274 secondInsnDestOpnd = nullptr; 275 useInsn = nullptr; 276 secondInsn = nullptr; 277 } 278 bool CheckCondition(Insn &insn) final; 279 void Optimize(Insn &insn) final; 280 void Run() final; 281 282 protected: 283 void Init() final; 284 285 private: 286 bool CheckFirstInsn(const Insn &firstInsn); 287 bool CheckSecondInsn(); 288 bool CheckAndGetUseInsn(Insn &firstInsn); 289 bool CheckLiveRange(const Insn &firstInsn); 290 Operand *firstInsnSrcOpnd = nullptr; 291 Operand *firstInsnDestOpnd = nullptr; 292 Operand *secondInsnSrcOpnd = nullptr; 293 Operand *secondInsnDestOpnd = nullptr; 294 Insn *useInsn = nullptr; 295 Insn *secondInsn = nullptr; 296 }; 297 298 class ExtendShiftOptPattern : public OptimizePattern { 299 public: ExtendShiftOptPattern(CGFunc & cgFunc)300 explicit ExtendShiftOptPattern(CGFunc &cgFunc) : OptimizePattern(cgFunc) {} ~ExtendShiftOptPattern()301 ~ExtendShiftOptPattern() override 302 { 303 defInsn = nullptr; 304 newInsn = nullptr; 305 } 306 bool CheckCondition(Insn &insn) final; 307 void Optimize(Insn &insn) final; 308 void Run() final; 309 void DoExtendShiftOpt(Insn &insn); 310 311 enum ExMOpType : uint8 { 312 kExUndef, 313 kExAdd, /* MOP_xaddrrr | MOP_xxwaddrrre | MOP_xaddrrrs */ 314 kEwAdd, /* MOP_waddrrr | MOP_wwwaddrrre | MOP_waddrrrs */ 315 kExSub, /* MOP_xsubrrr | MOP_xxwsubrrre | MOP_xsubrrrs */ 316 kEwSub, /* MOP_wsubrrr | MOP_wwwsubrrre | MOP_wsubrrrs */ 317 kExCmn, /* MOP_xcmnrr | MOP_xwcmnrre | MOP_xcmnrrs */ 318 kEwCmn, /* MOP_wcmnrr | MOP_wwcmnrre | MOP_wcmnrrs */ 319 kExCmp, /* MOP_xcmprr | MOP_xwcmprre | MOP_xcmprrs */ 320 kEwCmp, /* MOP_wcmprr | MOP_wwcmprre | MOP_wcmprrs */ 321 }; 322 323 enum LsMOpType : uint8 { 324 kLsUndef, 325 kLxAdd, /* MOP_xaddrrr | MOP_xaddrrrs */ 326 kLwAdd, /* MOP_waddrrr | MOP_waddrrrs */ 327 kLxSub, /* MOP_xsubrrr | MOP_xsubrrrs */ 328 kLwSub, /* MOP_wsubrrr | MOP_wsubrrrs */ 329 kLxCmn, /* MOP_xcmnrr | MOP_xcmnrrs */ 330 kLwCmn, /* MOP_wcmnrr | MOP_wcmnrrs */ 331 kLxCmp, /* MOP_xcmprr | MOP_xcmprrs */ 332 kLwCmp, /* MOP_wcmprr | MOP_wcmprrs */ 333 kLxEor, /* MOP_xeorrrr | MOP_xeorrrrs */ 334 kLwEor, /* MOP_weorrrr | MOP_weorrrrs */ 335 kLxNeg, /* MOP_xinegrr | MOP_xinegrrs */ 336 kLwNeg, /* MOP_winegrr | MOP_winegrrs */ 337 kLxIor, /* MOP_xiorrrr | MOP_xiorrrrs */ 338 kLwIor, /* MOP_wiorrrr | MOP_wiorrrrs */ 339 }; 340 341 enum SuffixType : uint8 { 342 kNoSuffix, /* no suffix or do not perform the optimization. */ 343 kLSL, /* logical shift left */ 344 kLSR, /* logical shift right */ 345 kASR, /* arithmetic shift right */ 346 kExten /* ExtendOp */ 347 }; 348 349 protected: 350 void Init() final; 351 352 private: 353 void SelectExtendOrShift(const Insn &def); 354 bool CheckDefUseInfo(Insn &use, uint32 size); 355 SuffixType CheckOpType(const Operand &lastOpnd) const; 356 void ReplaceUseInsn(Insn &use, const Insn &def, uint32 amount); 357 void SetExMOpType(const Insn &use); 358 void SetLsMOpType(const Insn &use); 359 360 MOperator replaceOp; 361 uint32 replaceIdx; 362 ExtendShiftOperand::ExtendOp extendOp; 363 BitShiftOperand::ShiftOp shiftOp; 364 Insn *defInsn = nullptr; 365 Insn *newInsn = nullptr; 366 bool optSuccess; 367 bool removeDefInsn; 368 ExMOpType exMOpType; 369 LsMOpType lsMOpType; 370 }; 371 372 /* 373 * This pattern do: 374 * 1) 375 * uxtw vreg:Rm validBitNum:[64], vreg:Rn validBitNum:[32] 376 * ------> 377 * mov vreg:Rm validBitNum:[64], vreg:Rn validBitNum:[32] 378 * 2) 379 * ldrh R201, [...] 380 * and R202, R201, #65520 381 * uxth R203, R202 382 * -------> 383 * ldrh R201, [...] 384 * and R202, R201, #65520 385 * mov R203, R202 386 */ 387 class ExtenToMovPattern : public OptimizePattern { 388 public: ExtenToMovPattern(CGFunc & cgFunc)389 explicit ExtenToMovPattern(CGFunc &cgFunc) : OptimizePattern(cgFunc) {} 390 ~ExtenToMovPattern() override = default; 391 bool CheckCondition(Insn &insn) final; 392 void Optimize(Insn &insn) final; 393 void Run() final; 394 395 protected: 396 void Init() final; 397 398 private: 399 bool CheckHideUxtw(const Insn &insn, regno_t regno) const; 400 bool CheckUxtw(Insn &insn); 401 bool BitNotAffected(Insn &insn, uint32 validNum); /* check whether significant bits are affected */ 402 bool CheckSrcReg(Insn &insn, regno_t srcRegNo, uint32 validNum); 403 404 MOperator replaceMop = MOP_undef; 405 }; 406 407 class SameDefPattern : public OptimizePattern { 408 public: SameDefPattern(CGFunc & cgFunc)409 explicit SameDefPattern(CGFunc &cgFunc) : OptimizePattern(cgFunc) {} ~SameDefPattern()410 ~SameDefPattern() override 411 { 412 currInsn = nullptr; 413 sameInsn = nullptr; 414 } 415 bool CheckCondition(Insn &insn) final; 416 void Optimize(Insn &insn) final; 417 void Run() final; 418 419 protected: 420 void Init() final; 421 422 private: 423 bool IsSameDef(); 424 bool SrcRegIsRedefined(regno_t regNo); 425 bool IsSameOperand(Operand &opnd0, Operand &opnd1); 426 427 Insn *currInsn = nullptr; 428 Insn *sameInsn = nullptr; 429 }; 430 431 /* 432 * and r0, r0, #4 (the imm is n power of 2) 433 * ... (r0 is not used) 434 * cbz r0, .Label 435 * ===> tbz r0, #2, .Label 436 * 437 * and r0, r0, #4 (the imm is n power of 2) 438 * ... (r0 is not used) 439 * cbnz r0, .Label 440 * ===> tbnz r0, #2, .Label 441 */ 442 class AndCbzPattern : public OptimizePattern { 443 public: AndCbzPattern(CGFunc & cgFunc)444 explicit AndCbzPattern(CGFunc &cgFunc) : OptimizePattern(cgFunc) {} ~AndCbzPattern()445 ~AndCbzPattern() override 446 { 447 prevInsn = nullptr; 448 } 449 bool CheckCondition(Insn &insn) final; 450 void Optimize(Insn &insn) final; 451 void Run() final; 452 453 protected: 454 void Init() final; 455 456 private: 457 int64 CalculateLogValue(int64 val) const; 458 bool IsAdjacentArea(Insn &prev, Insn &curr) const; 459 Insn *prevInsn = nullptr; 460 }; 461 462 /* 463 * [arithmetic operation] 464 * add/sub/ R202, R201, #1 add/sub/ R202, R201, #1 465 * ... ... 466 * add/sub/ R203, R201, #1 ---> mov R203, R202 467 * 468 * [copy operation] 469 * mov R201, #1 mov R201, #1 470 * ... ... 471 * mov R202, #1 ---> mov R202, R201 472 * 473 * The pattern finds the insn with the same rvalue as the current insn, 474 * then prop its lvalue, and replaces the current insn with movrr insn. 475 * The mov can be prop in forwardprop or backprop. 476 * 477 * conditions: 478 * 1. in same BB 479 * 2. rvalue is not defined between two insns 480 * 3. lvalue is not defined between two insns 481 */ 482 class SameRHSPropPattern : public OptimizePattern { 483 public: SameRHSPropPattern(CGFunc & cgFunc)484 explicit SameRHSPropPattern(CGFunc &cgFunc) : OptimizePattern(cgFunc) {} ~SameRHSPropPattern()485 ~SameRHSPropPattern() override 486 { 487 prevInsn = nullptr; 488 } 489 bool CheckCondition(Insn &insn) final; 490 void Optimize(Insn &insn) final; 491 void Run() final; 492 493 protected: 494 void Init() final; 495 496 private: 497 bool IsSameOperand(Operand *opnd1, Operand *opnd2) const; 498 bool FindSameRHSInsnInBB(Insn &insn); 499 Insn *prevInsn = nullptr; 500 std::vector<MOperator> candidates; 501 }; 502 } /* namespace maplebe */ 503 504 #endif /* MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_GLOBAL_H */ 505