• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef MAPLEBE_INCLUDE_AARCH64_PROP_H
17 #define MAPLEBE_INCLUDE_AARCH64_PROP_H
18 
19 #include "cg_prop.h"
20 #include "aarch64_cgfunc.h"
21 #include "aarch64_strldr.h"
22 namespace maplebe {
23 class AArch64Prop : public CGProp {
24 public:
AArch64Prop(MemPool & mp,CGFunc & f,CGSSAInfo & sInfo,LiveIntervalAnalysis & ll)25     AArch64Prop(MemPool &mp, CGFunc &f, CGSSAInfo &sInfo, LiveIntervalAnalysis &ll) : CGProp(mp, f, sInfo, ll) {}
26     ~AArch64Prop() override = default;
27 
28     /* do not extend life range */
29     static bool IsInLimitCopyRange(VRegVersion *toBeReplaced);
30 
31 private:
32     void CopyProp() override;
33     /*
34      * for aarch64
35      * 1. extended register prop
36      * 2. shift register prop
37      * 3. add/ext/shf prop -> str/ldr
38      * 4. const prop
39      */
40     void TargetProp(Insn &insn) override;
41     void PropPatternOpt() override;
42 };
43 
44 class A64StrLdrProp {
45 public:
A64StrLdrProp(MemPool & mp,CGFunc & f,CGSSAInfo & sInfo,Insn & insn,CGDce & dce)46     A64StrLdrProp(MemPool &mp, CGFunc &f, CGSSAInfo &sInfo, Insn &insn, CGDce &dce)
47         : cgFunc(&f),
48           ssaInfo(&sInfo),
49           curInsn(&insn),
50           a64StrLdrAlloc(&mp),
51           replaceVersions(a64StrLdrAlloc.Adapter()),
52           cgDce(&dce)
53     {
54     }
55     void DoOpt();
56 
57 private:
58     MemOperand *StrLdrPropPreCheck(const Insn &insn, MemPropMode prevMod = kUndef);
59     static MemPropMode SelectStrLdrPropMode(const MemOperand &currMemOpnd);
60     bool ReplaceMemOpnd(const MemOperand &currMemOpnd, const Insn *defInsn);
61     MemOperand *SelectReplaceMem(const Insn &defInsn, const MemOperand &currMemOpnd);
62     RegOperand *GetReplaceReg(RegOperand &a64Reg);
63     MemOperand *HandleArithImmDef(RegOperand &replace, Operand *oldOffset, int64 defVal, uint32 memSize) const;
64     MemOperand *SelectReplaceExt(const Insn &defInsn, RegOperand &base, uint32 amount, bool isSigned, uint32 memSize);
65     bool CheckNewMemOffset(const Insn &insn, MemOperand *newMemOpnd, uint32 opndIdx) const;
66     void DoMemReplace(const RegOperand &replacedReg, MemOperand &newMem, Insn &useInsn);
67     uint32 GetMemOpndIdx(MemOperand *newMemOpnd, const Insn &insn) const;
68 
69     bool CheckSameReplace(const RegOperand &replacedReg, const MemOperand *memOpnd) const;
70 
71     CGFunc *cgFunc;
72     CGSSAInfo *ssaInfo;
73     Insn *curInsn;
74     MapleAllocator a64StrLdrAlloc;
75     MapleMap<regno_t, VRegVersion *> replaceVersions;
76     MemPropMode memPropMode = kUndef;
77     CGDce *cgDce = nullptr;
78 };
79 
80 enum ArithmeticType { kAArch64Add, kAArch64Sub, kAArch64Orr, kAArch64Eor, kUndefArith };
81 
82 class A64ConstProp {
83 public:
A64ConstProp(MemPool & mp,CGFunc & f,CGSSAInfo & sInfo,Insn & insn)84     A64ConstProp(MemPool &mp, CGFunc &f, CGSSAInfo &sInfo, Insn &insn)
85         : constPropMp(&mp), cgFunc(&f), ssaInfo(&sInfo), curInsn(&insn)
86     {
87     }
88     void DoOpt();
89     /* false : default lsl #0 true: lsl #12 (only support 12 bit left shift in aarch64) */
90     static MOperator GetRegImmMOP(MOperator regregMop, bool withLeftShift);
91     static MOperator GetReversalMOP(MOperator arithMop);
92     static MOperator GetFoldMopAndVal(int64 &newVal, int64 constVal, const Insn &arithInsn);
93 
94 private:
95     bool ConstProp(DUInsnInfo &useDUInfo, ImmOperand &constOpnd);
96     /* use xzr/wzr in aarch64 to shrink register live range */
97     void ZeroRegProp(DUInsnInfo &useDUInfo, RegOperand &toReplaceReg);
98 
99     /* replace old Insn with new Insn, update ssa info automatically */
100     void ReplaceInsnAndUpdateSSA(Insn &oriInsn, Insn &newInsn) const;
101     ImmOperand *CanDoConstFold(const ImmOperand &value1, const ImmOperand &value2, ArithmeticType aT, bool is64Bit);
102 
103     /* optimization */
104     bool MovConstReplace(DUInsnInfo &useDUInfo, ImmOperand &constOpnd);
105     bool ArithmeticConstReplace(DUInsnInfo &useDUInfo, ImmOperand &constOpnd, ArithmeticType aT);
106     bool ArithmeticConstFold(DUInsnInfo &useDUInfo, const ImmOperand &constOpnd, ArithmeticType aT);
107     bool ShiftConstReplace(DUInsnInfo &useDUInfo, const ImmOperand &constOpnd);
108     bool BitInsertReplace(DUInsnInfo &useDUInfo, const ImmOperand &constOpnd);
109 
110     MemPool *constPropMp;
111     CGFunc *cgFunc;
112     CGSSAInfo *ssaInfo;
113     Insn *curInsn;
114 };
115 
116 class CopyRegProp : public PropOptimizePattern {
117 public:
CopyRegProp(CGFunc & cgFunc,CGSSAInfo * cgssaInfo,LiveIntervalAnalysis * ll)118     CopyRegProp(CGFunc &cgFunc, CGSSAInfo *cgssaInfo, LiveIntervalAnalysis *ll)
119         : PropOptimizePattern(cgFunc, cgssaInfo, ll)
120     {
121     }
122     ~CopyRegProp() override = default;
123     bool CheckCondition(Insn &insn) final;
124     void Optimize(Insn &insn) final;
125     void Run() final;
126 
127 protected:
Init()128     void Init() final
129     {
130         destVersion = nullptr;
131         srcVersion = nullptr;
132     }
133 
134 private:
135     bool IsValidCopyProp(const RegOperand &dstReg, const RegOperand &srcReg) const;
136     void VaildateImplicitCvt(RegOperand &destReg, const RegOperand &srcReg, Insn &movInsn);
137     VRegVersion *destVersion = nullptr;
138     VRegVersion *srcVersion = nullptr;
139 };
140 
141 class RedundantPhiProp : public PropOptimizePattern {
142 public:
RedundantPhiProp(CGFunc & cgFunc,CGSSAInfo * cgssaInfo)143     RedundantPhiProp(CGFunc &cgFunc, CGSSAInfo *cgssaInfo) : PropOptimizePattern(cgFunc, cgssaInfo) {}
144     ~RedundantPhiProp() override = default;
145     bool CheckCondition(Insn &insn) final;
146     void Optimize(Insn &insn) final;
147     void Run() final;
148 
149 protected:
Init()150     void Init() final
151     {
152         destVersion = nullptr;
153         srcVersion = nullptr;
154     }
155 
156 private:
157     VRegVersion *destVersion = nullptr;
158     VRegVersion *srcVersion = nullptr;
159 };
160 
161 class ValidBitNumberProp : public PropOptimizePattern {
162 public:
ValidBitNumberProp(CGFunc & cgFunc,CGSSAInfo * cgssaInfo)163     ValidBitNumberProp(CGFunc &cgFunc, CGSSAInfo *cgssaInfo) : PropOptimizePattern(cgFunc, cgssaInfo) {}
164     ~ValidBitNumberProp() override = default;
165     bool CheckCondition(Insn &insn) final;
166     void Optimize(Insn &insn) final;
167     void Run() final;
168 
169 protected:
Init()170     void Init() final
171     {
172         destVersion = nullptr;
173         srcVersion = nullptr;
174     }
175 
176 private:
177     VRegVersion *destVersion = nullptr;
178     VRegVersion *srcVersion = nullptr;
179 };
180 
181 /*
182  * frame pointer and stack pointer will not be varied in function body
183  * treat them as const
184  */
185 class FpSpConstProp : public PropOptimizePattern {
186 public:
FpSpConstProp(CGFunc & cgFunc,CGSSAInfo * cgssaInfo)187     FpSpConstProp(CGFunc &cgFunc, CGSSAInfo *cgssaInfo) : PropOptimizePattern(cgFunc, cgssaInfo) {}
188     ~FpSpConstProp() override = default;
189     bool CheckCondition(Insn &insn) final;
190     void Optimize(Insn &insn) final;
191     void Run() final;
192 
193 protected:
Init()194     void Init() final
195     {
196         fpSpBase = nullptr;
197         shiftOpnd = nullptr;
198         aT = kUndefArith;
199         replaced = nullptr;
200     }
201 
202 private:
203     bool GetValidSSAInfo(Operand &opnd);
204     void PropInMem(DUInsnInfo &useDUInfo, Insn &useInsn);
205     void PropInArith(DUInsnInfo &useDUInfo, Insn &useInsn, ArithmeticType curAT);
206     void PropInCopy(DUInsnInfo &useDUInfo, Insn &useInsn, MOperator oriMop);
207     int64 ArithmeticFold(int64 valInUse, ArithmeticType useAT) const;
208 
209     RegOperand *fpSpBase = nullptr;
210     ImmOperand *shiftOpnd = nullptr;
211     ArithmeticType aT = kUndefArith;
212     VRegVersion *replaced = nullptr;
213 };
214 
215 /*
216  * This pattern do:
217  * 1)
218  * uxtw vreg:Rm validBitNum:[64], vreg:Rn validBitNum:[32]
219  * ------>
220  * mov vreg:Rm validBitNum:[64], vreg:Rn validBitNum:[32]
221  * 2)
222  * ldrh  R201, [...]
223  * and R202, R201, #65520
224  * uxth  R203, R202
225  * ------->
226  * ldrh  R201, [...]
227  * and R202, R201, #65520
228  * mov  R203, R202
229  */
230 class ExtendMovPattern : public PropOptimizePattern {
231 public:
ExtendMovPattern(CGFunc & cgFunc,CGSSAInfo * cgssaInfo)232     ExtendMovPattern(CGFunc &cgFunc, CGSSAInfo *cgssaInfo) : PropOptimizePattern(cgFunc, cgssaInfo) {}
233     ~ExtendMovPattern() override = default;
234     bool CheckCondition(Insn &insn) final;
235     void Optimize(Insn &insn) final;
236     void Run() final;
237 
238 protected:
239     void Init() final;
240 
241 private:
242     bool BitNotAffected(const Insn &insn, uint32 validNum); /* check whether significant bits are affected */
243     bool CheckSrcReg(regno_t srcRegNo, uint32 validNum);
244 
245     MOperator replaceMop = MOP_undef;
246 };
247 
248 class ExtendShiftPattern : public PropOptimizePattern {
249 public:
ExtendShiftPattern(CGFunc & cgFunc,CGSSAInfo * cgssaInfo)250     ExtendShiftPattern(CGFunc &cgFunc, CGSSAInfo *cgssaInfo) : PropOptimizePattern(cgFunc, cgssaInfo) {}
251     ~ExtendShiftPattern() override = default;
252     bool IsSwapInsn(const Insn &insn) const;
253     void SwapOpnd(Insn &insn);
254     bool CheckAllOpndCondition(Insn &insn);
255     bool CheckCondition(Insn &insn) final;
256     void Optimize(Insn &insn) final;
257     void Run() final;
258     void DoExtendShiftOpt(Insn &insn);
259 
260     enum ExMOpType : uint8 {
261         kExUndef,
262         kExAdd, /* MOP_xaddrrr | MOP_xxwaddrrre | MOP_xaddrrrs */
263         kEwAdd, /* MOP_waddrrr | MOP_wwwaddrrre | MOP_waddrrrs */
264         kExSub, /* MOP_xsubrrr | MOP_xxwsubrrre | MOP_xsubrrrs */
265         kEwSub, /* MOP_wsubrrr | MOP_wwwsubrrre | MOP_wsubrrrs */
266         kExCmn, /* MOP_xcmnrr | MOP_xwcmnrre | MOP_xcmnrrs */
267         kEwCmn, /* MOP_wcmnrr | MOP_wwcmnrre | MOP_wcmnrrs */
268         kExCmp, /* MOP_xcmprr | MOP_xwcmprre | MOP_xcmprrs */
269         kEwCmp, /* MOP_wcmprr | MOP_wwcmprre | MOP_wcmprrs */
270     };
271 
272     enum LsMOpType : uint8 {
273         kLsUndef,
274         kLxAdd, /* MOP_xaddrrr | MOP_xaddrrrs */
275         kLwAdd, /* MOP_waddrrr | MOP_waddrrrs */
276         kLxSub, /* MOP_xsubrrr | MOP_xsubrrrs */
277         kLwSub, /* MOP_wsubrrr | MOP_wsubrrrs */
278         kLxCmn, /* MOP_xcmnrr | MOP_xcmnrrs */
279         kLwCmn, /* MOP_wcmnrr | MOP_wcmnrrs */
280         kLxCmp, /* MOP_xcmprr | MOP_xcmprrs */
281         kLwCmp, /* MOP_wcmprr | MOP_wcmprrs */
282         kLxEor, /* MOP_xeorrrr | MOP_xeorrrrs */
283         kLwEor, /* MOP_weorrrr | MOP_weorrrrs */
284         kLxNeg, /* MOP_xinegrr | MOP_xinegrrs */
285         kLwNeg, /* MOP_winegrr | MOP_winegrrs */
286         kLxIor, /* MOP_xiorrrr | MOP_xiorrrrs */
287         kLwIor, /* MOP_wiorrrr | MOP_wiorrrrs */
288     };
289 
290     enum SuffixType : uint8 {
291         kNoSuffix, /* no suffix or do not perform the optimization. */
292         kLSL,      /* logical shift left */
293         kLSR,      /* logical shift right */
294         kASR,      /* arithmetic shift right */
295         kExten     /* ExtendOp */
296     };
297 
298 protected:
299     void Init() final;
300 
301 private:
302     void SelectExtendOrShift(const Insn &def);
303     SuffixType CheckOpType(const Operand &lastOpnd) const;
304     void ReplaceUseInsn(Insn &use, const Insn &def, uint32 amount);
305     void SetExMOpType(const Insn &use);
306     void SetLsMOpType(const Insn &use);
307 
308     MOperator replaceOp;
309     uint32 replaceIdx;
310     ExtendShiftOperand::ExtendOp extendOp;
311     BitShiftOperand::ShiftOp shiftOp;
312     Insn *defInsn = nullptr;
313     Insn *newInsn = nullptr;
314     Insn *curInsn = nullptr;
315     bool optSuccess;
316     ExMOpType exMOpType;
317     LsMOpType lsMOpType;
318 };
319 
320 /*
321  * optimization for call convention
322  * example:
323  *                              [BB26]                      [BB43]
324  *                        sub R287, R101, R275        sub R279, R101, R275
325  *                                            \      /
326  *                                             \    /
327  *                                             [BB27]
328  *                                                <---- insert new phi: R403, (R275 <26>, R275 <43>)
329  *                                       old phi: R297, (R287 <26>, R279 <43>)
330  *                                               /          \
331  *                                              /            \
332  *                                           [BB28]           \
333  *                                       sub R310, R101, R309  \
334  *                                             |                \
335  *                                             |                 \
336  *            [BB17]                         [BB29]            [BB44]
337  *        sub R314, R101, R275                 |              /
338  *                                \            |             /
339  *                                 \           |            /
340  *                                  \          |           /
341  *                                   \         |          /
342  *                                           [BB18]
343  *                                               <---- insert new phi: R404, (R275 <17>, R309 <29>, R403 <44>)
344  *                                       old phi: R318, (R314 <17>, R310 <29>, R297 <44>)
345  *                                       mov R1, R318    ====>    sub R1, R101, R404
346  *                                          /                   \
347  *                                         /                     \
348  *                                        /                       \
349  *                                     [BB19]                   [BB34]
350  *                              sub R336, R101, R335           /
351  *                                               \            /
352  *                                                \          /
353  *                                                 \        /
354  *                                                   [BB20]
355  *                                                      <---- insert new phi: R405, (R335 <19>, R404<34>)
356  *                                                old phi: R340, (R336 <19>, R318 <34>)
357  *                                                mov R1, R340      ====>     sub R1, R101, R405
358  */
359 class A64PregCopyPattern : public PropOptimizePattern {
360 public:
A64PregCopyPattern(CGFunc & cgFunc,CGSSAInfo * cgssaInfo)361     A64PregCopyPattern(CGFunc &cgFunc, CGSSAInfo *cgssaInfo) : PropOptimizePattern(cgFunc, cgssaInfo) {}
~A64PregCopyPattern()362     ~A64PregCopyPattern() override
363     {
364         firstPhiInsn = nullptr;
365     }
366     bool CheckCondition(Insn &insn) override;
367     void Optimize(Insn &insn) override;
368     void Run() override;
369 
370 protected:
Init()371     void Init() override
372     {
373         validDefInsns.clear();
374         firstPhiInsn = nullptr;
375         differIdx = -1;
376         differOrigNO = 0;
377         isCrossPhi = false;
378     }
379 
380 private:
381     bool CheckUselessDefInsn(const Insn *defInsn) const;
382     bool CheckValidDefInsn(const Insn *defInsn);
383     bool CheckMultiUsePoints(const Insn *defInsn) const;
384     bool CheckPhiCaseCondition(Insn &curInsn, Insn &defInsn);
385     bool DFSFindValidDefInsns(Insn *curDefInsn, RegOperand *lastPhiDef, std::unordered_map<uint32, bool> &visited);
386     Insn &CreateNewPhiInsn(std::unordered_map<uint32, RegOperand *> &newPhiList, Insn *curInsn);
387     RegOperand &DFSBuildPhiInsn(Insn *curInsn, std::unordered_map<uint32, RegOperand *> &visited);
388     RegOperand *CheckAndGetExistPhiDef(Insn &phiInsn, std::vector<regno_t> &validDifferRegNOs) const;
389     std::vector<Insn *> validDefInsns;
390     Insn *firstPhiInsn = nullptr;
391     int differIdx = -1;
392     regno_t differOrigNO = 0;
393     bool isCrossPhi = false;
394 };
395 
396 class A64ReplaceRegOpndVisitor : public ReplaceRegOpndVisitor {
397 public:
A64ReplaceRegOpndVisitor(CGFunc & f,Insn & cInsn,uint32 cIdx,RegOperand & oldRegister,RegOperand & newRegister)398     A64ReplaceRegOpndVisitor(CGFunc &f, Insn &cInsn, uint32 cIdx, RegOperand &oldRegister, RegOperand &newRegister)
399         : ReplaceRegOpndVisitor(f, cInsn, cIdx, oldRegister, newRegister)
400     {
401     }
402     ~A64ReplaceRegOpndVisitor() override = default;
403 
404 private:
405     void Visit(RegOperand *v) final;
406     void Visit(ListOperand *v) final;
407     void Visit(MemOperand *v) final;
408     void Visit(PhiOperand *v) final;
409 };
410 }  // namespace maplebe
411 #endif /* MAPLEBE_INCLUDE_AARCH64_PROP_H */
412