LLVM 22.0.0git
AArch64PostLegalizerLowering.cpp
Go to the documentation of this file.
1//=== AArch64PostLegalizerLowering.cpp --------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// Post-legalization lowering for instructions.
11///
12/// This is used to offload pattern matching from the selector.
13///
14/// For example, this combiner will notice that a G_SHUFFLE_VECTOR is actually
15/// a G_ZIP, G_UZP, etc.
16///
17/// General optimization combines should be handled by either the
18/// AArch64PostLegalizerCombiner or the AArch64PreLegalizerCombiner.
19///
20//===----------------------------------------------------------------------===//
21
22#include "AArch64ExpandImm.h"
25#include "AArch64Subtarget.h"
45#include "llvm/IR/InstrTypes.h"
47#include <optional>
48
49#define GET_GICOMBINER_DEPS
50#include "AArch64GenPostLegalizeGILowering.inc"
51#undef GET_GICOMBINER_DEPS
52
53#define DEBUG_TYPE "aarch64-postlegalizer-lowering"
54
55using namespace llvm;
56using namespace MIPatternMatch;
57using namespace AArch64GISelUtils;
58
59namespace {
60
61#define GET_GICOMBINER_TYPES
62#include "AArch64GenPostLegalizeGILowering.inc"
63#undef GET_GICOMBINER_TYPES
64
65/// Represents a pseudo instruction which replaces a G_SHUFFLE_VECTOR.
66///
67/// Used for matching target-supported shuffles before codegen.
68struct ShuffleVectorPseudo {
69 unsigned Opc; ///< Opcode for the instruction. (E.g. G_ZIP1)
70 Register Dst; ///< Destination register.
71 SmallVector<SrcOp, 2> SrcOps; ///< Source registers.
72 ShuffleVectorPseudo(unsigned Opc, Register Dst,
73 std::initializer_list<SrcOp> SrcOps)
74 : Opc(Opc), Dst(Dst), SrcOps(SrcOps){};
75 ShuffleVectorPseudo() = default;
76};
77
78/// Return true if a G_FCONSTANT instruction is known to be better-represented
79/// as a G_CONSTANT.
80bool matchFConstantToConstant(MachineInstr &MI, MachineRegisterInfo &MRI) {
81 assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT);
82 Register DstReg = MI.getOperand(0).getReg();
83 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
84 if (DstSize != 16 && DstSize != 32 && DstSize != 64)
85 return false;
86
87 // When we're storing a value, it doesn't matter what register bank it's on.
88 // Since not all floating point constants can be materialized using a fmov,
89 // it makes more sense to just use a GPR.
90 return all_of(MRI.use_nodbg_instructions(DstReg),
91 [](const MachineInstr &Use) { return Use.mayStore(); });
92}
93
94/// Change a G_FCONSTANT into a G_CONSTANT.
95void applyFConstantToConstant(MachineInstr &MI) {
96 assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT);
98 const APFloat &ImmValAPF = MI.getOperand(1).getFPImm()->getValueAPF();
99 MIB.buildConstant(MI.getOperand(0).getReg(), ImmValAPF.bitcastToAPInt());
100 MI.eraseFromParent();
101}
102
103/// Check if a G_EXT instruction can handle a shuffle mask \p M when the vector
104/// sources of the shuffle are different.
105std::optional<std::pair<bool, uint64_t>> getExtMask(ArrayRef<int> M,
106 unsigned NumElts) {
107 // Look for the first non-undef element.
108 auto FirstRealElt = find_if(M, [](int Elt) { return Elt >= 0; });
109 if (FirstRealElt == M.end())
110 return std::nullopt;
111
112 // Use APInt to handle overflow when calculating expected element.
113 unsigned MaskBits = APInt(32, NumElts * 2).logBase2();
114 APInt ExpectedElt = APInt(MaskBits, *FirstRealElt + 1, false, true);
115
116 // The following shuffle indices must be the successive elements after the
117 // first real element.
118 if (any_of(
119 make_range(std::next(FirstRealElt), M.end()),
120 [&ExpectedElt](int Elt) { return Elt != ExpectedElt++ && Elt >= 0; }))
121 return std::nullopt;
122
123 // The index of an EXT is the first element if it is not UNDEF.
124 // Watch out for the beginning UNDEFs. The EXT index should be the expected
125 // value of the first element. E.g.
126 // <-1, -1, 3, ...> is treated as <1, 2, 3, ...>.
127 // <-1, -1, 0, 1, ...> is treated as <2*NumElts-2, 2*NumElts-1, 0, 1, ...>.
128 // ExpectedElt is the last mask index plus 1.
129 uint64_t Imm = ExpectedElt.getZExtValue();
130 bool ReverseExt = false;
131
132 // There are two difference cases requiring to reverse input vectors.
133 // For example, for vector <4 x i32> we have the following cases,
134 // Case 1: shufflevector(<4 x i32>,<4 x i32>,<-1, -1, -1, 0>)
135 // Case 2: shufflevector(<4 x i32>,<4 x i32>,<-1, -1, 7, 0>)
136 // For both cases, we finally use mask <5, 6, 7, 0>, which requires
137 // to reverse two input vectors.
138 if (Imm < NumElts)
139 ReverseExt = true;
140 else
141 Imm -= NumElts;
142 return std::make_pair(ReverseExt, Imm);
143}
144
145/// Helper function for matchINS.
146///
147/// \returns a value when \p M is an ins mask for \p NumInputElements.
148///
149/// First element of the returned pair is true when the produced
150/// G_INSERT_VECTOR_ELT destination should be the LHS of the G_SHUFFLE_VECTOR.
151///
152/// Second element is the destination lane for the G_INSERT_VECTOR_ELT.
153std::optional<std::pair<bool, int>> isINSMask(ArrayRef<int> M,
154 int NumInputElements) {
155 if (M.size() != static_cast<size_t>(NumInputElements))
156 return std::nullopt;
157 int NumLHSMatch = 0, NumRHSMatch = 0;
158 int LastLHSMismatch = -1, LastRHSMismatch = -1;
159 for (int Idx = 0; Idx < NumInputElements; ++Idx) {
160 if (M[Idx] == -1) {
161 ++NumLHSMatch;
162 ++NumRHSMatch;
163 continue;
164 }
165 M[Idx] == Idx ? ++NumLHSMatch : LastLHSMismatch = Idx;
166 M[Idx] == Idx + NumInputElements ? ++NumRHSMatch : LastRHSMismatch = Idx;
167 }
168 const int NumNeededToMatch = NumInputElements - 1;
169 if (NumLHSMatch == NumNeededToMatch)
170 return std::make_pair(true, LastLHSMismatch);
171 if (NumRHSMatch == NumNeededToMatch)
172 return std::make_pair(false, LastRHSMismatch);
173 return std::nullopt;
174}
175
176/// \return true if a G_SHUFFLE_VECTOR instruction \p MI can be replaced with a
177/// G_REV instruction. Returns the appropriate G_REV opcode in \p Opc.
178bool matchREV(MachineInstr &MI, MachineRegisterInfo &MRI,
179 ShuffleVectorPseudo &MatchInfo) {
180 assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
181 ArrayRef<int> ShuffleMask = MI.getOperand(3).getShuffleMask();
182 Register Dst = MI.getOperand(0).getReg();
183 Register Src = MI.getOperand(1).getReg();
184 LLT Ty = MRI.getType(Dst);
185 unsigned EltSize = Ty.getScalarSizeInBits();
186
187 // Element size for a rev cannot be 64.
188 if (EltSize == 64)
189 return false;
190
191 unsigned NumElts = Ty.getNumElements();
192
193 // Try to produce a G_REV instruction
194 for (unsigned LaneSize : {64U, 32U, 16U}) {
195 if (isREVMask(ShuffleMask, EltSize, NumElts, LaneSize)) {
196 unsigned Opcode;
197 if (LaneSize == 64U)
198 Opcode = AArch64::G_REV64;
199 else if (LaneSize == 32U)
200 Opcode = AArch64::G_REV32;
201 else
202 Opcode = AArch64::G_REV16;
203
204 MatchInfo = ShuffleVectorPseudo(Opcode, Dst, {Src});
205 return true;
206 }
207 }
208
209 return false;
210}
211
212/// \return true if a G_SHUFFLE_VECTOR instruction \p MI can be replaced with
213/// a G_TRN1 or G_TRN2 instruction.
214bool matchTRN(MachineInstr &MI, MachineRegisterInfo &MRI,
215 ShuffleVectorPseudo &MatchInfo) {
216 assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
217 unsigned WhichResult;
218 ArrayRef<int> ShuffleMask = MI.getOperand(3).getShuffleMask();
219 Register Dst = MI.getOperand(0).getReg();
220 unsigned NumElts = MRI.getType(Dst).getNumElements();
221 if (!isTRNMask(ShuffleMask, NumElts, WhichResult))
222 return false;
223 unsigned Opc = (WhichResult == 0) ? AArch64::G_TRN1 : AArch64::G_TRN2;
224 Register V1 = MI.getOperand(1).getReg();
225 Register V2 = MI.getOperand(2).getReg();
226 MatchInfo = ShuffleVectorPseudo(Opc, Dst, {V1, V2});
227 return true;
228}
229
230/// \return true if a G_SHUFFLE_VECTOR instruction \p MI can be replaced with
231/// a G_UZP1 or G_UZP2 instruction.
232///
233/// \param [in] MI - The shuffle vector instruction.
234/// \param [out] MatchInfo - Either G_UZP1 or G_UZP2 on success.
235bool matchUZP(MachineInstr &MI, MachineRegisterInfo &MRI,
236 ShuffleVectorPseudo &MatchInfo) {
237 assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
238 unsigned WhichResult;
239 ArrayRef<int> ShuffleMask = MI.getOperand(3).getShuffleMask();
240 Register Dst = MI.getOperand(0).getReg();
241 unsigned NumElts = MRI.getType(Dst).getNumElements();
242 if (!isUZPMask(ShuffleMask, NumElts, WhichResult))
243 return false;
244 unsigned Opc = (WhichResult == 0) ? AArch64::G_UZP1 : AArch64::G_UZP2;
245 Register V1 = MI.getOperand(1).getReg();
246 Register V2 = MI.getOperand(2).getReg();
247 MatchInfo = ShuffleVectorPseudo(Opc, Dst, {V1, V2});
248 return true;
249}
250
251bool matchZip(MachineInstr &MI, MachineRegisterInfo &MRI,
252 ShuffleVectorPseudo &MatchInfo) {
253 assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
254 unsigned WhichResult;
255 unsigned OperandOrder;
256 ArrayRef<int> ShuffleMask = MI.getOperand(3).getShuffleMask();
257 Register Dst = MI.getOperand(0).getReg();
258 unsigned NumElts = MRI.getType(Dst).getNumElements();
259 if (!isZIPMask(ShuffleMask, NumElts, WhichResult, OperandOrder))
260 return false;
261 unsigned Opc = (WhichResult == 0) ? AArch64::G_ZIP1 : AArch64::G_ZIP2;
262 Register V1 = MI.getOperand(OperandOrder == 0 ? 1 : 2).getReg();
263 Register V2 = MI.getOperand(OperandOrder == 0 ? 2 : 1).getReg();
264 MatchInfo = ShuffleVectorPseudo(Opc, Dst, {V1, V2});
265 return true;
266}
267
268/// Helper function for matchDup.
269bool matchDupFromInsertVectorElt(int Lane, MachineInstr &MI,
271 ShuffleVectorPseudo &MatchInfo) {
272 if (Lane != 0)
273 return false;
274
275 // Try to match a vector splat operation into a dup instruction.
276 // We're looking for this pattern:
277 //
278 // %scalar:gpr(s64) = COPY $x0
279 // %undef:fpr(<2 x s64>) = G_IMPLICIT_DEF
280 // %cst0:gpr(s32) = G_CONSTANT i32 0
281 // %zerovec:fpr(<2 x s32>) = G_BUILD_VECTOR %cst0(s32), %cst0(s32)
282 // %ins:fpr(<2 x s64>) = G_INSERT_VECTOR_ELT %undef, %scalar(s64), %cst0(s32)
283 // %splat:fpr(<2 x s64>) = G_SHUFFLE_VECTOR %ins(<2 x s64>), %undef,
284 // %zerovec(<2 x s32>)
285 //
286 // ...into:
287 // %splat = G_DUP %scalar
288
289 // Begin matching the insert.
290 auto *InsMI = getOpcodeDef(TargetOpcode::G_INSERT_VECTOR_ELT,
291 MI.getOperand(1).getReg(), MRI);
292 if (!InsMI)
293 return false;
294 // Match the undef vector operand.
295 if (!getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, InsMI->getOperand(1).getReg(),
296 MRI))
297 return false;
298
299 // Match the index constant 0.
300 if (!mi_match(InsMI->getOperand(3).getReg(), MRI, m_ZeroInt()))
301 return false;
302
303 MatchInfo = ShuffleVectorPseudo(AArch64::G_DUP, MI.getOperand(0).getReg(),
304 {InsMI->getOperand(2).getReg()});
305 return true;
306}
307
308/// Helper function for matchDup.
309bool matchDupFromBuildVector(int Lane, MachineInstr &MI,
311 ShuffleVectorPseudo &MatchInfo) {
312 assert(Lane >= 0 && "Expected positive lane?");
313 int NumElements = MRI.getType(MI.getOperand(1).getReg()).getNumElements();
314 // Test if the LHS is a BUILD_VECTOR. If it is, then we can just reference the
315 // lane's definition directly.
316 auto *BuildVecMI =
317 getOpcodeDef(TargetOpcode::G_BUILD_VECTOR,
318 MI.getOperand(Lane < NumElements ? 1 : 2).getReg(), MRI);
319 // If Lane >= NumElements then it is point to RHS, just check from RHS
320 if (NumElements <= Lane)
321 Lane -= NumElements;
322
323 if (!BuildVecMI)
324 return false;
325 Register Reg = BuildVecMI->getOperand(Lane + 1).getReg();
326 MatchInfo =
327 ShuffleVectorPseudo(AArch64::G_DUP, MI.getOperand(0).getReg(), {Reg});
328 return true;
329}
330
331bool matchDup(MachineInstr &MI, MachineRegisterInfo &MRI,
332 ShuffleVectorPseudo &MatchInfo) {
333 assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
334 auto MaybeLane = getSplatIndex(MI);
335 if (!MaybeLane)
336 return false;
337 int Lane = *MaybeLane;
338 // If this is undef splat, generate it via "just" vdup, if possible.
339 if (Lane < 0)
340 Lane = 0;
341 if (matchDupFromInsertVectorElt(Lane, MI, MRI, MatchInfo))
342 return true;
343 if (matchDupFromBuildVector(Lane, MI, MRI, MatchInfo))
344 return true;
345 return false;
346}
347
348// Check if an EXT instruction can handle the shuffle mask when the vector
349// sources of the shuffle are the same.
350bool isSingletonExtMask(ArrayRef<int> M, LLT Ty) {
351 unsigned NumElts = Ty.getNumElements();
352
353 // Assume that the first shuffle index is not UNDEF. Fail if it is.
354 if (M[0] < 0)
355 return false;
356
357 // If this is a VEXT shuffle, the immediate value is the index of the first
358 // element. The other shuffle indices must be the successive elements after
359 // the first one.
360 unsigned ExpectedElt = M[0];
361 for (unsigned I = 1; I < NumElts; ++I) {
362 // Increment the expected index. If it wraps around, just follow it
363 // back to index zero and keep going.
364 ++ExpectedElt;
365 if (ExpectedElt == NumElts)
366 ExpectedElt = 0;
367
368 if (M[I] < 0)
369 continue; // Ignore UNDEF indices.
370 if (ExpectedElt != static_cast<unsigned>(M[I]))
371 return false;
372 }
373
374 return true;
375}
376
377bool matchEXT(MachineInstr &MI, MachineRegisterInfo &MRI,
378 ShuffleVectorPseudo &MatchInfo) {
379 assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
380 Register Dst = MI.getOperand(0).getReg();
381 LLT DstTy = MRI.getType(Dst);
382 Register V1 = MI.getOperand(1).getReg();
383 Register V2 = MI.getOperand(2).getReg();
384 auto Mask = MI.getOperand(3).getShuffleMask();
386 auto ExtInfo = getExtMask(Mask, DstTy.getNumElements());
387 uint64_t ExtFactor = MRI.getType(V1).getScalarSizeInBits() / 8;
388
389 if (!ExtInfo) {
391 !isSingletonExtMask(Mask, DstTy))
392 return false;
393
394 Imm = Mask[0] * ExtFactor;
395 MatchInfo = ShuffleVectorPseudo(AArch64::G_EXT, Dst, {V1, V1, Imm});
396 return true;
397 }
398 bool ReverseExt;
399 std::tie(ReverseExt, Imm) = *ExtInfo;
400 if (ReverseExt)
401 std::swap(V1, V2);
402 Imm *= ExtFactor;
403 MatchInfo = ShuffleVectorPseudo(AArch64::G_EXT, Dst, {V1, V2, Imm});
404 return true;
405}
406
407/// Replace a G_SHUFFLE_VECTOR instruction with a pseudo.
408/// \p Opc is the opcode to use. \p MI is the G_SHUFFLE_VECTOR.
409void applyShuffleVectorPseudo(MachineInstr &MI,
410 ShuffleVectorPseudo &MatchInfo) {
411 MachineIRBuilder MIRBuilder(MI);
412 MIRBuilder.buildInstr(MatchInfo.Opc, {MatchInfo.Dst}, MatchInfo.SrcOps);
413 MI.eraseFromParent();
414}
415
416/// Replace a G_SHUFFLE_VECTOR instruction with G_EXT.
417/// Special-cased because the constant operand must be emitted as a G_CONSTANT
418/// for the imported tablegen patterns to work.
419void applyEXT(MachineInstr &MI, ShuffleVectorPseudo &MatchInfo) {
420 MachineIRBuilder MIRBuilder(MI);
421 if (MatchInfo.SrcOps[2].getImm() == 0)
422 MIRBuilder.buildCopy(MatchInfo.Dst, MatchInfo.SrcOps[0]);
423 else {
424 // Tablegen patterns expect an i32 G_CONSTANT as the final op.
425 auto Cst =
426 MIRBuilder.buildConstant(LLT::scalar(32), MatchInfo.SrcOps[2].getImm());
427 MIRBuilder.buildInstr(MatchInfo.Opc, {MatchInfo.Dst},
428 {MatchInfo.SrcOps[0], MatchInfo.SrcOps[1], Cst});
429 }
430 MI.eraseFromParent();
431}
432
433void applyFullRev(MachineInstr &MI, MachineRegisterInfo &MRI) {
434 Register Dst = MI.getOperand(0).getReg();
435 Register Src = MI.getOperand(1).getReg();
436 LLT DstTy = MRI.getType(Dst);
437 assert(DstTy.getSizeInBits() == 128 &&
438 "Expected 128bit vector in applyFullRev");
439 MachineIRBuilder MIRBuilder(MI);
440 auto Cst = MIRBuilder.buildConstant(LLT::scalar(32), 8);
441 auto Rev = MIRBuilder.buildInstr(AArch64::G_REV64, {DstTy}, {Src});
442 MIRBuilder.buildInstr(AArch64::G_EXT, {Dst}, {Rev, Rev, Cst});
443 MI.eraseFromParent();
444}
445
446bool matchNonConstInsert(MachineInstr &MI, MachineRegisterInfo &MRI) {
447 assert(MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT);
448
449 auto ValAndVReg =
450 getIConstantVRegValWithLookThrough(MI.getOperand(3).getReg(), MRI);
451 return !ValAndVReg;
452}
453
454void applyNonConstInsert(MachineInstr &MI, MachineRegisterInfo &MRI,
455 MachineIRBuilder &Builder) {
457 Builder.setInstrAndDebugLoc(Insert);
458
459 Register Offset = Insert.getIndexReg();
460 LLT VecTy = MRI.getType(Insert.getReg(0));
461 LLT EltTy = MRI.getType(Insert.getElementReg());
462 LLT IdxTy = MRI.getType(Insert.getIndexReg());
463
464 if (VecTy.isScalableVector())
465 return;
466
467 // Create a stack slot and store the vector into it
468 MachineFunction &MF = Builder.getMF();
469 Align Alignment(
470 std::min<uint64_t>(VecTy.getSizeInBytes().getKnownMinValue(), 16));
471 int FrameIdx = MF.getFrameInfo().CreateStackObject(VecTy.getSizeInBytes(),
472 Alignment, false);
473 LLT FramePtrTy = LLT::pointer(0, 64);
475 auto StackTemp = Builder.buildFrameIndex(FramePtrTy, FrameIdx);
476
477 Builder.buildStore(Insert.getOperand(1), StackTemp, PtrInfo, Align(8));
478
479 // Get the pointer to the element, and be sure not to hit undefined behavior
480 // if the index is out of bounds.
482 "Expected a power-2 vector size");
483 auto Mask = Builder.buildConstant(IdxTy, VecTy.getNumElements() - 1);
484 Register And = Builder.buildAnd(IdxTy, Offset, Mask).getReg(0);
485 auto EltSize = Builder.buildConstant(IdxTy, EltTy.getSizeInBytes());
486 Register Mul = Builder.buildMul(IdxTy, And, EltSize).getReg(0);
487 Register EltPtr =
488 Builder.buildPtrAdd(MRI.getType(StackTemp.getReg(0)), StackTemp, Mul)
489 .getReg(0);
490
491 // Write the inserted element
492 Builder.buildStore(Insert.getElementReg(), EltPtr, PtrInfo, Align(1));
493 // Reload the whole vector.
494 Builder.buildLoad(Insert.getReg(0), StackTemp, PtrInfo, Align(8));
495 Insert.eraseFromParent();
496}
497
498/// Match a G_SHUFFLE_VECTOR with a mask which corresponds to a
499/// G_INSERT_VECTOR_ELT and G_EXTRACT_VECTOR_ELT pair.
500///
501/// e.g.
502/// %shuf = G_SHUFFLE_VECTOR %left, %right, shufflemask(0, 0)
503///
504/// Can be represented as
505///
506/// %extract = G_EXTRACT_VECTOR_ELT %left, 0
507/// %ins = G_INSERT_VECTOR_ELT %left, %extract, 1
508///
509bool matchINS(MachineInstr &MI, MachineRegisterInfo &MRI,
510 std::tuple<Register, int, Register, int> &MatchInfo) {
511 assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
512 ArrayRef<int> ShuffleMask = MI.getOperand(3).getShuffleMask();
513 Register Dst = MI.getOperand(0).getReg();
514 int NumElts = MRI.getType(Dst).getNumElements();
515 auto DstIsLeftAndDstLane = isINSMask(ShuffleMask, NumElts);
516 if (!DstIsLeftAndDstLane)
517 return false;
518 bool DstIsLeft;
519 int DstLane;
520 std::tie(DstIsLeft, DstLane) = *DstIsLeftAndDstLane;
521 Register Left = MI.getOperand(1).getReg();
522 Register Right = MI.getOperand(2).getReg();
523 Register DstVec = DstIsLeft ? Left : Right;
524 Register SrcVec = Left;
525
526 int SrcLane = ShuffleMask[DstLane];
527 if (SrcLane >= NumElts) {
528 SrcVec = Right;
529 SrcLane -= NumElts;
530 }
531
532 MatchInfo = std::make_tuple(DstVec, DstLane, SrcVec, SrcLane);
533 return true;
534}
535
536void applyINS(MachineInstr &MI, MachineRegisterInfo &MRI,
537 MachineIRBuilder &Builder,
538 std::tuple<Register, int, Register, int> &MatchInfo) {
539 Builder.setInstrAndDebugLoc(MI);
540 Register Dst = MI.getOperand(0).getReg();
541 auto ScalarTy = MRI.getType(Dst).getElementType();
542 Register DstVec, SrcVec;
543 int DstLane, SrcLane;
544 std::tie(DstVec, DstLane, SrcVec, SrcLane) = MatchInfo;
545 auto SrcCst = Builder.buildConstant(LLT::scalar(64), SrcLane);
546 auto Extract = Builder.buildExtractVectorElement(ScalarTy, SrcVec, SrcCst);
547 auto DstCst = Builder.buildConstant(LLT::scalar(64), DstLane);
548 Builder.buildInsertVectorElement(Dst, DstVec, Extract, DstCst);
549 MI.eraseFromParent();
550}
551
552/// isVShiftRImm - Check if this is a valid vector for the immediate
553/// operand of a vector shift right operation. The value must be in the range:
554/// 1 <= Value <= ElementBits for a right shift.
556 int64_t &Cnt) {
557 assert(Ty.isVector() && "vector shift count is not a vector type");
558 MachineInstr *MI = MRI.getVRegDef(Reg);
559 auto Cst = getAArch64VectorSplatScalar(*MI, MRI);
560 if (!Cst)
561 return false;
562 Cnt = *Cst;
563 int64_t ElementBits = Ty.getScalarSizeInBits();
564 return Cnt >= 1 && Cnt <= ElementBits;
565}
566
567/// Match a vector G_ASHR or G_LSHR with a valid immediate shift.
568bool matchVAshrLshrImm(MachineInstr &MI, MachineRegisterInfo &MRI,
569 int64_t &Imm) {
570 assert(MI.getOpcode() == TargetOpcode::G_ASHR ||
571 MI.getOpcode() == TargetOpcode::G_LSHR);
572 LLT Ty = MRI.getType(MI.getOperand(1).getReg());
573 if (!Ty.isVector())
574 return false;
575 return isVShiftRImm(MI.getOperand(2).getReg(), MRI, Ty, Imm);
576}
577
578void applyVAshrLshrImm(MachineInstr &MI, MachineRegisterInfo &MRI,
579 int64_t &Imm) {
580 unsigned Opc = MI.getOpcode();
581 assert(Opc == TargetOpcode::G_ASHR || Opc == TargetOpcode::G_LSHR);
582 unsigned NewOpc =
583 Opc == TargetOpcode::G_ASHR ? AArch64::G_VASHR : AArch64::G_VLSHR;
584 MachineIRBuilder MIB(MI);
585 MIB.buildInstr(NewOpc, {MI.getOperand(0)}, {MI.getOperand(1)}).addImm(Imm);
586 MI.eraseFromParent();
587}
588
589/// Determine if it is possible to modify the \p RHS and predicate \p P of a
590/// G_ICMP instruction such that the right-hand side is an arithmetic immediate.
591///
592/// \returns A pair containing the updated immediate and predicate which may
593/// be used to optimize the instruction.
594///
595/// \note This assumes that the comparison has been legalized.
596std::optional<std::pair<uint64_t, CmpInst::Predicate>>
597tryAdjustICmpImmAndPred(Register RHS, CmpInst::Predicate P,
598 const MachineRegisterInfo &MRI) {
599 const auto &Ty = MRI.getType(RHS);
600 if (Ty.isVector())
601 return std::nullopt;
602 unsigned Size = Ty.getSizeInBits();
603 assert((Size == 32 || Size == 64) && "Expected 32 or 64 bit compare only?");
604
605 // If the RHS is not a constant, or the RHS is already a valid arithmetic
606 // immediate, then there is nothing to change.
607 auto ValAndVReg = getIConstantVRegValWithLookThrough(RHS, MRI);
608 if (!ValAndVReg)
609 return std::nullopt;
610 uint64_t OriginalC = ValAndVReg->Value.getZExtValue();
611 uint64_t C = OriginalC;
612 if (isLegalArithImmed(C))
613 return std::nullopt;
614
615 // We have a non-arithmetic immediate. Check if adjusting the immediate and
616 // adjusting the predicate will result in a legal arithmetic immediate.
617 switch (P) {
618 default:
619 return std::nullopt;
622 // Check for
623 //
624 // x slt c => x sle c - 1
625 // x sge c => x sgt c - 1
626 //
627 // When c is not the smallest possible negative number.
628 if ((Size == 64 && static_cast<int64_t>(C) == INT64_MIN) ||
629 (Size == 32 && static_cast<int32_t>(C) == INT32_MIN))
630 return std::nullopt;
631 P = (P == CmpInst::ICMP_SLT) ? CmpInst::ICMP_SLE : CmpInst::ICMP_SGT;
632 C -= 1;
633 break;
636 // Check for
637 //
638 // x ult c => x ule c - 1
639 // x uge c => x ugt c - 1
640 //
641 // When c is not zero.
642 assert(C != 0 && "C should not be zero here!");
643 P = (P == CmpInst::ICMP_ULT) ? CmpInst::ICMP_ULE : CmpInst::ICMP_UGT;
644 C -= 1;
645 break;
648 // Check for
649 //
650 // x sle c => x slt c + 1
651 // x sgt c => s sge c + 1
652 //
653 // When c is not the largest possible signed integer.
654 if ((Size == 32 && static_cast<int32_t>(C) == INT32_MAX) ||
655 (Size == 64 && static_cast<int64_t>(C) == INT64_MAX))
656 return std::nullopt;
657 P = (P == CmpInst::ICMP_SLE) ? CmpInst::ICMP_SLT : CmpInst::ICMP_SGE;
658 C += 1;
659 break;
662 // Check for
663 //
664 // x ule c => x ult c + 1
665 // x ugt c => s uge c + 1
666 //
667 // When c is not the largest possible unsigned integer.
668 if ((Size == 32 && static_cast<uint32_t>(C) == UINT32_MAX) ||
669 (Size == 64 && C == UINT64_MAX))
670 return std::nullopt;
671 P = (P == CmpInst::ICMP_ULE) ? CmpInst::ICMP_ULT : CmpInst::ICMP_UGE;
672 C += 1;
673 break;
674 }
675
676 // Check if the new constant is valid, and return the updated constant and
677 // predicate if it is.
678 if (Size == 32)
679 C = static_cast<uint32_t>(C);
680 if (isLegalArithImmed(C))
681 return {{C, P}};
682
683 auto NumberOfInstrToLoadImm = [=](uint64_t Imm) {
685 AArch64_IMM::expandMOVImm(Imm, 32, Insn);
686 return Insn.size();
687 };
688
689 if (NumberOfInstrToLoadImm(OriginalC) > NumberOfInstrToLoadImm(C))
690 return {{C, P}};
691
692 return std::nullopt;
693}
694
695/// Determine whether or not it is possible to update the RHS and predicate of
696/// a G_ICMP instruction such that the RHS will be selected as an arithmetic
697/// immediate.
698///
699/// \p MI - The G_ICMP instruction
700/// \p MatchInfo - The new RHS immediate and predicate on success
701///
702/// See tryAdjustICmpImmAndPred for valid transformations.
703bool matchAdjustICmpImmAndPred(
705 std::pair<uint64_t, CmpInst::Predicate> &MatchInfo) {
706 assert(MI.getOpcode() == TargetOpcode::G_ICMP);
707 Register RHS = MI.getOperand(3).getReg();
708 auto Pred = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
709 if (auto MaybeNewImmAndPred = tryAdjustICmpImmAndPred(RHS, Pred, MRI)) {
710 MatchInfo = *MaybeNewImmAndPred;
711 return true;
712 }
713 return false;
714}
715
716void applyAdjustICmpImmAndPred(
717 MachineInstr &MI, std::pair<uint64_t, CmpInst::Predicate> &MatchInfo,
718 MachineIRBuilder &MIB, GISelChangeObserver &Observer) {
720 MachineOperand &RHS = MI.getOperand(3);
722 auto Cst = MIB.buildConstant(MRI.cloneVirtualRegister(RHS.getReg()),
723 MatchInfo.first);
724 Observer.changingInstr(MI);
725 RHS.setReg(Cst->getOperand(0).getReg());
726 MI.getOperand(1).setPredicate(MatchInfo.second);
727 Observer.changedInstr(MI);
728}
729
730bool matchDupLane(MachineInstr &MI, MachineRegisterInfo &MRI,
731 std::pair<unsigned, int> &MatchInfo) {
732 assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
733 Register Src1Reg = MI.getOperand(1).getReg();
734 const LLT SrcTy = MRI.getType(Src1Reg);
735 const LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
736
737 auto LaneIdx = getSplatIndex(MI);
738 if (!LaneIdx)
739 return false;
740
741 // The lane idx should be within the first source vector.
742 if (*LaneIdx >= SrcTy.getNumElements())
743 return false;
744
745 if (DstTy != SrcTy)
746 return false;
747
748 LLT ScalarTy = SrcTy.getElementType();
749 unsigned ScalarSize = ScalarTy.getSizeInBits();
750
751 unsigned Opc = 0;
752 switch (SrcTy.getNumElements()) {
753 case 2:
754 if (ScalarSize == 64)
755 Opc = AArch64::G_DUPLANE64;
756 else if (ScalarSize == 32)
757 Opc = AArch64::G_DUPLANE32;
758 break;
759 case 4:
760 if (ScalarSize == 32)
761 Opc = AArch64::G_DUPLANE32;
762 else if (ScalarSize == 16)
763 Opc = AArch64::G_DUPLANE16;
764 break;
765 case 8:
766 if (ScalarSize == 8)
767 Opc = AArch64::G_DUPLANE8;
768 else if (ScalarSize == 16)
769 Opc = AArch64::G_DUPLANE16;
770 break;
771 case 16:
772 if (ScalarSize == 8)
773 Opc = AArch64::G_DUPLANE8;
774 break;
775 default:
776 break;
777 }
778 if (!Opc)
779 return false;
780
781 MatchInfo.first = Opc;
782 MatchInfo.second = *LaneIdx;
783 return true;
784}
785
786void applyDupLane(MachineInstr &MI, MachineRegisterInfo &MRI,
787 MachineIRBuilder &B, std::pair<unsigned, int> &MatchInfo) {
788 assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
789 Register Src1Reg = MI.getOperand(1).getReg();
790 const LLT SrcTy = MRI.getType(Src1Reg);
791
792 B.setInstrAndDebugLoc(MI);
793 auto Lane = B.buildConstant(LLT::scalar(64), MatchInfo.second);
794
795 Register DupSrc = MI.getOperand(1).getReg();
796 // For types like <2 x s32>, we can use G_DUPLANE32, with a <4 x s32> source.
797 // To do this, we can use a G_CONCAT_VECTORS to do the widening.
798 if (SrcTy.getSizeInBits() == 64) {
799 auto Undef = B.buildUndef(SrcTy);
800 DupSrc = B.buildConcatVectors(SrcTy.multiplyElements(2),
801 {Src1Reg, Undef.getReg(0)})
802 .getReg(0);
803 }
804 B.buildInstr(MatchInfo.first, {MI.getOperand(0).getReg()}, {DupSrc, Lane});
805 MI.eraseFromParent();
806}
807
808bool matchScalarizeVectorUnmerge(MachineInstr &MI, MachineRegisterInfo &MRI) {
809 auto &Unmerge = cast<GUnmerge>(MI);
810 Register Src1Reg = Unmerge.getReg(Unmerge.getNumOperands() - 1);
811 const LLT SrcTy = MRI.getType(Src1Reg);
812 if (SrcTy.getSizeInBits() != 128 && SrcTy.getSizeInBits() != 64)
813 return false;
814 return SrcTy.isVector() && !SrcTy.isScalable() &&
815 Unmerge.getNumOperands() == (unsigned)SrcTy.getNumElements() + 1;
816}
817
818void applyScalarizeVectorUnmerge(MachineInstr &MI, MachineRegisterInfo &MRI,
820 auto &Unmerge = cast<GUnmerge>(MI);
821 Register Src1Reg = Unmerge.getReg(Unmerge.getNumOperands() - 1);
822 const LLT SrcTy = MRI.getType(Src1Reg);
823 assert((SrcTy.isVector() && !SrcTy.isScalable()) &&
824 "Expected a fixed length vector");
825
826 for (int I = 0; I < SrcTy.getNumElements(); ++I)
827 B.buildExtractVectorElementConstant(Unmerge.getReg(I), Src1Reg, I);
828 MI.eraseFromParent();
829}
830
831bool matchBuildVectorToDup(MachineInstr &MI, MachineRegisterInfo &MRI) {
832 assert(MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
833
834 // Later, during selection, we'll try to match imported patterns using
835 // immAllOnesV and immAllZerosV. These require G_BUILD_VECTOR. Don't lower
836 // G_BUILD_VECTORs which could match those patterns.
838 return false;
839
840 return getAArch64VectorSplat(MI, MRI).has_value();
841}
842
843void applyBuildVectorToDup(MachineInstr &MI, MachineRegisterInfo &MRI,
845 B.setInstrAndDebugLoc(MI);
846 B.buildInstr(AArch64::G_DUP, {MI.getOperand(0).getReg()},
847 {MI.getOperand(1).getReg()});
848 MI.eraseFromParent();
849}
850
851/// \returns how many instructions would be saved by folding a G_ICMP's shift
852/// and/or extension operations.
854 // No instructions to save if there's more than one use or no uses.
855 if (!MRI.hasOneNonDBGUse(CmpOp))
856 return 0;
857
858 // FIXME: This is duplicated with the selector. (See: selectShiftedRegister)
859 auto IsSupportedExtend = [&](const MachineInstr &MI) {
860 if (MI.getOpcode() == TargetOpcode::G_SEXT_INREG)
861 return true;
862 if (MI.getOpcode() != TargetOpcode::G_AND)
863 return false;
864 auto ValAndVReg =
865 getIConstantVRegValWithLookThrough(MI.getOperand(2).getReg(), MRI);
866 if (!ValAndVReg)
867 return false;
868 uint64_t Mask = ValAndVReg->Value.getZExtValue();
869 return (Mask == 0xFF || Mask == 0xFFFF || Mask == 0xFFFFFFFF);
870 };
871
873 if (IsSupportedExtend(*Def))
874 return 1;
875
876 unsigned Opc = Def->getOpcode();
877 if (Opc != TargetOpcode::G_SHL && Opc != TargetOpcode::G_ASHR &&
878 Opc != TargetOpcode::G_LSHR)
879 return 0;
880
881 auto MaybeShiftAmt =
882 getIConstantVRegValWithLookThrough(Def->getOperand(2).getReg(), MRI);
883 if (!MaybeShiftAmt)
884 return 0;
885 uint64_t ShiftAmt = MaybeShiftAmt->Value.getZExtValue();
886 MachineInstr *ShiftLHS =
887 getDefIgnoringCopies(Def->getOperand(1).getReg(), MRI);
888
889 // Check if we can fold an extend and a shift.
890 // FIXME: This is duplicated with the selector. (See:
891 // selectArithExtendedRegister)
892 if (IsSupportedExtend(*ShiftLHS))
893 return (ShiftAmt <= 4) ? 2 : 1;
894
895 LLT Ty = MRI.getType(Def->getOperand(0).getReg());
896 if (Ty.isVector())
897 return 0;
898 unsigned ShiftSize = Ty.getSizeInBits();
899 if ((ShiftSize == 32 && ShiftAmt <= 31) ||
900 (ShiftSize == 64 && ShiftAmt <= 63))
901 return 1;
902 return 0;
903}
904
905/// \returns true if it would be profitable to swap the LHS and RHS of a G_ICMP
906/// instruction \p MI.
907bool trySwapICmpOperands(MachineInstr &MI, MachineRegisterInfo &MRI) {
908 assert(MI.getOpcode() == TargetOpcode::G_ICMP);
909 // Swap the operands if it would introduce a profitable folding opportunity.
910 // (e.g. a shift + extend).
911 //
912 // For example:
913 // lsl w13, w11, #1
914 // cmp w13, w12
915 // can be turned into:
916 // cmp w12, w11, lsl #1
917
918 // Don't swap if there's a constant on the RHS, because we know we can fold
919 // that.
920 Register RHS = MI.getOperand(3).getReg();
922 if (RHSCst && isLegalArithImmed(RHSCst->Value.getSExtValue()))
923 return false;
924
925 Register LHS = MI.getOperand(2).getReg();
926 auto Pred = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
927 auto GetRegForProfit = [&](Register Reg) {
929 return isCMN(Def, Pred, MRI) ? Def->getOperand(2).getReg() : Reg;
930 };
931
932 // Don't have a constant on the RHS. If we swap the LHS and RHS of the
933 // compare, would we be able to fold more instructions?
934 Register TheLHS = GetRegForProfit(LHS);
935 Register TheRHS = GetRegForProfit(RHS);
936
937 // If the LHS is more likely to give us a folding opportunity, then swap the
938 // LHS and RHS.
939 return (getCmpOperandFoldingProfit(TheLHS, MRI) >
941}
942
943void applySwapICmpOperands(MachineInstr &MI, GISelChangeObserver &Observer) {
944 auto Pred = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
945 Register LHS = MI.getOperand(2).getReg();
946 Register RHS = MI.getOperand(3).getReg();
947 Observer.changedInstr(MI);
948 MI.getOperand(1).setPredicate(CmpInst::getSwappedPredicate(Pred));
949 MI.getOperand(2).setReg(RHS);
950 MI.getOperand(3).setReg(LHS);
951 Observer.changedInstr(MI);
952}
953
954/// \returns a function which builds a vector floating point compare instruction
955/// for a condition code \p CC.
956/// \param [in] NoNans - True if the target has NoNansFPMath.
957std::function<Register(MachineIRBuilder &)>
958getVectorFCMP(AArch64CC::CondCode CC, Register LHS, Register RHS, bool NoNans,
960 LLT DstTy = MRI.getType(LHS);
961 assert(DstTy.isVector() && "Expected vector types only?");
962 assert(DstTy == MRI.getType(RHS) && "Src and Dst types must match!");
963 switch (CC) {
964 default:
965 llvm_unreachable("Unexpected condition code!");
966 case AArch64CC::NE:
967 return [LHS, RHS, DstTy](MachineIRBuilder &MIB) {
968 auto FCmp = MIB.buildInstr(AArch64::G_FCMEQ, {DstTy}, {LHS, RHS});
969 return MIB.buildNot(DstTy, FCmp).getReg(0);
970 };
971 case AArch64CC::EQ:
972 return [LHS, RHS, DstTy](MachineIRBuilder &MIB) {
973 return MIB.buildInstr(AArch64::G_FCMEQ, {DstTy}, {LHS, RHS}).getReg(0);
974 };
975 case AArch64CC::GE:
976 return [LHS, RHS, DstTy](MachineIRBuilder &MIB) {
977 return MIB.buildInstr(AArch64::G_FCMGE, {DstTy}, {LHS, RHS}).getReg(0);
978 };
979 case AArch64CC::GT:
980 return [LHS, RHS, DstTy](MachineIRBuilder &MIB) {
981 return MIB.buildInstr(AArch64::G_FCMGT, {DstTy}, {LHS, RHS}).getReg(0);
982 };
983 case AArch64CC::LS:
984 return [LHS, RHS, DstTy](MachineIRBuilder &MIB) {
985 return MIB.buildInstr(AArch64::G_FCMGE, {DstTy}, {RHS, LHS}).getReg(0);
986 };
987 case AArch64CC::MI:
988 return [LHS, RHS, DstTy](MachineIRBuilder &MIB) {
989 return MIB.buildInstr(AArch64::G_FCMGT, {DstTy}, {RHS, LHS}).getReg(0);
990 };
991 }
992}
993
994/// Try to lower a vector G_FCMP \p MI into an AArch64-specific pseudo.
995bool matchLowerVectorFCMP(MachineInstr &MI, MachineRegisterInfo &MRI,
996 MachineIRBuilder &MIB) {
997 assert(MI.getOpcode() == TargetOpcode::G_FCMP);
998 const auto &ST = MI.getMF()->getSubtarget<AArch64Subtarget>();
999
1000 Register Dst = MI.getOperand(0).getReg();
1001 LLT DstTy = MRI.getType(Dst);
1002 if (!DstTy.isVector() || !ST.hasNEON())
1003 return false;
1004 Register LHS = MI.getOperand(2).getReg();
1005 unsigned EltSize = MRI.getType(LHS).getScalarSizeInBits();
1006 if (EltSize == 16 && !ST.hasFullFP16())
1007 return false;
1008 if (EltSize != 16 && EltSize != 32 && EltSize != 64)
1009 return false;
1010
1011 return true;
1012}
1013
1014/// Try to lower a vector G_FCMP \p MI into an AArch64-specific pseudo.
1015void applyLowerVectorFCMP(MachineInstr &MI, MachineRegisterInfo &MRI,
1016 MachineIRBuilder &MIB) {
1017 assert(MI.getOpcode() == TargetOpcode::G_FCMP);
1018 const auto &ST = MI.getMF()->getSubtarget<AArch64Subtarget>();
1019
1020 const auto &CmpMI = cast<GFCmp>(MI);
1021
1022 Register Dst = CmpMI.getReg(0);
1023 CmpInst::Predicate Pred = CmpMI.getCond();
1024 Register LHS = CmpMI.getLHSReg();
1025 Register RHS = CmpMI.getRHSReg();
1026
1027 LLT DstTy = MRI.getType(Dst);
1028
1029 bool Invert = false;
1031 if ((Pred == CmpInst::Predicate::FCMP_ORD ||
1033 isBuildVectorAllZeros(*MRI.getVRegDef(RHS), MRI)) {
1034 // The special case "fcmp ord %a, 0" is the canonical check that LHS isn't
1035 // NaN, so equivalent to a == a and doesn't need the two comparisons an
1036 // "ord" normally would.
1037 // Similarly, "fcmp uno %a, 0" is the canonical check that LHS is NaN and is
1038 // thus equivalent to a != a.
1039 RHS = LHS;
1041 } else
1042 changeVectorFCMPPredToAArch64CC(Pred, CC, CC2, Invert);
1043
1044 // Instead of having an apply function, just build here to simplify things.
1046
1047 const bool NoNans =
1048 ST.getTargetLowering()->getTargetMachine().Options.NoNaNsFPMath;
1049
1050 auto Cmp = getVectorFCMP(CC, LHS, RHS, NoNans, MRI);
1051 Register CmpRes;
1052 if (CC2 == AArch64CC::AL)
1053 CmpRes = Cmp(MIB);
1054 else {
1055 auto Cmp2 = getVectorFCMP(CC2, LHS, RHS, NoNans, MRI);
1056 auto Cmp2Dst = Cmp2(MIB);
1057 auto Cmp1Dst = Cmp(MIB);
1058 CmpRes = MIB.buildOr(DstTy, Cmp1Dst, Cmp2Dst).getReg(0);
1059 }
1060 if (Invert)
1061 CmpRes = MIB.buildNot(DstTy, CmpRes).getReg(0);
1062 MRI.replaceRegWith(Dst, CmpRes);
1063 MI.eraseFromParent();
1064}
1065
1066// Matches G_BUILD_VECTOR where at least one source operand is not a constant
1067bool matchLowerBuildToInsertVecElt(MachineInstr &MI, MachineRegisterInfo &MRI) {
1068 auto *GBuildVec = cast<GBuildVector>(&MI);
1069
1070 // Check if the values are all constants
1071 for (unsigned I = 0; I < GBuildVec->getNumSources(); ++I) {
1072 auto ConstVal =
1073 getAnyConstantVRegValWithLookThrough(GBuildVec->getSourceReg(I), MRI);
1074
1075 if (!ConstVal.has_value())
1076 return true;
1077 }
1078
1079 return false;
1080}
1081
1082void applyLowerBuildToInsertVecElt(MachineInstr &MI, MachineRegisterInfo &MRI,
1084 auto *GBuildVec = cast<GBuildVector>(&MI);
1085 LLT DstTy = MRI.getType(GBuildVec->getReg(0));
1086 Register DstReg = B.buildUndef(DstTy).getReg(0);
1087
1088 for (unsigned I = 0; I < GBuildVec->getNumSources(); ++I) {
1089 Register SrcReg = GBuildVec->getSourceReg(I);
1090 if (mi_match(SrcReg, MRI, m_GImplicitDef()))
1091 continue;
1092 auto IdxReg = B.buildConstant(LLT::scalar(64), I);
1093 DstReg =
1094 B.buildInsertVectorElement(DstTy, DstReg, SrcReg, IdxReg).getReg(0);
1095 }
1096 B.buildCopy(GBuildVec->getReg(0), DstReg);
1097 GBuildVec->eraseFromParent();
1098}
1099
1100bool matchFormTruncstore(MachineInstr &MI, MachineRegisterInfo &MRI,
1101 Register &SrcReg) {
1102 assert(MI.getOpcode() == TargetOpcode::G_STORE);
1103 Register DstReg = MI.getOperand(0).getReg();
1104 if (MRI.getType(DstReg).isVector())
1105 return false;
1106 // Match a store of a truncate.
1107 if (!mi_match(DstReg, MRI, m_GTrunc(m_Reg(SrcReg))))
1108 return false;
1109 // Only form truncstores for value types of max 64b.
1110 return MRI.getType(SrcReg).getSizeInBits() <= 64;
1111}
1112
1113void applyFormTruncstore(MachineInstr &MI, MachineRegisterInfo &MRI,
1115 Register &SrcReg) {
1116 assert(MI.getOpcode() == TargetOpcode::G_STORE);
1117 Observer.changingInstr(MI);
1118 MI.getOperand(0).setReg(SrcReg);
1119 Observer.changedInstr(MI);
1120}
1121
1122// Lower vector G_SEXT_INREG back to shifts for selection. We allowed them to
1123// form in the first place for combine opportunities, so any remaining ones
1124// at this stage need be lowered back.
1125bool matchVectorSextInReg(MachineInstr &MI, MachineRegisterInfo &MRI) {
1126 assert(MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1127 Register DstReg = MI.getOperand(0).getReg();
1128 LLT DstTy = MRI.getType(DstReg);
1129 return DstTy.isVector();
1130}
1131
1132void applyVectorSextInReg(MachineInstr &MI, MachineRegisterInfo &MRI,
1134 assert(MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1135 B.setInstrAndDebugLoc(MI);
1136 LegalizerHelper Helper(*MI.getMF(), Observer, B);
1137 Helper.lower(MI, 0, /* Unused hint type */ LLT());
1138}
1139
1140/// Combine <N x t>, unused = unmerge(G_EXT <2*N x t> v, undef, N)
1141/// => unused, <N x t> = unmerge v
1142bool matchUnmergeExtToUnmerge(MachineInstr &MI, MachineRegisterInfo &MRI,
1143 Register &MatchInfo) {
1144 auto &Unmerge = cast<GUnmerge>(MI);
1145 if (Unmerge.getNumDefs() != 2)
1146 return false;
1147 if (!MRI.use_nodbg_empty(Unmerge.getReg(1)))
1148 return false;
1149
1150 LLT DstTy = MRI.getType(Unmerge.getReg(0));
1151 if (!DstTy.isVector())
1152 return false;
1153
1154 MachineInstr *Ext = getOpcodeDef(AArch64::G_EXT, Unmerge.getSourceReg(), MRI);
1155 if (!Ext)
1156 return false;
1157
1158 Register ExtSrc1 = Ext->getOperand(1).getReg();
1159 Register ExtSrc2 = Ext->getOperand(2).getReg();
1160 auto LowestVal =
1161 getIConstantVRegValWithLookThrough(Ext->getOperand(3).getReg(), MRI);
1162 if (!LowestVal || LowestVal->Value.getZExtValue() != DstTy.getSizeInBytes())
1163 return false;
1164
1165 if (!getOpcodeDef<GImplicitDef>(ExtSrc2, MRI))
1166 return false;
1167
1168 MatchInfo = ExtSrc1;
1169 return true;
1170}
1171
1172void applyUnmergeExtToUnmerge(MachineInstr &MI, MachineRegisterInfo &MRI,
1174 GISelChangeObserver &Observer, Register &SrcReg) {
1175 Observer.changingInstr(MI);
1176 // Swap dst registers.
1177 Register Dst1 = MI.getOperand(0).getReg();
1178 MI.getOperand(0).setReg(MI.getOperand(1).getReg());
1179 MI.getOperand(1).setReg(Dst1);
1180 MI.getOperand(2).setReg(SrcReg);
1181 Observer.changedInstr(MI);
1182}
1183
1184// Match mul({z/s}ext , {z/s}ext) => {u/s}mull OR
1185// Match v2s64 mul instructions, which will then be scalarised later on
1186// Doing these two matches in one function to ensure that the order of matching
1187// will always be the same.
1188// Try lowering MUL to MULL before trying to scalarize if needed.
1189bool matchMulv2s64(MachineInstr &MI, MachineRegisterInfo &MRI) {
1190 // Get the instructions that defined the source operand
1191 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
1192 return DstTy == LLT::fixed_vector(2, 64);
1193}
1194
1195void applyMulv2s64(MachineInstr &MI, MachineRegisterInfo &MRI,
1197 assert(MI.getOpcode() == TargetOpcode::G_MUL &&
1198 "Expected a G_MUL instruction");
1199
1200 // Get the instructions that defined the source operand
1201 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
1202 assert(DstTy == LLT::fixed_vector(2, 64) && "Expected v2s64 Mul");
1203 LegalizerHelper Helper(*MI.getMF(), Observer, B);
1204 Helper.fewerElementsVector(
1205 MI, 0,
1207}
1208
1209class AArch64PostLegalizerLoweringImpl : public Combiner {
1210protected:
1211 const CombinerHelper Helper;
1212 const AArch64PostLegalizerLoweringImplRuleConfig &RuleConfig;
1213 const AArch64Subtarget &STI;
1214
1215public:
1216 AArch64PostLegalizerLoweringImpl(
1217 MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC,
1218 GISelCSEInfo *CSEInfo,
1219 const AArch64PostLegalizerLoweringImplRuleConfig &RuleConfig,
1220 const AArch64Subtarget &STI);
1221
1222 static const char *getName() { return "AArch6400PreLegalizerCombiner"; }
1223
1224 bool tryCombineAll(MachineInstr &I) const override;
1225
1226private:
1227#define GET_GICOMBINER_CLASS_MEMBERS
1228#include "AArch64GenPostLegalizeGILowering.inc"
1229#undef GET_GICOMBINER_CLASS_MEMBERS
1230};
1231
1232#define GET_GICOMBINER_IMPL
1233#include "AArch64GenPostLegalizeGILowering.inc"
1234#undef GET_GICOMBINER_IMPL
1235
1236AArch64PostLegalizerLoweringImpl::AArch64PostLegalizerLoweringImpl(
1237 MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC,
1238 GISelCSEInfo *CSEInfo,
1239 const AArch64PostLegalizerLoweringImplRuleConfig &RuleConfig,
1240 const AArch64Subtarget &STI)
1241 : Combiner(MF, CInfo, TPC, /*VT*/ nullptr, CSEInfo),
1242 Helper(Observer, B, /*IsPreLegalize*/ true), RuleConfig(RuleConfig),
1243 STI(STI),
1245#include "AArch64GenPostLegalizeGILowering.inc"
1247{
1248}
1249
1250class AArch64PostLegalizerLowering : public MachineFunctionPass {
1251public:
1252 static char ID;
1253
1254 AArch64PostLegalizerLowering();
1255
1256 StringRef getPassName() const override {
1257 return "AArch64PostLegalizerLowering";
1258 }
1259
1260 bool runOnMachineFunction(MachineFunction &MF) override;
1261 void getAnalysisUsage(AnalysisUsage &AU) const override;
1262
1263private:
1264 AArch64PostLegalizerLoweringImplRuleConfig RuleConfig;
1265};
1266} // end anonymous namespace
1267
1268void AArch64PostLegalizerLowering::getAnalysisUsage(AnalysisUsage &AU) const {
1270 AU.setPreservesCFG();
1273}
1274
1275AArch64PostLegalizerLowering::AArch64PostLegalizerLowering()
1277 if (!RuleConfig.parseCommandLineOption())
1278 report_fatal_error("Invalid rule identifier");
1279}
1280
1281bool AArch64PostLegalizerLowering::runOnMachineFunction(MachineFunction &MF) {
1282 if (MF.getProperties().hasFailedISel())
1283 return false;
1284 assert(MF.getProperties().hasLegalized() && "Expected a legalized function?");
1285 auto *TPC = &getAnalysis<TargetPassConfig>();
1286 const Function &F = MF.getFunction();
1287
1289 CombinerInfo CInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
1290 /*LegalizerInfo*/ nullptr, /*OptEnabled=*/true,
1291 F.hasOptSize(), F.hasMinSize());
1292 // Disable fixed-point iteration to reduce compile-time
1293 CInfo.MaxIterations = 1;
1294 CInfo.ObserverLvl = CombinerInfo::ObserverLevel::SinglePass;
1295 // PostLegalizerCombiner performs DCE, so a full DCE pass is unnecessary.
1296 CInfo.EnableFullDCE = false;
1297 AArch64PostLegalizerLoweringImpl Impl(MF, CInfo, TPC, /*CSEInfo*/ nullptr,
1298 RuleConfig, ST);
1299 return Impl.combineMachineInstrs();
1300}
1301
1302char AArch64PostLegalizerLowering::ID = 0;
1303INITIALIZE_PASS_BEGIN(AArch64PostLegalizerLowering, DEBUG_TYPE,
1304 "Lower AArch64 MachineInstrs after legalization", false,
1305 false)
1307INITIALIZE_PASS_END(AArch64PostLegalizerLowering, DEBUG_TYPE,
1308 "Lower AArch64 MachineInstrs after legalization", false,
1309 false)
1310
1311namespace llvm {
1313 return new AArch64PostLegalizerLowering();
1314}
1315} // end namespace llvm
unsigned const MachineRegisterInfo * MRI
static bool isVShiftRImm(SDValue Op, EVT VT, bool isNarrow, int64_t &Cnt)
isVShiftRImm - Check if this is a valid build_vector for the immediate operand of a vector shift righ...
static bool isINSMask(ArrayRef< int > M, int NumInputElements, bool &DstIsLeft, int &Anomaly)
static unsigned getCmpOperandFoldingProfit(SDValue Op)
Returns how profitable it is to fold a comparison's operand's shift and/or extension operations.
This file declares the targeting of the Machinelegalizer class for AArch64.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define GET_GICOMBINER_CONSTRUCTOR_INITS
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This contains common combine transformations that may be used in a combine pass,or by the target else...
Option class for Targets to specify which operations are combined how and when.
This contains the base class for all Combiners generated by TableGen.
This contains common code to allow clients to notify changes to machine instr.
#define DEBUG_TYPE
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register Reg
Promote Memory to Register
Definition Mem2Reg.cpp:110
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
#define P(N)
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
static StringRef getName(Value *V)
Target-Independent Code Generator Pass Configuration Options pass.
Value * RHS
Value * LHS
BinaryOperator * Mul
APInt bitcastToAPInt() const
Definition APFloat.h:1335
Class for arbitrary precision integers.
Definition APInt.h:78
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1541
unsigned logBase2() const
Definition APInt.h:1762
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition Pass.cpp:270
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
This class is the base class for the comparison instructions.
Definition InstrTypes.h:664
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:676
@ ICMP_SLT
signed less than
Definition InstrTypes.h:705
@ ICMP_SLE
signed less or equal
Definition InstrTypes.h:706
@ ICMP_UGE
unsigned greater or equal
Definition InstrTypes.h:700
@ ICMP_UGT
unsigned greater than
Definition InstrTypes.h:699
@ ICMP_SGT
signed greater than
Definition InstrTypes.h:703
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:701
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
Definition InstrTypes.h:685
@ ICMP_SGE
signed greater or equal
Definition InstrTypes.h:704
@ ICMP_ULE
unsigned less or equal
Definition InstrTypes.h:702
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Definition InstrTypes.h:686
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Definition InstrTypes.h:827
Combiner implementation.
Definition Combiner.h:34
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
The CSE Analysis object.
Definition CSEInfo.h:71
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
constexpr bool isScalableVector() const
Returns true if the LLT is a scalable vector.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
constexpr ElementCount getElementCount() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineFunctionProperties & getProperties() const
Get the function properties.
Helper class to build MachineInstr.
MachineInstrBuilder buildNot(const DstOp &Dst, const SrcOp &Src0)
Build and insert a bitwise not, NegOne = G_CONSTANT -1 Res = G_OR Op0, NegOne.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
void setInstrAndDebugLoc(MachineInstr &MI)
Set the insertion point to before MI, and set the debug loc to MI's loc.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildOr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_OR Op0, Op1.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
Register getReg(unsigned Idx) const
Get the register for the operand index.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition Pass.cpp:85
Wrapper class representing virtual and physical registers.
Definition Register.h:20
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Target-Independent Code Generator Pass Configuration Options.
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
Definition TypeSize.h:252
#define UINT64_MAX
Definition DataTypes.h:77
#define INT64_MIN
Definition DataTypes.h:74
#define INT64_MAX
Definition DataTypes.h:71
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::optional< RegOrConstant > getAArch64VectorSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI)
constexpr bool isLegalArithImmed(const uint64_t C)
void changeVectorFCMPPredToAArch64CC(const CmpInst::Predicate P, AArch64CC::CondCode &CondCode, AArch64CC::CondCode &CondCode2, bool &Invert)
Find the AArch64 condition codes necessary to represent P for a vector floating point comparison.
bool isCMN(const MachineInstr *MaybeSub, const CmpInst::Predicate &Pred, const MachineRegisterInfo &MRI)
std::optional< int64_t > getAArch64VectorSplatScalar(const MachineInstr &MI, const MachineRegisterInfo &MRI)
void expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl< ImmInsnModel > &Insn)
Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more real move-immediate instructions to...
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
operand_type_match m_Reg()
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
ImplicitDefMatch m_GImplicitDef()
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
Predicate getPredicate(unsigned Condition, unsigned Hint)
Return predicate consisting of specified condition and hint bits.
@ Undef
Value of the register doesn't matter.
NodeAddr< DefNode * > Def
Definition RDFGraph.h:384
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:532
LLVM_ABI bool isBuildVectorAllZeros(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndef=false)
Return true if the specified instruction is a G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC where all of the...
Definition Utils.cpp:1481
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1725
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
Definition Utils.cpp:651
bool isZIPMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut, unsigned &OperandOrderOut)
Return true for zip1 or zip2 masks of the form: <0, 8, 1, 9, 2, 10, 3, 11> (WhichResultOut = 0,...
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:284
LLVM_ABI MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
Definition Utils.cpp:492
FunctionPass * createAArch64PostLegalizerLowering()
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1732
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
bool isUZPMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut)
Return true for uzp1 or uzp2 masks of the form: <0, 2, 4, 6, 8, 10, 12, 14> or <1,...
bool isREVMask(ArrayRef< int > M, unsigned EltSize, unsigned NumElts, unsigned BlockSize)
isREVMask - Check if a vector shuffle corresponds to a REV instruction with the specified blocksize.
LLVM_ABI std::optional< ValueAndVReg > getAnyConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true, bool LookThroughAnyExt=false)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT or G_FCONST...
Definition Utils.cpp:439
LLVM_ABI bool isBuildVectorAllOnes(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndef=false)
Return true if the specified instruction is a G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC where all of the...
Definition Utils.cpp:1487
LLVM_ABI void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU)
Modify analysis usage so it preserves passes required for the SelectionDAG fallback.
Definition Utils.cpp:1184
bool isTRNMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut)
Return true for trn1 or trn2 masks of the form: <0, 8, 2, 10, 4, 12, 6, 14> or <1,...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
Definition Utils.cpp:433
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1758
LLVM_ABI int getSplatIndex(ArrayRef< int > Mask)
If all non-negative Mask elements are the same value, return that value.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:869
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
@ SinglePass
Enables Observer-based DCE and additional heuristics that retry combining defined and used instructio...
Matching combinators.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.