• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #ifndef MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_MOP_SPLIT_H
16 #define MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_MOP_SPLIT_H
17 
18 #include "aarch64_cg.h"
19 #include "aarch64_isa.h"
20 #include "cg_irbuilder.h"
21 #include "cgbb.h"
22 #include "common_utils.h"
23 
24 namespace maplebe {
25 // Supply a new reg operand for insn split process, which type is kRegTyInt for immediate.
26 // Before regalloc: create a new virtual reg;
27 // After regalloc: use R16 to be a temporary physical reg.
GetSplitBaseReg(bool isAfterRegAlloc,bool is64Bits,OperandBuilder * opndBuilder)28 inline RegOperand *GetSplitBaseReg(bool isAfterRegAlloc, bool is64Bits, OperandBuilder *opndBuilder)
29 {
30     RegOperand *resOpnd = nullptr;
31     if (!isAfterRegAlloc) {
32         resOpnd = &opndBuilder->CreateVReg((is64Bits ? k64BitSize : k32BitSize), kRegTyInt);
33     } else {
34         resOpnd = &opndBuilder->CreatePReg(R16, (is64Bits ? k64BitSize : k32BitSize), kRegTyInt);
35     }
36     return resOpnd;
37 }
38 
39 // Judging valid range of the immediate by passing in bitLen & forPair parameter, return the closest valid value to
40 // ofstVal, getting the remainder simultaneously. The valid value will be input in new memopnd, and the remainder
41 // will be input in add insn.
SplitGetRemained(const MemOperand & memOpnd,uint32 bitLen,int64 ofstVal,bool forPair,OperandBuilder * opndBuilder)42 inline ImmOperand &SplitGetRemained(const MemOperand &memOpnd, uint32 bitLen, int64 ofstVal, bool forPair,
43                                     OperandBuilder *opndBuilder)
44 {
45     // opndVal == Q0 * 32760(16380) + R0
46     // R0 == Q1 * 8(4) + R1
47     // ADDEND == Q0 * 32760(16380) + R1
48     // NEW_OFFSET = Q1 * 8(4)
49     // we want to generate two instructions:
50     // ADD TEMP_REG, X29, ADDEND
51     // LDR/STR TEMP_REG, [ TEMP_REG, #NEW_OFFSET ]
52     int32 maxPimm = 0;
53     if (!forPair) {
54         maxPimm = MemOperand::GetMaxPIMM(bitLen);
55     } else {
56         maxPimm = MemOperand::GetMaxPairPIMM(bitLen);
57     }
58     DEBUG_ASSERT(maxPimm != 0, "get max pimm failed");
59     int64 q0 = ofstVal / maxPimm + (ofstVal < 0 ? -1 : 0);
60     int64 addend = q0 * maxPimm;
61     uint64 r0 = static_cast<uint64>(ofstVal - addend);
62     uint64 alignment = static_cast<uint64>(static_cast<int64>(MemOperand::GetImmediateOffsetAlignment(bitLen)));
63     auto q1 = r0 >> alignment;
64     auto r1 = static_cast<int64>(r0 & ((1u << alignment) - 1));
65     auto remained = static_cast<int64>(q1 << alignment);
66     addend = addend + r1;
67     if (addend > 0) {
68         uint64 suffixClear = 0xfff;
69         if (forPair) {
70             suffixClear = 0xff;
71         }
72         int64 remainedTmp = remained + static_cast<int64>(static_cast<uint64>(addend) & suffixClear);
73         if (!MemOperand::IsPIMMOffsetOutOfRange(static_cast<int32>(remainedTmp), bitLen) &&
74             ((static_cast<uint64>(remainedTmp) & ((1u << alignment) - 1)) == 0)) {
75             addend = static_cast<int64>(static_cast<uint64>(addend) & ~suffixClear);
76         }
77     }
78     ImmOperand &immAddend = opndBuilder->CreateImm(k64BitSize, addend, true);
79     if (memOpnd.GetOffsetImmediate()->GetVary() == kUnAdjustVary) {
80         immAddend.SetVary(kUnAdjustVary);
81     }
82     return immAddend;
83 }
84 
85 // Split Add Insn add reg, reg, #imm, steps as follows:
86 // If #imm value range 0 ~ 2^24 - 1, insn will be split into add reg, reg, #imm(, LSL 12)
87 // If #imm value out of range 2^24, insn will be split as follows:
88 // add  x0, x1, #imm    ====>    mov  x2, #imm
89 //                               add  x0, x1, x2
AddInsnSplit(Insn * insn,bool is64Bits,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)90 inline void AddInsnSplit(Insn *insn, bool is64Bits, bool isAfterRegAlloc, InsnBuilder *insnBuilder,
91                          OperandBuilder *opndBuilder)
92 {
93     if (insn->VerifySelf()) {
94         return;
95     }
96     Operand *opnd0 = &insn->GetOperand(kInsnFirstOpnd);
97     Operand *opnd1 = &insn->GetOperand(kInsnSecondOpnd);
98     Operand *opnd2 = &insn->GetOperand(kInsnThirdOpnd);
99     ImmOperand *oldImmOpnd = static_cast<ImmOperand *>(opnd2);
100     ImmOperand *immOpnd =
101         &opndBuilder->CreateImm(oldImmOpnd->GetSize(), oldImmOpnd->GetValue(), oldImmOpnd->IsSignedValue());
102     immOpnd->SetVary(oldImmOpnd->GetVary());
103     insn->SetOperand(kInsnThirdOpnd, *immOpnd);
104     MOperator mOpCode = MOP_undef;
105     if (immOpnd->IsNegative()) {
106         immOpnd->Negate();
107         mOpCode = is64Bits ? MOP_xsubrri12 : MOP_wsubrri12;
108         insn->SetMOP(AArch64CG::kMd[mOpCode]);
109         if (!insn->VerifySelf()) {
110             insn->SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder);
111         }
112         return;
113     }
114     BB *bb = insn->GetBB();
115     // lower 24 bits has 1, higher bits are all 0
116     if (immOpnd->IsInBitSize(kMaxImmVal24Bits, 0)) {
117         // lower 12 bits and higher 12 bits both has 1
118         Operand *newOpnd1 = opnd1;
119         if (!(immOpnd->IsInBitSize(kMaxImmVal12Bits, 0) || immOpnd->IsInBitSize(kMaxImmVal12Bits, kMaxImmVal12Bits))) {
120             // process higher 12 bits
121             ImmOperand &immOpnd2 = opndBuilder->CreateImm(
122                 immOpnd->GetSize(), static_cast<int64>(static_cast<uint64>(immOpnd->GetValue()) >> kMaxImmVal12Bits),
123                 immOpnd->IsSignedValue());
124             mOpCode = is64Bits ? MOP_xaddrri24 : MOP_waddrri24;
125             RegOperand *tmpRes = GetSplitBaseReg(isAfterRegAlloc, is64Bits, opndBuilder);
126             BitShiftOperand &shiftopnd = opndBuilder->CreateBitShift(BitShiftOperand::kLSL, k12BitSize, k64BitSize);
127             Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *tmpRes, *opnd1, immOpnd2, shiftopnd);
128             newInsn.SetBB(bb);
129             DEBUG_ASSERT(newInsn.VerifySelf(), "immOpnd2 appears invalid");
130             (void)bb->InsertInsnBefore(*insn, newInsn);
131             // get lower 12 bits value
132             immOpnd->ModuloByPow2(kMaxImmVal12Bits);
133             newOpnd1 = tmpRes;
134         }
135         // process lower 12 bits value
136         mOpCode = is64Bits ? MOP_xaddrri12 : MOP_waddrri12;
137         // It`s worth noting that if immOpnd->IsInBitSize(12, 12) returns true, gcc assembler can compile correctly,
138         // so we pass immOpnd directly as a parameter.
139         Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *newOpnd1, *immOpnd);
140         newInsn.SetBB(bb);
141         DEBUG_ASSERT(newInsn.VerifySelf(), "immOpnd appears invalid");
142         bb->ReplaceInsn(*insn, newInsn);
143         return;
144     } else {
145         // load into register
146         int64 immVal = immOpnd->GetValue();
147         int32 tail0bitNum = AArch64isa::GetTail0BitNum(immVal);
148         int32 head0bitNum = AArch64isa::GetHead0BitNum(immVal);
149         const int32 bitNum = (k64BitSizeInt - head0bitNum) - tail0bitNum;
150         RegOperand *movOpnd = GetSplitBaseReg(isAfterRegAlloc, is64Bits, opndBuilder);
151         regno_t regNO0 = static_cast<RegOperand *>(opnd1)->GetRegisterNumber();
152         // The content of the next if code block is when immvalue can be moved in one insn, we do next:
153         // add  x0, x1, #imm1    ====>    mov  x2, #imm2
154         //                                add  x0, x1, x2, LSL <shift>
155         // #imm2 = #imm1 >> shift
156         // addrrrs do not support sp
157         if (bitNum <= k16BitSizeInt && regNO0 != RSP) {
158             int64 newImm =
159                 static_cast<int64>((static_cast<uint64>(immVal) >> static_cast<uint32>(tail0bitNum)) & 0xFFFF);
160             ImmOperand &immOpnd1 = opndBuilder->CreateImm(k16BitSize, newImm, false);
161             mOpCode = is64Bits ? MOP_xmovri64 : MOP_wmovri32;
162             Insn &movInsn = insnBuilder->BuildInsn(mOpCode, *movOpnd, immOpnd1);
163             movInsn.SetBB(bb);
164             (void)bb->InsertInsnBefore(*insn, movInsn);
165             mOpCode = is64Bits ? MOP_xaddrrrs : MOP_waddrrrs;
166             // bitLen means bitshiftopnd size: 64bits -> 6, 32bits ->5
167             uint32 bitLen = is64Bits ? k6BitSize : k5BitSize;
168             BitShiftOperand &bitShiftOpnd =
169                 opndBuilder->CreateBitShift(BitShiftOperand::kLSL, static_cast<uint32>(tail0bitNum), bitLen);
170             Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *opnd1, *movOpnd, bitShiftOpnd);
171             newInsn.SetBB(bb);
172             bb->ReplaceInsn(*insn, newInsn);
173             return;
174         }
175         mOpCode = is64Bits ? MOP_xmovri64 : MOP_wmovri32;
176         Insn &movInsn = insnBuilder->BuildInsn(mOpCode, *movOpnd, *immOpnd);
177         movInsn.SetBB(bb);
178         mOpCode = is64Bits ? MOP_xaddrrr : MOP_waddrrr;
179         Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *opnd1, *movOpnd);
180         newInsn.SetBB(bb);
181         (void)bb->InsertInsnBefore(*insn, movInsn);
182         // If #imm of mov is invalid, split mov insn
183         if (!movInsn.VerifySelf()) {
184             movInsn.SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder);
185         }
186         bb->ReplaceInsn(*insn, newInsn);
187     }
188 }
189 
190 // Split Sub Insn sub reg, reg, #imm, the same split steps as add
SubInsnSplit(Insn * insn,bool is64Bits,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)191 inline void SubInsnSplit(Insn *insn, bool is64Bits, bool isAfterRegAlloc, InsnBuilder *insnBuilder,
192                          OperandBuilder *opndBuilder)
193 {
194     if (insn->VerifySelf()) {
195         return;
196     }
197     Operand *opnd0 = &insn->GetOperand(kInsnFirstOpnd);
198     Operand *opnd1 = &insn->GetOperand(kInsnSecondOpnd);
199     Operand *opnd2 = &insn->GetOperand(kInsnThirdOpnd);
200     ImmOperand *oldImmOpnd = static_cast<ImmOperand *>(opnd2);
201     ImmOperand *immOpnd =
202         &opndBuilder->CreateImm(oldImmOpnd->GetSize(), oldImmOpnd->GetValue(), oldImmOpnd->IsSignedValue());
203     immOpnd->SetVary(oldImmOpnd->GetVary());
204     insn->SetOperand(kInsnThirdOpnd, *immOpnd);
205     MOperator mOpCode = MOP_undef;
206     if (immOpnd->IsNegative()) {
207         immOpnd->Negate();
208         mOpCode = is64Bits ? MOP_xaddrri12 : MOP_waddrri12;
209         insn->SetMOP(AArch64CG::kMd[mOpCode]);
210         if (!insn->VerifySelf()) {
211             insn->SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder);
212         }
213         return;
214     }
215     BB *bb = insn->GetBB();
216     int64 higher12BitVal = static_cast<int64>(static_cast<uint64>(immOpnd->GetValue()) >> kMaxImmVal12Bits);
217     if (immOpnd->IsInBitSize(kMaxImmVal24Bits, 0) && higher12BitVal + 1 <= kMaxPimm8) {
218         // SUB Wd|WSP, Wn|WSP, #imm{, shift} ; 32-bit general registers
219         // SUB Xd|SP,  Xn|SP,  #imm{, shift} ; 64-bit general registers
220         // imm : 0 ~ 4095, shift: none, LSL #0, or LSL #12
221         // aarch64 assembly takes up to 24-bits, if the lower 12 bits is all 0
222         // large offset is treated as sub (higher 12 bits + 4096) + add
223         // it gives opportunities for combining add + ldr due to the characteristics of aarch64's load/store
224         bool isSplitSub = false;
225         Operand *newOpnd1 = opnd1;
226         if (!(immOpnd->IsInBitSize(kMaxImmVal12Bits, 0) || immOpnd->IsInBitSize(kMaxImmVal12Bits, kMaxImmVal12Bits))) {
227             isSplitSub = true;
228             // process higher 12 bits
229             ImmOperand &immOpnd2 =
230                 opndBuilder->CreateImm(immOpnd->GetSize(), higher12BitVal + 1, immOpnd->IsSignedValue());
231             mOpCode = is64Bits ? MOP_xsubrri24 : MOP_wsubrri24;
232             RegOperand *resOpnd = GetSplitBaseReg(isAfterRegAlloc, is64Bits, opndBuilder);
233             BitShiftOperand &shiftopnd = opndBuilder->CreateBitShift(BitShiftOperand::kLSL, k12BitSize, k64BitSize);
234             Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *resOpnd, *opnd1, immOpnd2, shiftopnd);
235             newInsn.SetBB(bb);
236             (void)bb->InsertInsnBefore(*insn, newInsn);
237             immOpnd->ModuloByPow2(kMaxImmVal12Bits);
238             immOpnd->SetValue(static_cast<int64>(kMax12UnsignedImm) - immOpnd->GetValue());
239             newOpnd1 = resOpnd;
240         }
241         // process lower 12 bits
242         mOpCode = isSplitSub ? (is64Bits ? MOP_xaddrri12 : MOP_waddrri12) : (is64Bits ? MOP_xsubrri12 : MOP_wsubrri12);
243         Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *newOpnd1, *immOpnd);
244         newInsn.SetBB(bb);
245         bb->ReplaceInsn(*insn, newInsn);
246         return;
247     } else {
248         // load into register
249         int64 immVal = immOpnd->GetValue();
250         int32 tail0bitNum = AArch64isa::GetTail0BitNum(immVal);
251         int32 head0bitNum = AArch64isa::GetHead0BitNum(immVal);
252         const int32 bitNum = (k64BitSizeInt - head0bitNum) - tail0bitNum;
253         RegOperand *movOpnd = GetSplitBaseReg(isAfterRegAlloc, is64Bits, opndBuilder);
254         // The content of the next if code block is when immvalue can be moved in one insn, we do next:
255         // sub  x0, x1, #imm1    ====>    mov  x2, #imm2
256         //                                sub  x0, x1, x2, LSL <shift>
257         // #imm2 = #imm1 >> shift
258         // subrrrs supports sp, so do not need to check whether regNo is RSP
259         if (bitNum <= k16BitSizeInt) {
260             int64 newImm =
261                 static_cast<int64>((static_cast<uint64>(immVal) >> static_cast<uint32>(tail0bitNum)) & 0xFFFF);
262             ImmOperand &immOpnd1 = opndBuilder->CreateImm(k16BitSize, newImm, false);
263             mOpCode = is64Bits ? MOP_xmovri64 : MOP_wmovri32;
264             Insn &movInsn = insnBuilder->BuildInsn(mOpCode, *movOpnd, immOpnd1);
265             movInsn.SetBB(bb);
266             (void)bb->InsertInsnBefore(*insn, movInsn);
267             mOpCode = is64Bits ? MOP_xsubrrrs : MOP_wsubrrrs;
268             // bitLen means bitshiftopnd size: 64bits -> 6, 32bits ->5
269             uint32 bitLen = is64Bits ? k6BitSize : k5BitSize;
270             BitShiftOperand &bitShiftOpnd =
271                 opndBuilder->CreateBitShift(BitShiftOperand::kLSL, static_cast<uint32>(tail0bitNum), bitLen);
272             Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *opnd1, *movOpnd, bitShiftOpnd);
273             newInsn.SetBB(bb);
274             bb->ReplaceInsn(*insn, newInsn);
275             return;
276         }
277         mOpCode = is64Bits ? MOP_xmovri64 : MOP_wmovri32;
278         Insn &movInsn = insnBuilder->BuildInsn(mOpCode, *movOpnd, *immOpnd);
279         movInsn.SetBB(bb);
280         mOpCode = is64Bits ? MOP_xsubrrr : MOP_wsubrrr;
281         Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *opnd1, *movOpnd);
282         newInsn.SetBB(bb);
283         (void)bb->InsertInsnBefore(*insn, movInsn);
284         // If #imm of mov is invalid, split mov insn
285         if (!movInsn.VerifySelf()) {
286             movInsn.SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder);
287         }
288         bb->ReplaceInsn(*insn, newInsn);
289     }
290 }
291 
292 // adds & subs updates the condition flags based on the result, so it cannot be split into multiple instructions
293 // of the same type, because we don`t know when the result is out of range and changes flags. The solution is:
294 // adds/subs  x0, x1, #imm    ====>    mov        x2, #imm
295 //                                     adds/subs  x0, x1, x2
296 // isAdds: true -> adds, false -> subs
AddsSubsInsnSplit(Insn * insn,bool isAdds,bool is64Bits,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)297 inline void AddsSubsInsnSplit(Insn *insn, bool isAdds, bool is64Bits, bool isAfterRegAlloc, InsnBuilder *insnBuilder,
298                               OperandBuilder *opndBuilder)
299 {
300     if (insn->VerifySelf()) {
301         return;
302     }
303     Operand *opnd0 = &insn->GetOperand(kInsnFirstOpnd);
304     Operand *opnd1 = &insn->GetOperand(kInsnSecondOpnd);
305     Operand *opnd2 = &insn->GetOperand(kInsnThirdOpnd);
306     Operand *opnd3 = &insn->GetOperand(kInsnFourthOpnd);
307     ImmOperand *immOpnd = static_cast<ImmOperand *>(opnd3);
308     MOperator mOpCode = MOP_undef;
309     BB *bb = insn->GetBB();
310     RegOperand *movOpnd = GetSplitBaseReg(isAfterRegAlloc, is64Bits, opndBuilder);
311     mOpCode = is64Bits ? MOP_xmovri64 : MOP_wmovri32;
312     Insn &movInsn = insnBuilder->BuildInsn(mOpCode, *movOpnd, *immOpnd);
313     movInsn.SetBB(bb);
314     mOpCode = isAdds ? (is64Bits ? MOP_xaddsrrr : MOP_waddsrrr) : (is64Bits ? MOP_xsubsrrr : MOP_wsubsrrr);
315     Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *opnd1, *opnd2, *movOpnd);
316     newInsn.SetBB(bb);
317     (void)bb->InsertInsnBefore(*insn, movInsn);
318     // If #imm of mov is invalid, split mov first.
319     if (!movInsn.VerifySelf()) {
320         movInsn.SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder);
321     }
322     (void)bb->InsertInsnBefore(*insn, newInsn);
323     bb->RemoveInsn(*insn);
324 }
325 
326 // Split Add/Sub Insn with BitShiftOperand (LSL 12), steps as follows:
327 // add/sub  x0, x1, #imm, LSL 12   ====>   add/sub  x0, x1, #newimm   ====>   Add/SubInsnSplit
328 // isAdd: true -> add, false -> sub
AddSubWithLslSplit(Insn * insn,bool isAdd,bool is64Bits,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)329 inline void AddSubWithLslSplit(Insn *insn, bool isAdd, bool is64Bits, bool isAfterRegAlloc, InsnBuilder *insnBuilder,
330                                OperandBuilder *opndBuilder)
331 {
332     if (insn->VerifySelf()) {
333         return;
334     }
335     uint32 size = is64Bits ? k64BitSize : k32BitSize;
336     ImmOperand &immOpnd = static_cast<ImmOperand &>(insn->GetOperand(kInsnThirdOpnd));
337     // add/sub x0, x1, #imm, LSL 12  ====>  imm value range can be split: 2^12 ~ 2^52 - 1
338     // add/sub w0, w1, #imm, LSL 12  ====>  imm value range can be split: 2^12 ~ 2^20 - 1
339     // If imm is out of range, insn will not be split
340     if (!immOpnd.IsInBitSize((size - k12BitSize), k0BitSize)) {
341         return;
342     }
343     BB *bb = insn->GetBB();
344     ImmOperand &newImmOpnd =
345         opndBuilder->CreateImm(size, static_cast<int64>(static_cast<uint64>(immOpnd.GetValue()) << k12BitSize));
346     MOperator mOpCode = is64Bits ? (isAdd ? MOP_xaddrri12 : MOP_xsubrri12) : (isAdd ? MOP_waddrri12 : MOP_wsubrri12);
347     Insn &newInsn = insnBuilder->BuildInsn(mOpCode, insn->GetOperand(kInsnFirstOpnd), insn->GetOperand(kInsnSecondOpnd),
348                                            newImmOpnd);
349     newInsn.SetBB(bb);
350     bb->ReplaceInsn(*insn, newInsn);
351     if (!newInsn.VerifySelf()) {
352         newInsn.SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder);
353     }
354 }
355 
356 // Split memoperand with invalid offset value to a new valid memoperand and add insn with remainder.
MemOfstSplitWithAdd(const MemOperand & memOpnd,uint32 bitLen,bool isAfterRegAlloc,Insn * insn,bool forPair,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)357 inline MemOperand &MemOfstSplitWithAdd(const MemOperand &memOpnd, uint32 bitLen, bool isAfterRegAlloc, Insn *insn,
358                                        bool forPair, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
359 {
360     DEBUG_ASSERT((memOpnd.GetAddrMode() == MemOperand::kAddrModeBOi), "expect kAddrModeBOi memOpnd");
361     DEBUG_ASSERT(memOpnd.IsIntactIndexed(), "expect intactIndexed memOpnd");
362     BB *bb = insn->GetBB();
363     OfstOperand *ofstOpnd = memOpnd.GetOffsetImmediate();
364     int64 ofstVal = ofstOpnd->GetOffsetValue();
365     RegOperand *resOpnd = GetSplitBaseReg(isAfterRegAlloc, true, opndBuilder);
366     ImmOperand &immAddend = SplitGetRemained(memOpnd, bitLen, ofstVal, forPair, opndBuilder);
367     int64 remained = (ofstVal - immAddend.GetValue());
368     RegOperand *origBaseReg = memOpnd.GetBaseRegister();
369     DEBUG_ASSERT(origBaseReg != nullptr, "nullptr check");
370     // Provide add insn to split offset, where add insn is 64-bit explicitly
371     Insn &addInsn = insnBuilder->BuildInsn(MOP_xaddrri12, *resOpnd, *origBaseReg, immAddend);
372     addInsn.SetBB(bb);
373     bb->InsertInsnBefore(*insn, addInsn);
374     if (!addInsn.VerifySelf()) {
375         addInsn.SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder);
376     }
377     ImmOperand &remainedOpnd = opndBuilder->CreateImm(k32BitSize, remained, true);
378     MemOperand &newMemOpnd = opndBuilder->CreateMem(bitLen, *resOpnd, remainedOpnd);
379     newMemOpnd.SetStackMem(memOpnd.IsStackMem());
380     return newMemOpnd;
381 }
382 
383 // Split a load/store insn with invalid offset value to a new valid insn and add insn.
384 // idx: memOperand index of insn
LoadStoreInsnSplit(Insn * insn,uint32 idx,bool forPair,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)385 inline void LoadStoreInsnSplit(Insn *insn, uint32 idx, bool forPair, bool isAfterRegAlloc, InsnBuilder *insnBuilder,
386                                OperandBuilder *opndBuilder)
387 {
388     if (insn->VerifySelf()) {
389         return;
390     }
391     MemOperand &memOpnd = static_cast<MemOperand &>(insn->GetOperand(idx));
392     if (!(memOpnd.GetAddrMode() == MemOperand::kAddrModeBOi && memOpnd.IsIntactIndexed())) {
393         return;
394     }
395     uint32 bitLen = insn->GetDesc()->GetOpndDes(idx)->GetSize();
396     MemOperand &newMemOpnd =
397         MemOfstSplitWithAdd(memOpnd, bitLen, isAfterRegAlloc, insn, forPair, insnBuilder, opndBuilder);
398     insn->SetOperand(idx, newMemOpnd);
399 }
400 
401 // ccmp updates the condition flags based on the result, so it cannot be split into multiple instructions
402 // of the same type, because we don`t know when the result is out of range and changes flags. The solution is:
403 // ccmp  <Xn>, #<imm>, #<nzcv>, <cond>    ====>    mov   <Xm>, #<imm>
404 //                                                 ccmp  <Xn>, <Xm>, #<nzcv>, <cond>
CondCompareInsnSplit(Insn * insn,bool is64Bits,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)405 inline void CondCompareInsnSplit(Insn *insn, bool is64Bits, bool isAfterRegAlloc, InsnBuilder *insnBuilder,
406                                  OperandBuilder *opndBuilder)
407 {
408     if (insn->VerifySelf()) {
409         return;
410     }
411     ImmOperand &immOpnd = static_cast<ImmOperand &>(insn->GetOperand(kInsnSecondOpnd));
412     MOperator mOpCode = MOP_undef;
413     BB *bb = insn->GetBB();
414     RegOperand *movOpnd = GetSplitBaseReg(isAfterRegAlloc, is64Bits, opndBuilder);
415     mOpCode = is64Bits ? MOP_xmovri64 : MOP_wmovri32;
416     Insn &movInsn = insnBuilder->BuildInsn(mOpCode, *movOpnd, immOpnd);
417     movInsn.SetBB(bb);
418     bb->InsertInsnBefore(*insn, movInsn);
419     if (!movInsn.VerifySelf()) {
420         movInsn.SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder);
421     }
422     mOpCode = is64Bits ? MOP_xccmprric : MOP_wccmprric;
423     insn->SetMOP(AArch64CG::kMd[mOpCode]);
424     insn->SetOperand(kInsnSecondOpnd, *movOpnd);
425 }
426 
427 // split mov w0, #imm to mov and movk
MOP_wmovri32Split(Insn * curInsn,bool,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)428 inline void MOP_wmovri32Split(Insn *curInsn, bool /* isAfterRegAlloc */, InsnBuilder *insnBuilder,
429                               OperandBuilder *opndBuilder)
430 {
431     // If higher 32bits of immVal have 1, we will truncate and keep lower 32 bits.
432     int64 immVal = static_cast<int64>(
433         static_cast<uint64>(static_cast<ImmOperand &>(curInsn->GetOperand(kInsnSecondOpnd)).GetValue()) &
434         0x00000000FFFFFFFFULL);
435     ImmOperand &immOpnd = opndBuilder->CreateImm(k64BitSize, immVal, true);
436     curInsn->SetOperand(kInsnSecondOpnd, immOpnd);
437     if (curInsn->VerifySelf()) {
438         return;
439     }
440     RegOperand &destReg = static_cast<RegOperand &>(curInsn->GetOperand(kInsnFirstOpnd));
441     auto *bb = curInsn->GetBB();
442     uint64 chunkVal0 = static_cast<uint64>(immVal) & 0x0000FFFFULL;
443     ImmOperand &src0 = opndBuilder->CreateImm(k16BitSize, static_cast<int64>(chunkVal0), false);
444     Insn &movInsn = insnBuilder->BuildInsn(MOP_wmovri32, destReg, src0);
445     movInsn.SetBB(bb);
446     (void)bb->InsertInsnBefore(*curInsn, movInsn);
447     uint64 chunkVal1 = (static_cast<uint64>(immVal) >> k16BitSize) & 0x0000FFFFULL;
448     ImmOperand &src16 = opndBuilder->CreateImm(k16BitSize, static_cast<int64>(chunkVal1), false);
449     BitShiftOperand *lslOpnd = &opndBuilder->CreateBitShift(BitShiftOperand::kLSL, static_cast<uint32>(k16BitSize), 6);
450     Insn &movkInsn = insnBuilder->BuildInsn(MOP_wmovkri16, destReg, src16, *lslOpnd);
451     movkInsn.SetBB(bb);
452     (void)bb->InsertInsnBefore(*curInsn, movkInsn);
453     bb->RemoveInsn(*curInsn);
454 }
455 
456 // split mov x0, #imm to movz/movn and movk
MOP_xmovri64Split(Insn * curInsn,bool,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)457 inline void MOP_xmovri64Split(Insn *curInsn, bool /* isAfterRegAlloc */, InsnBuilder *insnBuilder,
458                               OperandBuilder *opndBuilder)
459 {
460     if (curInsn->VerifySelf()) {
461         return;
462     }
463     RegOperand &destReg = static_cast<RegOperand &>(curInsn->GetOperand(kInsnFirstOpnd));
464     int64 immVal = static_cast<ImmOperand &>(curInsn->GetOperand(kInsnSecondOpnd)).GetValue();
465     bool useMovz = BetterUseMOVZ(static_cast<uint64>(immVal));
466     bool useMovk = false;
467     // get lower 32 bits of the immediate
468     uint64 chunkLval = static_cast<uint64>(immVal) & 0xFFFFFFFFULL;
469     // get upper 32 bits of the immediate
470     uint64 chunkHval = (static_cast<uint64>(immVal) >> k32BitSize) & 0xFFFFFFFFULL;
471     int32 maxLoopTime = 4;
472     if (chunkLval == chunkHval) {
473         // compute lower 32 bits, and then copy to higher 32 bits, so only 2 chunks need be processed
474         maxLoopTime = 2;
475     }
476     uint64 sa = 0;
477     auto *bb = curInsn->GetBB();
478     for (int64 i = 0; i < maxLoopTime; ++i, sa += k16BitSize) {
479         // create an imm opereand which represents the i-th 16-bit chunk of the immediate
480         uint64 chunkVal = (static_cast<uint64>(immVal) >> sa) & 0x0000FFFFULL;
481         if (useMovz ? (chunkVal == 0) : (chunkVal == 0x0000FFFFULL)) {
482             continue;
483         }
484         ImmOperand &src16 = opndBuilder->CreateImm(k16BitSize, static_cast<int64>(chunkVal), false);
485         BitShiftOperand *lslOpnd = &opndBuilder->CreateBitShift(BitShiftOperand::kLSL, static_cast<uint32>(sa), 6);
486         Insn *newInsn = nullptr;
487         if (!useMovk) {
488             // use movz or movn
489             if (!useMovz) {
490                 src16.BitwiseNegate();
491             }
492             MOperator mOpCode = useMovz ? MOP_xmovzri16 : MOP_xmovnri16;
493             newInsn = &insnBuilder->BuildInsn(mOpCode, destReg, src16, *lslOpnd);
494             newInsn->SetBB(bb);
495             useMovk = true;
496         } else {
497             newInsn = &insnBuilder->BuildInsn(MOP_xmovkri16, destReg, src16, *lslOpnd);
498             newInsn->SetBB(bb);
499         }
500         (void)bb->InsertInsnBefore(*curInsn, *newInsn);
501     }
502     constexpr int32 loopTime = 2;
503     if (maxLoopTime == loopTime) {
504         // copy lower 32 bits to higher 32 bits
505         ImmOperand &immOpnd = opndBuilder->CreateImm(k8BitSize, k32BitSize, false);
506         Insn &insn = insnBuilder->BuildInsn(MOP_xbfirri6i6, destReg, destReg, immOpnd, immOpnd);
507         insn.SetBB(bb);
508         (void)bb->InsertInsnBefore(*curInsn, insn);
509     }
510     bb->RemoveInsn(*curInsn);
511 }
512 
MOP_xaddrri24Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)513 inline void MOP_xaddrri24Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
514 {
515     AddSubWithLslSplit(insn, true, true, isAfterRegAlloc, insnBuilder, opndBuilder);
516 }
517 
MOP_xaddrri12Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)518 inline void MOP_xaddrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
519 {
520     AddInsnSplit(insn, true, isAfterRegAlloc, insnBuilder, opndBuilder);
521 }
522 
MOP_xaddsrri12Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)523 inline void MOP_xaddsrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
524 {
525     AddsSubsInsnSplit(insn, true, true, isAfterRegAlloc, insnBuilder, opndBuilder);
526 }
527 
MOP_waddrri24Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)528 inline void MOP_waddrri24Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
529 {
530     AddSubWithLslSplit(insn, true, false, isAfterRegAlloc, insnBuilder, opndBuilder);
531 }
532 
MOP_waddrri12Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)533 inline void MOP_waddrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
534 {
535     AddInsnSplit(insn, false, isAfterRegAlloc, insnBuilder, opndBuilder);
536 }
537 
MOP_waddsrri12Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)538 inline void MOP_waddsrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
539 {
540     AddsSubsInsnSplit(insn, true, false, isAfterRegAlloc, insnBuilder, opndBuilder);
541 }
542 
MOP_xsubrri24Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)543 inline void MOP_xsubrri24Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
544 {
545     AddSubWithLslSplit(insn, false, true, isAfterRegAlloc, insnBuilder, opndBuilder);
546 }
547 
MOP_xsubrri12Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)548 inline void MOP_xsubrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
549 {
550     SubInsnSplit(insn, true, isAfterRegAlloc, insnBuilder, opndBuilder);
551 }
552 
MOP_xsubsrri12Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)553 inline void MOP_xsubsrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
554 {
555     AddsSubsInsnSplit(insn, false, true, isAfterRegAlloc, insnBuilder, opndBuilder);
556 }
557 
MOP_wsubrri24Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)558 inline void MOP_wsubrri24Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
559 {
560     AddSubWithLslSplit(insn, false, false, isAfterRegAlloc, insnBuilder, opndBuilder);
561 }
562 
MOP_wsubrri12Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)563 inline void MOP_wsubrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
564 {
565     SubInsnSplit(insn, false, isAfterRegAlloc, insnBuilder, opndBuilder);
566 }
567 
MOP_wsubsrri12Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)568 inline void MOP_wsubsrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
569 {
570     AddsSubsInsnSplit(insn, false, false, isAfterRegAlloc, insnBuilder, opndBuilder);
571 }
572 
MOP_wldrsbSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)573 inline void MOP_wldrsbSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
574 {
575     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
576 }
577 
MOP_xldrsbSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)578 inline void MOP_xldrsbSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
579 {
580     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
581 }
582 
MOP_wldrbSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)583 inline void MOP_wldrbSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
584 {
585     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
586 }
587 
MOP_wldrshSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)588 inline void MOP_wldrshSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
589 {
590     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
591 }
592 
MOP_xldrshSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)593 inline void MOP_xldrshSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
594 {
595     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
596 }
597 
MOP_xldrswSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)598 inline void MOP_xldrswSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
599 {
600     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
601 }
602 
MOP_wldrhSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)603 inline void MOP_wldrhSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
604 {
605     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
606 }
607 
MOP_wldrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)608 inline void MOP_wldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
609 {
610     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
611 }
612 
MOP_xldrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)613 inline void MOP_xldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
614 {
615     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
616 }
617 
MOP_bldrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)618 inline void MOP_bldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
619 {
620     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
621 }
622 
MOP_hldrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)623 inline void MOP_hldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
624 {
625     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
626 }
627 
MOP_sldrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)628 inline void MOP_sldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
629 {
630     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
631 }
632 
MOP_dldrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)633 inline void MOP_dldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
634 {
635     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
636 }
637 
MOP_qldrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)638 inline void MOP_qldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
639 {
640     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
641 }
642 
MOP_wldpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)643 inline void MOP_wldpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
644 {
645     LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
646 }
647 
MOP_xldpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)648 inline void MOP_xldpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
649 {
650     LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
651 }
652 
MOP_xldpswSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)653 inline void MOP_xldpswSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
654 {
655     LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
656 }
657 
MOP_sldpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)658 inline void MOP_sldpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
659 {
660     LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
661 }
662 
MOP_dldpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)663 inline void MOP_dldpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
664 {
665     LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
666 }
667 
MOP_qldpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)668 inline void MOP_qldpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
669 {
670     LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
671 }
672 
MOP_wccmpriicSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)673 inline void MOP_wccmpriicSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
674 {
675     CondCompareInsnSplit(insn, false, isAfterRegAlloc, insnBuilder, opndBuilder);
676 }
677 
MOP_xccmpriicSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)678 inline void MOP_xccmpriicSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
679 {
680     CondCompareInsnSplit(insn, true, isAfterRegAlloc, insnBuilder, opndBuilder);
681 }
682 
MOP_wstrbSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)683 inline void MOP_wstrbSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
684 {
685     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
686 }
687 
MOP_wstrhSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)688 inline void MOP_wstrhSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
689 {
690     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
691 }
692 
MOP_wstrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)693 inline void MOP_wstrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
694 {
695     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
696 }
697 
MOP_xstrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)698 inline void MOP_xstrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
699 {
700     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
701 }
702 
MOP_sstrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)703 inline void MOP_sstrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
704 {
705     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
706 }
707 
MOP_dstrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)708 inline void MOP_dstrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
709 {
710     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
711 }
712 
MOP_qstrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)713 inline void MOP_qstrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
714 {
715     LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
716 }
717 
MOP_wstpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)718 inline void MOP_wstpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
719 {
720     LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
721 }
722 
MOP_xstpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)723 inline void MOP_xstpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
724 {
725     LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
726 }
727 
MOP_sstpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)728 inline void MOP_sstpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
729 {
730     LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
731 }
732 
MOP_dstpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)733 inline void MOP_dstpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
734 {
735     LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
736 }
737 
MOP_qstpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)738 inline void MOP_qstpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
739 {
740     LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
741 }
742 
MOP_assert_nonnullSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)743 inline void MOP_assert_nonnullSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder,
744                                     OperandBuilder *opndBuilder)
745 {
746     MOP_wldrSplit(insn, isAfterRegAlloc, insnBuilder, opndBuilder);
747 }
748 } /* namespace maplebe */
749 #endif /* MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_MOP_SPLIT_H */
750