LLVM 24.0.0git
AArch64InstructionSelector.cpp
Go to the documentation of this file.
1//===- AArch64InstructionSelector.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/// \file
9/// This file implements the targeting of the InstructionSelector class for
10/// AArch64.
11/// \todo This should be generated by TableGen.
12//===----------------------------------------------------------------------===//
13
14#include "AArch64ExpandImm.h"
16#include "AArch64InstrInfo.h"
19#include "AArch64RegisterInfo.h"
20#include "AArch64Subtarget.h"
43#include "llvm/IR/Constants.h"
46#include "llvm/IR/IntrinsicsAArch64.h"
47#include "llvm/IR/Type.h"
48#include "llvm/Pass.h"
49#include "llvm/Support/Debug.h"
51#include <optional>
52
53#define DEBUG_TYPE "aarch64-isel"
54
55using namespace llvm;
56using namespace MIPatternMatch;
57using namespace AArch64GISelUtils;
58
59namespace llvm {
62}
63
64namespace {
65
66#define GET_GLOBALISEL_PREDICATE_BITSET
67#include "AArch64GenGlobalISel.inc"
68#undef GET_GLOBALISEL_PREDICATE_BITSET
69
70
71class AArch64InstructionSelector : public InstructionSelector {
72public:
73 AArch64InstructionSelector(const AArch64TargetMachine &TM,
74 const AArch64Subtarget &STI,
75 const AArch64RegisterBankInfo &RBI);
76
77 bool select(MachineInstr &I) override;
78 static const char *getName() { return DEBUG_TYPE; }
79
80 void setupMF(MachineFunction &MF, GISelValueTracking *VT,
81 CodeGenCoverage *CoverageInfo, ProfileSummaryInfo *PSI,
82 BlockFrequencyInfo *BFI) override {
83 InstructionSelector::setupMF(MF, VT, CoverageInfo, PSI, BFI);
84 MIB.setMF(MF);
85
86 // hasFnAttribute() is expensive to call on every BRCOND selection, so
87 // cache it here for each run of the selector.
88 ProduceNonFlagSettingCondBr =
89 !MF.getFunction().hasFnAttribute(Attribute::SpeculativeLoadHardening);
90 MFReturnAddr = Register();
91
92 processPHIs(MF);
93 }
94
95private:
96 /// tblgen-erated 'select' implementation, used as the initial selector for
97 /// the patterns that don't require complex C++.
98 bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
99
100 // A lowering phase that runs before any selection attempts.
101 // Returns true if the instruction was modified.
102 bool preISelLower(MachineInstr &I);
103
104 // An early selection function that runs before the selectImpl() call.
105 bool earlySelect(MachineInstr &I);
106
107 /// Save state that is shared between select calls, call select on \p I and
108 /// then restore the saved state. This can be used to recursively call select
109 /// within a select call.
110 bool selectAndRestoreState(MachineInstr &I);
111
112 // Do some preprocessing of G_PHIs before we begin selection.
113 void processPHIs(MachineFunction &MF);
114
115 bool earlySelectSHL(MachineInstr &I, MachineRegisterInfo &MRI);
116
117 /// Eliminate same-sized cross-bank copies into stores before selectImpl().
118 bool contractCrossBankCopyIntoStore(MachineInstr &I,
120
121 bool convertPtrAddToAdd(MachineInstr &I, MachineRegisterInfo &MRI);
122
123 bool selectVaStartAAPCS(MachineInstr &I, MachineFunction &MF,
124 MachineRegisterInfo &MRI) const;
125 bool selectVaStartDarwin(MachineInstr &I, MachineFunction &MF,
126 MachineRegisterInfo &MRI) const;
127
128 ///@{
129 /// Helper functions for selectCompareBranch.
130 bool selectCompareBranchFedByFCmp(MachineInstr &I, MachineInstr &FCmp,
131 MachineIRBuilder &MIB) const;
132 bool selectCompareBranchFedByICmp(MachineInstr &I, MachineInstr &ICmp,
133 MachineIRBuilder &MIB) const;
134 bool tryOptCompareBranchFedByICmp(MachineInstr &I, MachineInstr &ICmp,
135 MachineIRBuilder &MIB) const;
136 bool tryOptAndIntoCompareBranch(MachineInstr &AndInst, bool Invert,
137 MachineBasicBlock *DstMBB,
138 MachineIRBuilder &MIB) const;
139 ///@}
140
141 bool selectCompareBranch(MachineInstr &I, MachineFunction &MF,
143
144 bool selectVectorAshrLshr(MachineInstr &I, MachineRegisterInfo &MRI);
145 bool selectVectorSHL(MachineInstr &I, MachineRegisterInfo &MRI);
146
147 // Helper to generate an equivalent of scalar_to_vector into a new register,
148 // returned via 'Dst'.
149 MachineInstr *emitScalarToVector(unsigned EltSize,
150 const TargetRegisterClass *DstRC,
151 Register Scalar,
152 MachineIRBuilder &MIRBuilder) const;
153 /// Helper to narrow vector that was widened by emitScalarToVector.
154 /// Copy lowest part of 128-bit or 64-bit vector to 64-bit or 32-bit
155 /// vector, correspondingly.
156 MachineInstr *emitNarrowVector(Register DstReg, Register SrcReg,
157 MachineIRBuilder &MIRBuilder,
158 MachineRegisterInfo &MRI) const;
159
160 /// Emit a lane insert into \p DstReg, or a new vector register if
161 /// std::nullopt is provided.
162 ///
163 /// The lane inserted into is defined by \p LaneIdx. The vector source
164 /// register is given by \p SrcReg. The register containing the element is
165 /// given by \p EltReg.
166 MachineInstr *emitLaneInsert(std::optional<Register> DstReg, Register SrcReg,
167 Register EltReg, unsigned LaneIdx,
168 const RegisterBank &RB,
169 MachineIRBuilder &MIRBuilder) const;
170
171 /// Emit a sequence of instructions representing a constant \p Imm for a
172 /// vector register \p Dst via MOVI.
173 MachineInstr *emitConstantMOVVector(DstOp Dst, APInt Imm,
175
176 /// Emit a sequence of instructions representing a constant \p CV for a
177 /// vector register \p Dst. (E.g. a MOV, or a load from a constant pool.)
178 ///
179 /// \returns the last instruction in the sequence on success, and nullptr
180 /// otherwise.
181 MachineInstr *emitConstantVector(Register Dst, Constant *CV, APInt Imm,
183
184 bool tryOptConstantBuildVec(MachineInstr &MI, LLT DstTy,
186 /// \returns true if a G_BUILD_VECTOR instruction \p MI can be selected as a
187 /// SUBREG_TO_REG.
188 bool tryOptBuildVecToSubregToReg(MachineInstr &MI, MachineRegisterInfo &MRI);
189 bool selectBuildVector(MachineInstr &I, MachineRegisterInfo &MRI);
192
193 bool selectShuffleVector(MachineInstr &I, MachineRegisterInfo &MRI);
194 bool selectExtractElt(MachineInstr &I, MachineRegisterInfo &MRI);
195 bool selectConcatVectors(MachineInstr &I, MachineRegisterInfo &MRI);
196 bool selectSplitVectorUnmerge(MachineInstr &I, MachineRegisterInfo &MRI);
197
198 /// Helper function to select vector load intrinsics like
199 /// @llvm.aarch64.neon.ld2.*, @llvm.aarch64.neon.ld4.*, etc.
200 /// \p Opc is the opcode that the selected instruction should use.
201 /// \p NumVecs is the number of vector destinations for the instruction.
202 /// \p I is the original G_INTRINSIC_W_SIDE_EFFECTS instruction.
203 bool selectVectorLoadIntrinsic(unsigned Opc, unsigned NumVecs,
204 MachineInstr &I);
205 bool selectVectorLoadLaneIntrinsic(unsigned Opc, unsigned NumVecs,
206 MachineInstr &I);
207 void selectVectorStoreIntrinsic(MachineInstr &I, unsigned NumVecs,
208 unsigned Opc);
209 bool selectVectorStoreLaneIntrinsic(MachineInstr &I, unsigned NumVecs,
210 unsigned Opc);
211 bool selectIntrinsicWithSideEffects(MachineInstr &I,
213 bool selectIntrinsic(MachineInstr &I, MachineRegisterInfo &MRI);
214 bool selectJumpTable(MachineInstr &I, MachineRegisterInfo &MRI);
215 bool selectBrJT(MachineInstr &I, MachineRegisterInfo &MRI);
216 bool selectTLSGlobalValueELF(MachineInstr &I, MachineRegisterInfo &MRI);
217 bool selectTLSLocalExecELF(const GlobalValue *GV, MachineInstr &I,
219 bool selectTLSGlobalValueMachO(MachineInstr &I, MachineRegisterInfo &MRI);
220 bool selectTLSGlobalValue(MachineInstr &I, MachineRegisterInfo &MRI);
221 bool selectPtrAuthGlobalValue(MachineInstr &I,
222 MachineRegisterInfo &MRI) const;
223 bool selectMOPS(MachineInstr &I, MachineRegisterInfo &MRI);
224 bool selectUSMovFromExtend(MachineInstr &I, MachineRegisterInfo &MRI);
225 void SelectTable(MachineInstr &I, MachineRegisterInfo &MRI, unsigned NumVecs,
226 unsigned Opc1, unsigned Opc2, bool isExt);
227
228 bool selectIndexedExtLoad(MachineInstr &I, MachineRegisterInfo &MRI);
229 bool selectIndexedLoad(MachineInstr &I, MachineRegisterInfo &MRI);
230 bool selectIndexedStore(GIndexedStore &I, MachineRegisterInfo &MRI);
231
232 unsigned emitConstantPoolEntry(const Constant *CPVal,
233 MachineFunction &MF) const;
235 MachineIRBuilder &MIRBuilder) const;
236
237 // Emit a vector concat operation.
238 MachineInstr *emitVectorConcat(std::optional<Register> Dst, Register Op1,
239 Register Op2,
240 MachineIRBuilder &MIRBuilder) const;
241
242 // Emit an integer compare between LHS and RHS, which checks for Predicate.
243 MachineInstr *emitIntegerCompare(MachineOperand &LHS, MachineOperand &RHS,
245 MachineIRBuilder &MIRBuilder) const;
246
247 /// Emit a floating point comparison between \p LHS and \p RHS.
248 /// \p Pred if given is the intended predicate to use.
250 emitFPCompare(Register LHS, Register RHS, MachineIRBuilder &MIRBuilder,
251 std::optional<CmpInst::Predicate> = std::nullopt) const;
252
254 emitInstr(unsigned Opcode, std::initializer_list<llvm::DstOp> DstOps,
255 std::initializer_list<llvm::SrcOp> SrcOps,
256 MachineIRBuilder &MIRBuilder,
257 const ComplexRendererFns &RenderFns = std::nullopt) const;
258 /// Helper function to emit an add or sub instruction.
259 ///
260 /// \p AddrModeAndSizeToOpcode must contain each of the opcode variants above
261 /// in a specific order.
262 ///
263 /// Below is an example of the expected input to \p AddrModeAndSizeToOpcode.
264 ///
265 /// \code
266 /// const std::array<std::array<unsigned, 2>, 4> Table {
267 /// {{AArch64::ADDXri, AArch64::ADDWri},
268 /// {AArch64::ADDXrs, AArch64::ADDWrs},
269 /// {AArch64::ADDXrr, AArch64::ADDWrr},
270 /// {AArch64::SUBXri, AArch64::SUBWri},
271 /// {AArch64::ADDXrx, AArch64::ADDWrx}}};
272 /// \endcode
273 ///
274 /// Each row in the table corresponds to a different addressing mode. Each
275 /// column corresponds to a different register size.
276 ///
277 /// \attention Rows must be structured as follows:
278 /// - Row 0: The ri opcode variants
279 /// - Row 1: The rs opcode variants
280 /// - Row 2: The rr opcode variants
281 /// - Row 3: The ri opcode variants for negative immediates
282 /// - Row 4: The rx opcode variants
283 ///
284 /// \attention Columns must be structured as follows:
285 /// - Column 0: The 64-bit opcode variants
286 /// - Column 1: The 32-bit opcode variants
287 ///
288 /// \p Dst is the destination register of the binop to emit.
289 /// \p LHS is the left-hand operand of the binop to emit.
290 /// \p RHS is the right-hand operand of the binop to emit.
291 MachineInstr *emitAddSub(
292 const std::array<std::array<unsigned, 2>, 5> &AddrModeAndSizeToOpcode,
294 MachineIRBuilder &MIRBuilder) const;
295 MachineInstr *emitADD(Register DefReg, MachineOperand &LHS,
297 MachineIRBuilder &MIRBuilder) const;
299 MachineIRBuilder &MIRBuilder) const;
301 MachineIRBuilder &MIRBuilder) const;
303 MachineIRBuilder &MIRBuilder) const;
305 MachineIRBuilder &MIRBuilder) const;
307 MachineIRBuilder &MIRBuilder) const;
309 MachineIRBuilder &MIRBuilder) const;
311 MachineIRBuilder &MIRBuilder) const;
314 MachineIRBuilder &MIRBuilder) const;
315 MachineInstr *emitExtractVectorElt(std::optional<Register> DstReg,
316 const RegisterBank &DstRB, LLT ScalarTy,
317 Register VecReg, unsigned LaneIdx,
318 MachineIRBuilder &MIRBuilder) const;
319 MachineInstr *emitCSINC(Register Dst, Register Src1, Register Src2,
321 MachineIRBuilder &MIRBuilder) const;
322 /// Emit a CSet for a FP compare.
323 ///
324 /// \p Dst is expected to be a 32-bit scalar register.
325 MachineInstr *emitCSetForFCmp(Register Dst, CmpInst::Predicate Pred,
326 MachineIRBuilder &MIRBuilder) const;
327
328 /// Emit an instruction that sets NZCV to the carry-in expected by \p I.
329 /// Might elide the instruction if the previous instruction already sets NZCV
330 /// correctly.
331 MachineInstr *emitCarryIn(MachineInstr &I, Register CarryReg);
332
333 /// Emit the overflow op for \p Opcode.
334 ///
335 /// \p Opcode is expected to be an overflow op's opcode, e.g. G_UADDO,
336 /// G_USUBO, etc.
337 std::pair<MachineInstr *, AArch64CC::CondCode>
338 emitOverflowOp(unsigned Opcode, Register Dst, MachineOperand &LHS,
339 MachineOperand &RHS, MachineIRBuilder &MIRBuilder) const;
340
341 bool selectOverflowOp(MachineInstr &I, MachineRegisterInfo &MRI);
342
343 /// Emit expression as a conjunction (a series of CCMP/CFCMP ops).
344 /// In some cases this is even possible with OR operations in the expression.
346 MachineIRBuilder &MIB) const;
351 MachineIRBuilder &MIB) const;
353 bool Negate, Register CCOp,
355 MachineIRBuilder &MIB) const;
356
357 /// Emit a TB(N)Z instruction which tests \p Bit in \p TestReg.
358 /// \p IsNegative is true if the test should be "not zero".
359 /// This will also optimize the test bit instruction when possible.
360 MachineInstr *emitTestBit(Register TestReg, uint64_t Bit, bool IsNegative,
361 MachineBasicBlock *DstMBB,
362 MachineIRBuilder &MIB) const;
363
364 /// Emit a CB(N)Z instruction which branches to \p DestMBB.
365 MachineInstr *emitCBZ(Register CompareReg, bool IsNegative,
366 MachineBasicBlock *DestMBB,
367 MachineIRBuilder &MIB) const;
368
369 // Equivalent to the i32shift_a and friends from AArch64InstrInfo.td.
370 // We use these manually instead of using the importer since it doesn't
371 // support SDNodeXForm.
372 ComplexRendererFns selectShiftA_32(const MachineOperand &Root) const;
373 ComplexRendererFns selectShiftB_32(const MachineOperand &Root) const;
374 ComplexRendererFns selectShiftA_64(const MachineOperand &Root) const;
375 ComplexRendererFns selectShiftB_64(const MachineOperand &Root) const;
376
377 template <unsigned ShiftWidth>
378 ComplexRendererFns selectShiftMask(MachineOperand &Root) const;
379 ComplexRendererFns select12BitValueWithLeftShift(uint64_t Immed) const;
380 ComplexRendererFns selectArithImmed(MachineOperand &Root) const;
381 ComplexRendererFns selectNegArithImmed(MachineOperand &Root) const;
382
383 ComplexRendererFns selectAddrModeUnscaled(MachineOperand &Root,
384 unsigned Size) const;
385
386 ComplexRendererFns selectAddrModeUnscaled8(MachineOperand &Root) const {
387 return selectAddrModeUnscaled(Root, 1);
388 }
389 ComplexRendererFns selectAddrModeUnscaled16(MachineOperand &Root) const {
390 return selectAddrModeUnscaled(Root, 2);
391 }
392 ComplexRendererFns selectAddrModeUnscaled32(MachineOperand &Root) const {
393 return selectAddrModeUnscaled(Root, 4);
394 }
395 ComplexRendererFns selectAddrModeUnscaled64(MachineOperand &Root) const {
396 return selectAddrModeUnscaled(Root, 8);
397 }
398 ComplexRendererFns selectAddrModeUnscaled128(MachineOperand &Root) const {
399 return selectAddrModeUnscaled(Root, 16);
400 }
401
402 /// Helper to try to fold in a GISEL_ADD_LOW into an immediate, to be used
403 /// from complex pattern matchers like selectAddrModeIndexed().
404 ComplexRendererFns tryFoldAddLowIntoImm(MachineInstr &RootDef, unsigned Size,
405 MachineRegisterInfo &MRI) const;
406
407 ComplexRendererFns selectAddrModeIndexed(MachineOperand &Root,
408 unsigned Size) const;
409 template <int Width>
410 ComplexRendererFns selectAddrModeIndexed(MachineOperand &Root) const {
411 return selectAddrModeIndexed(Root, Width / 8);
412 }
413
414 std::optional<bool>
415 isWorthFoldingIntoAddrMode(const MachineInstr &MI,
416 const MachineRegisterInfo &MRI) const;
417
418 bool isWorthFoldingIntoExtendedReg(const MachineInstr &MI,
420 bool IsAddrOperand) const;
421 ComplexRendererFns
422 selectAddrModeShiftedExtendXReg(MachineOperand &Root,
423 unsigned SizeInBytes) const;
424
425 /// Returns a \p ComplexRendererFns which contains a base, offset, and whether
426 /// or not a shift + extend should be folded into an addressing mode. Returns
427 /// None when this is not profitable or possible.
428 ComplexRendererFns
429 selectExtendedSHL(MachineOperand &Root, MachineOperand &Base,
430 MachineOperand &Offset, unsigned SizeInBytes,
431 bool WantsExt) const;
432 ComplexRendererFns selectAddrModeRegisterOffset(MachineOperand &Root) const;
433 ComplexRendererFns selectAddrModeXRO(MachineOperand &Root,
434 unsigned SizeInBytes) const;
435 template <int Width>
436 ComplexRendererFns selectAddrModeXRO(MachineOperand &Root) const {
437 return selectAddrModeXRO(Root, Width / 8);
438 }
439
440 ComplexRendererFns selectAddrModeWRO(MachineOperand &Root,
441 unsigned SizeInBytes) const;
442 template <int Width>
443 ComplexRendererFns selectAddrModeWRO(MachineOperand &Root) const {
444 return selectAddrModeWRO(Root, Width / 8);
445 }
446
447 ComplexRendererFns selectShiftedRegister(MachineOperand &Root,
448 bool AllowROR = false) const;
449
450 ComplexRendererFns selectArithShiftedRegister(MachineOperand &Root) const {
451 return selectShiftedRegister(Root);
452 }
453
454 ComplexRendererFns selectLogicalShiftedRegister(MachineOperand &Root) const {
455 return selectShiftedRegister(Root, true);
456 }
457
458 /// Given an extend instruction, determine the correct shift-extend type for
459 /// that instruction.
460 ///
461 /// If the instruction is going to be used in a load or store, pass
462 /// \p IsLoadStore = true.
464 getExtendTypeForInst(MachineInstr &MI, MachineRegisterInfo &MRI,
465 bool IsLoadStore = false) const;
466
467 /// Move \p Reg to \p RC if \p Reg is not already on \p RC.
468 ///
469 /// \returns Either \p Reg if no change was necessary, or the new register
470 /// created by moving \p Reg.
471 ///
472 /// Note: This uses emitCopy right now.
473 Register moveScalarRegClass(Register Reg, const TargetRegisterClass &RC,
474 MachineIRBuilder &MIB) const;
475
476 ComplexRendererFns selectArithExtendedRegister(MachineOperand &Root) const;
477
478 ComplexRendererFns selectExtractHigh(MachineOperand &Root) const;
479 template <unsigned Width>
480 ComplexRendererFns selectCVTFixedPoint(MachineOperand &Root) const;
481 template <unsigned Width>
482 ComplexRendererFns selectCVTFixedPosRecipOperand(MachineOperand &Root) const;
483 ComplexRendererFns selectCVTFixedPointBase(const MachineOperand &Root,
484 unsigned width,
485 bool isReciprocal = false) const;
486 ComplexRendererFns selectCVTFixedPointVec(MachineOperand &Root) const;
487 ComplexRendererFns
488 selectCVTFixedPosRecipOperandVec(MachineOperand &Root) const;
489 void renderFixedPointScalarXForm(MachineInstrBuilder &MIB,
490 const MachineInstr &MI, int OpIdx) const;
491 unsigned getFixedPointWidthFromOperand(const MachineOperand &Root) const;
492 void renderFixedPointXForm(MachineInstrBuilder &MIB, const MachineInstr &MI,
493 int OpIdx = -1) const;
494 void renderFixedPointRecipXForm(MachineInstrBuilder &MIB,
495 const MachineInstr &MI, int OpIdx = -1) const;
496 void renderFixedPointImm(MachineInstrBuilder &MIB, const MachineOperand &Root,
497 unsigned Width, bool isReciprocal) const;
498 void renderTruncImm(MachineInstrBuilder &MIB, const MachineInstr &MI,
499 int OpIdx = -1) const;
500 void renderLogicalImm32(MachineInstrBuilder &MIB, const MachineInstr &I,
501 int OpIdx = -1) const;
502 void renderLogicalImm64(MachineInstrBuilder &MIB, const MachineInstr &I,
503 int OpIdx = -1) const;
504 void renderUbsanTrap(MachineInstrBuilder &MIB, const MachineInstr &MI,
505 int OpIdx) const;
506 void renderFPImm16(MachineInstrBuilder &MIB, const MachineInstr &MI,
507 int OpIdx = -1) const;
508 void renderFPImm32(MachineInstrBuilder &MIB, const MachineInstr &MI,
509 int OpIdx = -1) const;
510 void renderFPImm64(MachineInstrBuilder &MIB, const MachineInstr &MI,
511 int OpIdx = -1) const;
512 void renderFPImm32SIMDModImmType4(MachineInstrBuilder &MIB,
513 const MachineInstr &MI,
514 int OpIdx = -1) const;
515
516 // Materialize a GlobalValue or BlockAddress using a movz+movk sequence.
517 void materializeLargeCMVal(MachineInstr &I, const Value *V, unsigned OpFlags);
518
519 // Optimization methods.
520 bool tryOptSelect(GSelect &Sel);
521 bool tryOptSelectConjunction(GSelect &Sel, MachineInstr &CondMI);
522 MachineInstr *tryFoldIntegerCompare(MachineOperand &LHS, MachineOperand &RHS,
524 MachineIRBuilder &MIRBuilder) const;
525
526 /// Return true if \p MI is a load or store of \p NumBytes bytes.
527 bool isLoadStoreOfNumBytes(const MachineInstr &MI, unsigned NumBytes) const;
528
529 /// Returns true if \p MI is guaranteed to have the high-half of a 64-bit
530 /// register zeroed out. In other words, the result of MI has been explicitly
531 /// zero extended.
532 bool isDef32(const MachineInstr &MI) const;
533
534 const AArch64TargetMachine &TM;
535 const AArch64Subtarget &STI;
536 const AArch64InstrInfo &TII;
538 const AArch64RegisterBankInfo &RBI;
539
540 bool ProduceNonFlagSettingCondBr = false;
541
542 // Some cached values used during selection.
543 // We use LR as a live-in register, and we keep track of it here as it can be
544 // clobbered by calls.
545 Register MFReturnAddr;
546
548
549#define GET_GLOBALISEL_PREDICATES_DECL
550#include "AArch64GenGlobalISel.inc"
551#undef GET_GLOBALISEL_PREDICATES_DECL
552
553// We declare the temporaries used by selectImpl() in the class to minimize the
554// cost of constructing placeholder values.
555#define GET_GLOBALISEL_TEMPORARIES_DECL
556#include "AArch64GenGlobalISel.inc"
557#undef GET_GLOBALISEL_TEMPORARIES_DECL
558};
559
560} // end anonymous namespace
561
562#define GET_GLOBALISEL_IMPL
563#include "AArch64GenGlobalISel.inc"
564#undef GET_GLOBALISEL_IMPL
565
566AArch64InstructionSelector::AArch64InstructionSelector(
567 const AArch64TargetMachine &TM, const AArch64Subtarget &STI,
568 const AArch64RegisterBankInfo &RBI)
569 : TM(TM), STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()),
570 RBI(RBI),
572#include "AArch64GenGlobalISel.inc"
575#include "AArch64GenGlobalISel.inc"
577{
578}
579
580// FIXME: This should be target-independent, inferred from the types declared
581// for each class in the bank.
582//
583/// Given a register bank, and a type, return the smallest register class that
584/// can represent that combination.
585static const TargetRegisterClass *
586getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB,
587 bool GetAllRegSet = false) {
588 if (RB.getID() == AArch64::GPRRegBankID) {
589 if (Ty.getSizeInBits() <= 32)
590 return GetAllRegSet ? &AArch64::GPR32allRegClass
591 : &AArch64::GPR32RegClass;
592 if (Ty.getSizeInBits() == 64)
593 return GetAllRegSet ? &AArch64::GPR64allRegClass
594 : &AArch64::GPR64RegClass;
595 if (Ty.getSizeInBits() == 128)
596 return &AArch64::XSeqPairsClassRegClass;
597 return nullptr;
598 }
599
600 if (RB.getID() == AArch64::FPRRegBankID) {
601 switch (Ty.getSizeInBits()) {
602 case 8:
603 return &AArch64::FPR8RegClass;
604 case 16:
605 return &AArch64::FPR16RegClass;
606 case 32:
607 return &AArch64::FPR32RegClass;
608 case 64:
609 return &AArch64::FPR64RegClass;
610 case 128:
611 return &AArch64::FPR128RegClass;
612 }
613 return nullptr;
614 }
615
616 return nullptr;
617}
618
619/// Given a register bank, and size in bits, return the smallest register class
620/// that can represent that combination.
621static const TargetRegisterClass *
623 bool GetAllRegSet = false) {
624 if (SizeInBits.isScalable()) {
625 assert(RB.getID() == AArch64::FPRRegBankID &&
626 "Expected FPR regbank for scalable type size");
627 return &AArch64::ZPRRegClass;
628 }
629
630 unsigned RegBankID = RB.getID();
631
632 if (RegBankID == AArch64::GPRRegBankID) {
633 assert(!SizeInBits.isScalable() && "Unexpected scalable register size");
634 if (SizeInBits <= 32)
635 return GetAllRegSet ? &AArch64::GPR32allRegClass
636 : &AArch64::GPR32RegClass;
637 if (SizeInBits == 64)
638 return GetAllRegSet ? &AArch64::GPR64allRegClass
639 : &AArch64::GPR64RegClass;
640 if (SizeInBits == 128)
641 return &AArch64::XSeqPairsClassRegClass;
642 }
643
644 if (RegBankID == AArch64::FPRRegBankID) {
645 if (SizeInBits.isScalable()) {
646 assert(SizeInBits == TypeSize::getScalable(128) &&
647 "Unexpected scalable register size");
648 return &AArch64::ZPRRegClass;
649 }
650
651 switch (SizeInBits) {
652 default:
653 return nullptr;
654 case 8:
655 return &AArch64::FPR8RegClass;
656 case 16:
657 return &AArch64::FPR16RegClass;
658 case 32:
659 return &AArch64::FPR32RegClass;
660 case 64:
661 return &AArch64::FPR64RegClass;
662 case 128:
663 return &AArch64::FPR128RegClass;
664 }
665 }
666
667 return nullptr;
668}
669
670/// Returns the correct subregister to use for a given register class.
672 const TargetRegisterInfo &TRI, unsigned &SubReg) {
673 switch (TRI.getRegSizeInBits(*RC)) {
674 case 8:
675 SubReg = AArch64::bsub;
676 break;
677 case 16:
678 SubReg = AArch64::hsub;
679 break;
680 case 32:
681 if (RC != &AArch64::FPR32RegClass)
682 SubReg = AArch64::sub_32;
683 else
684 SubReg = AArch64::ssub;
685 break;
686 case 64:
687 SubReg = AArch64::dsub;
688 break;
689 default:
691 dbgs() << "Couldn't find appropriate subregister for register class.");
692 return false;
693 }
694
695 return true;
696}
697
698/// Returns the minimum size the given register bank can hold.
699static unsigned getMinSizeForRegBank(const RegisterBank &RB) {
700 switch (RB.getID()) {
701 case AArch64::GPRRegBankID:
702 return 32;
703 case AArch64::FPRRegBankID:
704 return 8;
705 default:
706 llvm_unreachable("Tried to get minimum size for unknown register bank.");
707 }
708}
709
710/// Create a REG_SEQUENCE instruction using the registers in \p Regs.
711/// Helper function for functions like createDTuple and createQTuple.
712///
713/// \p RegClassIDs - The list of register class IDs available for some tuple of
714/// a scalar class. E.g. QQRegClassID, QQQRegClassID, QQQQRegClassID. This is
715/// expected to contain between 2 and 4 tuple classes.
716///
717/// \p SubRegs - The list of subregister classes associated with each register
718/// class ID in \p RegClassIDs. E.g., QQRegClassID should use the qsub0
719/// subregister class. The index of each subregister class is expected to
720/// correspond with the index of each register class.
721///
722/// \returns Either the destination register of REG_SEQUENCE instruction that
723/// was created, or the 0th element of \p Regs if \p Regs contains a single
724/// element.
726 const unsigned RegClassIDs[],
727 const unsigned SubRegs[], MachineIRBuilder &MIB) {
728 unsigned NumRegs = Regs.size();
729 if (NumRegs == 1)
730 return Regs[0];
731 assert(NumRegs >= 2 && NumRegs <= 4 &&
732 "Only support between two and 4 registers in a tuple!");
734 auto *DesiredClass = TRI->getRegClass(RegClassIDs[NumRegs - 2]);
735 auto RegSequence =
736 MIB.buildInstr(TargetOpcode::REG_SEQUENCE, {DesiredClass}, {});
737 for (unsigned I = 0, E = Regs.size(); I < E; ++I) {
738 RegSequence.addUse(Regs[I]);
739 RegSequence.addImm(SubRegs[I]);
740 }
741 return RegSequence.getReg(0);
742}
743
744/// Create a tuple of D-registers using the registers in \p Regs.
746 static const unsigned RegClassIDs[] = {
747 AArch64::DDRegClassID, AArch64::DDDRegClassID, AArch64::DDDDRegClassID};
748 static const unsigned SubRegs[] = {AArch64::dsub0, AArch64::dsub1,
749 AArch64::dsub2, AArch64::dsub3};
750 return createTuple(Regs, RegClassIDs, SubRegs, MIB);
751}
752
753/// Create a tuple of Q-registers using the registers in \p Regs.
755 static const unsigned RegClassIDs[] = {
756 AArch64::QQRegClassID, AArch64::QQQRegClassID, AArch64::QQQQRegClassID};
757 static const unsigned SubRegs[] = {AArch64::qsub0, AArch64::qsub1,
758 AArch64::qsub2, AArch64::qsub3};
759 return createTuple(Regs, RegClassIDs, SubRegs, MIB);
760}
761
762static std::optional<uint64_t> getImmedFromMO(const MachineOperand &Root) {
763 auto &MI = *Root.getParent();
764 auto &MBB = *MI.getParent();
765 auto &MF = *MBB.getParent();
766 auto &MRI = MF.getRegInfo();
767 uint64_t Immed;
768 if (Root.isImm())
769 Immed = Root.getImm();
770 else if (Root.isCImm())
771 Immed = Root.getCImm()->getZExtValue();
772 else if (Root.isReg()) {
773 auto ValAndVReg =
775 if (!ValAndVReg)
776 return std::nullopt;
777 Immed = ValAndVReg->Value.getSExtValue();
778 } else
779 return std::nullopt;
780 return Immed;
781}
782
783/// Select the AArch64 opcode for the basic binary operation \p GenericOpc,
784/// appropriate for the register bank \p RegBankID and of size \p OpSize.
785/// \returns \p GenericOpc if the combination is unsupported.
786static unsigned selectBinaryOp(unsigned GenericOpc, unsigned RegBankID,
787 unsigned OpSize) {
788 if (RegBankID == AArch64::GPRRegBankID) {
789 if (OpSize == 32) {
790 switch (GenericOpc) {
791 case TargetOpcode::G_SHL:
792 return AArch64::LSLVWr;
793 case TargetOpcode::G_LSHR:
794 return AArch64::LSRVWr;
795 case TargetOpcode::G_ASHR:
796 return AArch64::ASRVWr;
797 default:
798 return GenericOpc;
799 }
800 } else if (OpSize == 64) {
801 switch (GenericOpc) {
802 case TargetOpcode::G_SHL:
803 return AArch64::LSLVXr;
804 case TargetOpcode::G_LSHR:
805 return AArch64::LSRVXr;
806 case TargetOpcode::G_ASHR:
807 return AArch64::ASRVXr;
808 default:
809 return GenericOpc;
810 }
811 }
812 }
813 return GenericOpc;
814}
815
816/// Select the AArch64 opcode for the G_LOAD or G_STORE operation \p GenericOpc,
817/// appropriate for the (value) register bank \p RegBankID and of memory access
818/// size \p OpSize. This returns the variant with the base+unsigned-immediate
819/// addressing mode (e.g., LDRXui).
820/// \returns \p GenericOpc if the combination is unsupported.
821static unsigned selectLoadStoreUIOp(unsigned GenericOpc, unsigned RegBankID,
822 unsigned OpSize) {
823 const bool isStore = GenericOpc == TargetOpcode::G_STORE;
824 switch (RegBankID) {
825 case AArch64::GPRRegBankID:
826 switch (OpSize) {
827 case 8:
828 return isStore ? AArch64::STRBBui : AArch64::LDRBBui;
829 case 16:
830 return isStore ? AArch64::STRHHui : AArch64::LDRHHui;
831 case 32:
832 return isStore ? AArch64::STRWui : AArch64::LDRWui;
833 case 64:
834 return isStore ? AArch64::STRXui : AArch64::LDRXui;
835 }
836 break;
837 case AArch64::FPRRegBankID:
838 switch (OpSize) {
839 case 8:
840 return isStore ? AArch64::STRBui : AArch64::LDRBui;
841 case 16:
842 return isStore ? AArch64::STRHui : AArch64::LDRHui;
843 case 32:
844 return isStore ? AArch64::STRSui : AArch64::LDRSui;
845 case 64:
846 return isStore ? AArch64::STRDui : AArch64::LDRDui;
847 case 128:
848 return isStore ? AArch64::STRQui : AArch64::LDRQui;
849 }
850 break;
851 }
852 return GenericOpc;
853}
854
855/// Helper function for selectCopy. Inserts a subregister copy from \p SrcReg
856/// to \p *To.
857///
858/// E.g "To = COPY SrcReg:SubReg"
860 const RegisterBankInfo &RBI, Register SrcReg,
861 const TargetRegisterClass *To, unsigned SubReg) {
862 assert(SrcReg.isValid() && "Expected a valid source register?");
863 assert(To && "Destination register class cannot be null");
864 assert(SubReg && "Expected a valid subregister");
865
866 MachineIRBuilder MIB(I);
867 auto SubRegCopy =
868 MIB.buildInstr(TargetOpcode::COPY, {To}, {}).addReg(SrcReg, {}, SubReg);
869 MachineOperand &RegOp = I.getOperand(1);
870 RegOp.setReg(SubRegCopy.getReg(0));
871
872 // It's possible that the destination register won't be constrained. Make
873 // sure that happens.
874 if (!I.getOperand(0).getReg().isPhysical())
875 RBI.constrainGenericRegister(I.getOperand(0).getReg(), *To, MRI);
876
877 return true;
878}
879
882 const RegisterBankInfo &RBI) {
883 Register DstReg = I.getOperand(0).getReg();
884 Register SrcReg = I.getOperand(1).getReg();
885 const RegisterBank &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
886 const RegisterBank &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
887
888 TypeSize DstRegSize = TRI.getRegSizeInBits(DstReg, MRI);
889 TypeSize SrcRegSize = TRI.getRegSizeInBits(SrcReg, MRI);
890
891 // Special casing for cross-bank copies of s1s. We can technically represent
892 // a 1-bit value with any size of register. The minimum size for a GPR is 32
893 // bits. So, we need to put the FPR on 32 bits as well.
894 //
895 // FIXME: I'm not sure if this case holds true outside of copies. If it does,
896 // then we can pull it into the helpers that get the appropriate class for a
897 // register bank. Or make a new helper that carries along some constraint
898 // information.
899 if (SrcRegBank != DstRegBank && (DstRegSize == TypeSize::getFixed(1) &&
900 SrcRegSize == TypeSize::getFixed(1)))
901 SrcRegSize = DstRegSize = TypeSize::getFixed(32);
902
903 // Find the correct register classes for the source and destination registers.
904 const TargetRegisterClass *SrcRC =
905 getMinClassForRegBank(SrcRegBank, SrcRegSize, true);
906 const TargetRegisterClass *DstRC =
907 getMinClassForRegBank(DstRegBank, DstRegSize, true);
908
909 if (!DstRC) {
910 LLVM_DEBUG(dbgs() << "Unexpected dest size "
911 << TRI.getRegSizeInBits(DstReg, MRI) << '\n');
912 return false;
913 }
914
915 if (I.getOpcode() == TargetOpcode::G_BITCAST &&
916 TRI.getRegSizeInBits(DstReg, MRI) == TypeSize::getFixed(16)) {
917 if (DstRegBank.getID() == AArch64::FPRRegBankID &&
918 SrcRegBank.getID() == AArch64::GPRRegBankID) {
919 if (!SrcReg.isPhysical() &&
920 !RBI.constrainGenericRegister(SrcReg, AArch64::GPR32RegClass, MRI))
921 return false;
922 if (!DstReg.isPhysical() &&
923 !RBI.constrainGenericRegister(DstReg, AArch64::FPR16RegClass, MRI))
924 return false;
925
926 Register FPR32 = MRI.createVirtualRegister(&AArch64::FPR32RegClass);
927 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AArch64::FMOVWSr))
928 .addDef(FPR32)
929 .addUse(SrcReg);
930 I.setDesc(TII.get(TargetOpcode::COPY));
931 I.getOperand(1).setReg(FPR32);
932 I.getOperand(1).setSubReg(AArch64::hsub);
933 return true;
934 }
935
936 if (DstRegBank.getID() == AArch64::GPRRegBankID &&
937 SrcRegBank.getID() == AArch64::FPRRegBankID) {
938 if (!SrcReg.isPhysical() &&
939 !RBI.constrainGenericRegister(SrcReg, AArch64::FPR16RegClass, MRI))
940 return false;
941 if (!DstReg.isPhysical() &&
942 !RBI.constrainGenericRegister(DstReg, AArch64::GPR32RegClass, MRI))
943 return false;
944
945 Register FPR32 = MRI.createVirtualRegister(&AArch64::FPR32RegClass);
946 BuildMI(*I.getParent(), I, I.getDebugLoc(),
947 TII.get(TargetOpcode::SUBREG_TO_REG))
948 .addDef(FPR32)
949 .addUse(SrcReg)
950 .addImm(AArch64::hsub);
951 I.setDesc(TII.get(AArch64::FMOVSWr));
952 I.getOperand(1).setReg(FPR32);
953 return true;
954 }
955 }
956
957 // Is this a copy? If so, then we may need to insert a subregister copy.
958 if (I.isCopy()) {
959 // Yes. Check if there's anything to fix up.
960 if (!SrcRC) {
961 LLVM_DEBUG(dbgs() << "Couldn't determine source register class\n");
962 return false;
963 }
964
965 const TypeSize SrcSize = TRI.getRegSizeInBits(*SrcRC);
966 const TypeSize DstSize = TRI.getRegSizeInBits(*DstRC);
967 unsigned SrcSubReg = I.getOperand(1).getSubReg();
968 unsigned SubReg;
969
970 if (SrcSubReg)
971 return RBI.constrainGenericRegister(DstReg, *DstRC, MRI);
972
973 // If the source bank doesn't support a subregister copy small enough,
974 // then we first need to copy to the destination bank.
975 if (getMinSizeForRegBank(SrcRegBank) > DstSize) {
976 const TargetRegisterClass *DstTempRC =
977 getMinClassForRegBank(DstRegBank, SrcSize, /* GetAllRegSet */ true);
978 getSubRegForClass(DstRC, TRI, SubReg);
979
980 MachineIRBuilder MIB(I);
981 auto Copy = MIB.buildCopy({DstTempRC}, {SrcReg});
982 copySubReg(I, MRI, RBI, Copy.getReg(0), DstRC, SubReg);
983 } else if (SrcSize > DstSize) {
984 // If the source register is bigger than the destination we need to
985 // perform a subregister copy.
986 const TargetRegisterClass *SubRegRC =
987 getMinClassForRegBank(SrcRegBank, DstSize, /* GetAllRegSet */ true);
988 getSubRegForClass(SubRegRC, TRI, SubReg);
989 copySubReg(I, MRI, RBI, SrcReg, DstRC, SubReg);
990 } else if (DstSize > SrcSize) {
991 // If the destination register is bigger than the source we need to do
992 // a promotion using SUBREG_TO_REG.
993 const TargetRegisterClass *PromotionRC =
994 getMinClassForRegBank(SrcRegBank, DstSize, /* GetAllRegSet */ true);
995 getSubRegForClass(SrcRC, TRI, SubReg);
996
997 Register PromoteReg = MRI.createVirtualRegister(PromotionRC);
998 BuildMI(*I.getParent(), I, I.getDebugLoc(),
999 TII.get(AArch64::SUBREG_TO_REG), PromoteReg)
1000 .addUse(SrcReg)
1001 .addImm(SubReg);
1002 MachineOperand &RegOp = I.getOperand(1);
1003 RegOp.setReg(PromoteReg);
1004 }
1005
1006 // If the destination is a physical register, then there's nothing to
1007 // change, so we're done.
1008 if (DstReg.isPhysical())
1009 return true;
1010 }
1011
1012 // No need to constrain SrcReg. It will get constrained when we hit another
1013 // of its use or its defs. Copies do not have constraints.
1014 if (!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
1015 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
1016 << " operand\n");
1017 return false;
1018 }
1019
1020 // If this a GPR ZEXT that we want to just reduce down into a copy.
1021 // The sizes will be mismatched with the source < 32b but that's ok.
1022 if (I.getOpcode() == TargetOpcode::G_ZEXT) {
1023 I.setDesc(TII.get(AArch64::COPY));
1024 assert(SrcRegBank.getID() == AArch64::GPRRegBankID);
1025 return selectCopy(I, TII, MRI, TRI, RBI);
1026 }
1027
1028 I.setDesc(TII.get(AArch64::COPY));
1029 return true;
1030}
1031
1033AArch64InstructionSelector::emitSelect(Register Dst, Register True,
1035 MachineIRBuilder &MIB) const {
1036 MachineRegisterInfo &MRI = *MIB.getMRI();
1037 assert(RBI.getRegBank(False, MRI, TRI)->getID() ==
1038 RBI.getRegBank(True, MRI, TRI)->getID() &&
1039 "Expected both select operands to have the same regbank?");
1040 LLT Ty = MRI.getType(True);
1041 if (Ty.isVector())
1042 return nullptr;
1043 const unsigned Size = Ty.getSizeInBits();
1044 assert((Size == 32 || Size == 64) &&
1045 "Expected 32 bit or 64 bit select only?");
1046 const bool Is32Bit = Size == 32;
1047 if (RBI.getRegBank(True, MRI, TRI)->getID() != AArch64::GPRRegBankID) {
1048 unsigned Opc = Is32Bit ? AArch64::FCSELSrrr : AArch64::FCSELDrrr;
1049 auto FCSel = MIB.buildInstr(Opc, {Dst}, {True, False}).addImm(CC);
1051 return &*FCSel;
1052 }
1053
1054 // By default, we'll try and emit a CSEL.
1055 unsigned Opc = Is32Bit ? AArch64::CSELWr : AArch64::CSELXr;
1056 bool Optimized = false;
1057 auto TryFoldBinOpIntoSelect = [&Opc, Is32Bit, &CC, &MRI,
1058 &Optimized](Register &Reg, Register &OtherReg,
1059 bool Invert) {
1060 if (Optimized)
1061 return false;
1062
1063 // Attempt to fold:
1064 //
1065 // %sub = G_SUB 0, %x
1066 // %select = G_SELECT cc, %reg, %sub
1067 //
1068 // Into:
1069 // %select = CSNEG %reg, %x, cc
1070 Register MatchReg;
1071 if (mi_match(Reg, MRI, m_Neg(m_Reg(MatchReg)))) {
1072 Opc = Is32Bit ? AArch64::CSNEGWr : AArch64::CSNEGXr;
1073 Reg = MatchReg;
1074 if (Invert) {
1076 std::swap(Reg, OtherReg);
1077 }
1078 return true;
1079 }
1080
1081 // Attempt to fold:
1082 //
1083 // %xor = G_XOR %x, -1
1084 // %select = G_SELECT cc, %reg, %xor
1085 //
1086 // Into:
1087 // %select = CSINV %reg, %x, cc
1088 if (mi_match(Reg, MRI, m_Not(m_Reg(MatchReg)))) {
1089 Opc = Is32Bit ? AArch64::CSINVWr : AArch64::CSINVXr;
1090 Reg = MatchReg;
1091 if (Invert) {
1093 std::swap(Reg, OtherReg);
1094 }
1095 return true;
1096 }
1097
1098 // Attempt to fold:
1099 //
1100 // %add = G_ADD %x, 1
1101 // %select = G_SELECT cc, %reg, %add
1102 //
1103 // Into:
1104 // %select = CSINC %reg, %x, cc
1105 if (mi_match(Reg, MRI,
1106 m_any_of(m_GAdd(m_Reg(MatchReg), m_SpecificICst(1)),
1107 m_GPtrAdd(m_Reg(MatchReg), m_SpecificICst(1))))) {
1108 Opc = Is32Bit ? AArch64::CSINCWr : AArch64::CSINCXr;
1109 Reg = MatchReg;
1110 if (Invert) {
1112 std::swap(Reg, OtherReg);
1113 }
1114 return true;
1115 }
1116
1117 return false;
1118 };
1119
1120 // Helper lambda which tries to use CSINC/CSINV for the instruction when its
1121 // true/false values are constants.
1122 // FIXME: All of these patterns already exist in tablegen. We should be
1123 // able to import these.
1124 auto TryOptSelectCst = [&Opc, &True, &False, &CC, Is32Bit, &MRI,
1125 &Optimized]() {
1126 if (Optimized)
1127 return false;
1130 if (!TrueCst && !FalseCst)
1131 return false;
1132
1133 Register ZReg = Is32Bit ? AArch64::WZR : AArch64::XZR;
1134 if (TrueCst && FalseCst) {
1135 int64_t T = TrueCst->Value.getSExtValue();
1136 int64_t F = FalseCst->Value.getSExtValue();
1137
1138 if (T == 0 && F == 1) {
1139 // G_SELECT cc, 0, 1 -> CSINC zreg, zreg, cc
1140 Opc = Is32Bit ? AArch64::CSINCWr : AArch64::CSINCXr;
1141 True = ZReg;
1142 False = ZReg;
1143 return true;
1144 }
1145
1146 if (T == 0 && F == -1) {
1147 // G_SELECT cc 0, -1 -> CSINV zreg, zreg cc
1148 Opc = Is32Bit ? AArch64::CSINVWr : AArch64::CSINVXr;
1149 True = ZReg;
1150 False = ZReg;
1151 return true;
1152 }
1153 }
1154
1155 if (TrueCst) {
1156 int64_t T = TrueCst->Value.getSExtValue();
1157 if (T == 1) {
1158 // G_SELECT cc, 1, f -> CSINC f, zreg, inv_cc
1159 Opc = Is32Bit ? AArch64::CSINCWr : AArch64::CSINCXr;
1160 True = False;
1161 False = ZReg;
1163 return true;
1164 }
1165
1166 if (T == -1) {
1167 // G_SELECT cc, -1, f -> CSINV f, zreg, inv_cc
1168 Opc = Is32Bit ? AArch64::CSINVWr : AArch64::CSINVXr;
1169 True = False;
1170 False = ZReg;
1172 return true;
1173 }
1174 }
1175
1176 if (FalseCst) {
1177 int64_t F = FalseCst->Value.getSExtValue();
1178 if (F == 1) {
1179 // G_SELECT cc, t, 1 -> CSINC t, zreg, cc
1180 Opc = Is32Bit ? AArch64::CSINCWr : AArch64::CSINCXr;
1181 False = ZReg;
1182 return true;
1183 }
1184
1185 if (F == -1) {
1186 // G_SELECT cc, t, -1 -> CSINC t, zreg, cc
1187 Opc = Is32Bit ? AArch64::CSINVWr : AArch64::CSINVXr;
1188 False = ZReg;
1189 return true;
1190 }
1191 }
1192 return false;
1193 };
1194
1195 Optimized |= TryFoldBinOpIntoSelect(False, True, /*Invert = */ false);
1196 Optimized |= TryFoldBinOpIntoSelect(True, False, /*Invert = */ true);
1197 Optimized |= TryOptSelectCst();
1198 auto SelectInst = MIB.buildInstr(Opc, {Dst}, {True, False}).addImm(CC);
1199 constrainSelectedInstRegOperands(*SelectInst, TII, TRI, RBI);
1200 return &*SelectInst;
1201}
1202
1205 MachineRegisterInfo *MRI = nullptr) {
1206 switch (P) {
1207 default:
1208 llvm_unreachable("Unknown condition code!");
1209 case CmpInst::ICMP_NE:
1210 return AArch64CC::NE;
1211 case CmpInst::ICMP_EQ:
1212 return AArch64CC::EQ;
1213 case CmpInst::ICMP_SGT:
1214 return AArch64CC::GT;
1215 case CmpInst::ICMP_SGE:
1216 if (RHS && MRI) {
1217 auto ValAndVReg = getIConstantVRegValWithLookThrough(RHS, *MRI);
1218 if (ValAndVReg && ValAndVReg->Value == 0)
1219 return AArch64CC::PL;
1220 }
1221 return AArch64CC::GE;
1222 case CmpInst::ICMP_SLT:
1223 if (RHS && MRI) {
1224 auto ValAndVReg = getIConstantVRegValWithLookThrough(RHS, *MRI);
1225 if (ValAndVReg && ValAndVReg->Value == 0)
1226 return AArch64CC::MI;
1227 }
1228 return AArch64CC::LT;
1229 case CmpInst::ICMP_SLE:
1230 return AArch64CC::LE;
1231 case CmpInst::ICMP_UGT:
1232 return AArch64CC::HI;
1233 case CmpInst::ICMP_UGE:
1234 return AArch64CC::HS;
1235 case CmpInst::ICMP_ULT:
1236 return AArch64CC::LO;
1237 case CmpInst::ICMP_ULE:
1238 return AArch64CC::LS;
1239 }
1240}
1241
1242/// changeFPCCToORAArch64CC - Convert an IR fp condition code to an AArch64 CC.
1244 AArch64CC::CondCode &CondCode,
1245 AArch64CC::CondCode &CondCode2) {
1246 CondCode2 = AArch64CC::AL;
1247 switch (CC) {
1248 default:
1249 llvm_unreachable("Unknown FP condition!");
1250 case CmpInst::FCMP_OEQ:
1251 CondCode = AArch64CC::EQ;
1252 break;
1253 case CmpInst::FCMP_OGT:
1254 CondCode = AArch64CC::GT;
1255 break;
1256 case CmpInst::FCMP_OGE:
1257 CondCode = AArch64CC::GE;
1258 break;
1259 case CmpInst::FCMP_OLT:
1260 CondCode = AArch64CC::MI;
1261 break;
1262 case CmpInst::FCMP_OLE:
1263 CondCode = AArch64CC::LS;
1264 break;
1265 case CmpInst::FCMP_ONE:
1266 CondCode = AArch64CC::MI;
1267 CondCode2 = AArch64CC::GT;
1268 break;
1269 case CmpInst::FCMP_ORD:
1270 CondCode = AArch64CC::VC;
1271 break;
1272 case CmpInst::FCMP_UNO:
1273 CondCode = AArch64CC::VS;
1274 break;
1275 case CmpInst::FCMP_UEQ:
1276 CondCode = AArch64CC::EQ;
1277 CondCode2 = AArch64CC::VS;
1278 break;
1279 case CmpInst::FCMP_UGT:
1280 CondCode = AArch64CC::HI;
1281 break;
1282 case CmpInst::FCMP_UGE:
1283 CondCode = AArch64CC::PL;
1284 break;
1285 case CmpInst::FCMP_ULT:
1286 CondCode = AArch64CC::LT;
1287 break;
1288 case CmpInst::FCMP_ULE:
1289 CondCode = AArch64CC::LE;
1290 break;
1291 case CmpInst::FCMP_UNE:
1292 CondCode = AArch64CC::NE;
1293 break;
1294 }
1295}
1296
1297/// Convert an IR fp condition code to an AArch64 CC.
1298/// This differs from changeFPCCToAArch64CC in that it returns cond codes that
1299/// should be AND'ed instead of OR'ed.
1301 AArch64CC::CondCode &CondCode,
1302 AArch64CC::CondCode &CondCode2) {
1303 CondCode2 = AArch64CC::AL;
1304 switch (CC) {
1305 default:
1306 changeFPCCToORAArch64CC(CC, CondCode, CondCode2);
1307 assert(CondCode2 == AArch64CC::AL);
1308 break;
1309 case CmpInst::FCMP_ONE:
1310 // (a one b)
1311 // == ((a olt b) || (a ogt b))
1312 // == ((a ord b) && (a une b))
1313 CondCode = AArch64CC::VC;
1314 CondCode2 = AArch64CC::NE;
1315 break;
1316 case CmpInst::FCMP_UEQ:
1317 // (a ueq b)
1318 // == ((a uno b) || (a oeq b))
1319 // == ((a ule b) && (a uge b))
1320 CondCode = AArch64CC::PL;
1321 CondCode2 = AArch64CC::LE;
1322 break;
1323 }
1324}
1325
1326/// Return a register which can be used as a bit to test in a TB(N)Z.
1327static Register getTestBitReg(Register Reg, uint64_t &Bit, bool &Invert,
1329 assert(Reg.isValid() && "Expected valid register!");
1330 bool HasZext = false;
1332 unsigned Opc = MI->getOpcode();
1333
1334 if (!MI->getOperand(0).isReg() ||
1335 !MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()))
1336 break;
1337
1338 // (tbz (any_ext x), b) -> (tbz x, b) and
1339 // (tbz (zext x), b) -> (tbz x, b) if we don't use the extended bits.
1340 //
1341 // (tbz (trunc x), b) -> (tbz x, b) is always safe, because the bit number
1342 // on the truncated x is the same as the bit number on x.
1343 if (Opc == TargetOpcode::G_ANYEXT || Opc == TargetOpcode::G_ZEXT ||
1344 Opc == TargetOpcode::G_TRUNC) {
1345 if (Opc == TargetOpcode::G_ZEXT)
1346 HasZext = true;
1347
1348 Register NextReg = MI->getOperand(1).getReg();
1349 // Did we find something worth folding?
1350 if (!NextReg.isValid() || !MRI.hasOneNonDBGUse(NextReg))
1351 break;
1352 TypeSize InSize = MRI.getType(NextReg).getSizeInBits();
1353 if (Bit >= InSize)
1354 break;
1355
1356 // NextReg is worth folding. Keep looking.
1357 Reg = NextReg;
1358 continue;
1359 }
1360
1361 // Attempt to find a suitable operation with a constant on one side.
1362 std::optional<uint64_t> C;
1363 Register TestReg;
1364 switch (Opc) {
1365 default:
1366 break;
1367 case TargetOpcode::G_AND:
1368 case TargetOpcode::G_XOR: {
1369 TestReg = MI->getOperand(1).getReg();
1370 Register ConstantReg = MI->getOperand(2).getReg();
1371 auto VRegAndVal = getIConstantVRegValWithLookThrough(ConstantReg, MRI);
1372 if (!VRegAndVal) {
1373 // AND commutes, check the other side for a constant.
1374 // FIXME: Can we canonicalize the constant so that it's always on the
1375 // same side at some point earlier?
1376 std::swap(ConstantReg, TestReg);
1377 VRegAndVal = getIConstantVRegValWithLookThrough(ConstantReg, MRI);
1378 }
1379 if (VRegAndVal) {
1380 if (HasZext)
1381 C = VRegAndVal->Value.getZExtValue();
1382 else
1383 C = VRegAndVal->Value.getSExtValue();
1384 }
1385 break;
1386 }
1387 case TargetOpcode::G_ASHR:
1388 case TargetOpcode::G_LSHR:
1389 case TargetOpcode::G_SHL: {
1390 TestReg = MI->getOperand(1).getReg();
1391 auto VRegAndVal =
1392 getIConstantVRegValWithLookThrough(MI->getOperand(2).getReg(), MRI);
1393 if (VRegAndVal)
1394 C = VRegAndVal->Value.getSExtValue();
1395 break;
1396 }
1397 }
1398
1399 // Didn't find a constant or viable register. Bail out of the loop.
1400 if (!C || !TestReg.isValid())
1401 break;
1402
1403 // We found a suitable instruction with a constant. Check to see if we can
1404 // walk through the instruction.
1405 Register NextReg;
1406 unsigned TestRegSize = MRI.getType(TestReg).getSizeInBits();
1407 switch (Opc) {
1408 default:
1409 break;
1410 case TargetOpcode::G_AND:
1411 // (tbz (and x, m), b) -> (tbz x, b) when the b-th bit of m is set.
1412 if ((*C >> Bit) & 1)
1413 NextReg = TestReg;
1414 break;
1415 case TargetOpcode::G_SHL:
1416 // (tbz (shl x, c), b) -> (tbz x, b-c) when b-c is positive and fits in
1417 // the type of the register.
1418 if (*C <= Bit && (Bit - *C) < TestRegSize) {
1419 NextReg = TestReg;
1420 Bit = Bit - *C;
1421 }
1422 break;
1423 case TargetOpcode::G_ASHR:
1424 // (tbz (ashr x, c), b) -> (tbz x, b+c) or (tbz x, msb) if b+c is > # bits
1425 // in x
1426 NextReg = TestReg;
1427 Bit = Bit + *C;
1428 if (Bit >= TestRegSize)
1429 Bit = TestRegSize - 1;
1430 break;
1431 case TargetOpcode::G_LSHR:
1432 // (tbz (lshr x, c), b) -> (tbz x, b+c) when b + c is < # bits in x
1433 if ((Bit + *C) < TestRegSize) {
1434 NextReg = TestReg;
1435 Bit = Bit + *C;
1436 }
1437 break;
1438 case TargetOpcode::G_XOR:
1439 // We can walk through a G_XOR by inverting whether we use tbz/tbnz when
1440 // appropriate.
1441 //
1442 // e.g. If x' = xor x, c, and the b-th bit is set in c then
1443 //
1444 // tbz x', b -> tbnz x, b
1445 //
1446 // Because x' only has the b-th bit set if x does not.
1447 if ((*C >> Bit) & 1)
1448 Invert = !Invert;
1449 NextReg = TestReg;
1450 break;
1451 }
1452
1453 // Check if we found anything worth folding.
1454 if (!NextReg.isValid())
1455 return Reg;
1456 Reg = NextReg;
1457 }
1458
1459 return Reg;
1460}
1461
1462MachineInstr *AArch64InstructionSelector::emitTestBit(
1463 Register TestReg, uint64_t Bit, bool IsNegative, MachineBasicBlock *DstMBB,
1464 MachineIRBuilder &MIB) const {
1465 assert(TestReg.isValid());
1466 assert(ProduceNonFlagSettingCondBr &&
1467 "Cannot emit TB(N)Z with speculation tracking!");
1468 MachineRegisterInfo &MRI = *MIB.getMRI();
1469
1470 // Attempt to optimize the test bit by walking over instructions.
1471 TestReg = getTestBitReg(TestReg, Bit, IsNegative, MRI);
1472 LLT Ty = MRI.getType(TestReg);
1473 unsigned Size = Ty.getSizeInBits();
1474 assert(!Ty.isVector() && "Expected a scalar!");
1475 assert(Bit < 64 && "Bit is too large!");
1476
1477 // When the test register is a 64-bit register, we have to narrow to make
1478 // TBNZW work.
1479 bool UseWReg = Bit < 32;
1480 unsigned NecessarySize = UseWReg ? 32 : 64;
1481 if (Size != NecessarySize)
1482 TestReg = moveScalarRegClass(
1483 TestReg, UseWReg ? AArch64::GPR32RegClass : AArch64::GPR64RegClass,
1484 MIB);
1485
1486 static const unsigned OpcTable[2][2] = {{AArch64::TBZX, AArch64::TBNZX},
1487 {AArch64::TBZW, AArch64::TBNZW}};
1488 unsigned Opc = OpcTable[UseWReg][IsNegative];
1489 auto TestBitMI =
1490 MIB.buildInstr(Opc).addReg(TestReg).addImm(Bit).addMBB(DstMBB);
1491 constrainSelectedInstRegOperands(*TestBitMI, TII, TRI, RBI);
1492 return &*TestBitMI;
1493}
1494
1495bool AArch64InstructionSelector::tryOptAndIntoCompareBranch(
1496 MachineInstr &AndInst, bool Invert, MachineBasicBlock *DstMBB,
1497 MachineIRBuilder &MIB) const {
1498 assert(AndInst.getOpcode() == TargetOpcode::G_AND && "Expected G_AND only?");
1499 // Given something like this:
1500 //
1501 // %x = ...Something...
1502 // %one = G_CONSTANT i64 1
1503 // %zero = G_CONSTANT i64 0
1504 // %and = G_AND %x, %one
1505 // %cmp = G_ICMP intpred(ne), %and, %zero
1506 // %cmp_trunc = G_TRUNC %cmp
1507 // G_BRCOND %cmp_trunc, %bb.3
1508 //
1509 // We want to try and fold the AND into the G_BRCOND and produce either a
1510 // TBNZ (when we have intpred(ne)) or a TBZ (when we have intpred(eq)).
1511 //
1512 // In this case, we'd get
1513 //
1514 // TBNZ %x %bb.3
1515 //
1516
1517 // Check if the AND has a constant on its RHS which we can use as a mask.
1518 // If it's a power of 2, then it's the same as checking a specific bit.
1519 // (e.g, ANDing with 8 == ANDing with 000...100 == testing if bit 3 is set)
1520 auto MaybeBit = getIConstantVRegValWithLookThrough(
1521 AndInst.getOperand(2).getReg(), *MIB.getMRI());
1522 if (!MaybeBit)
1523 return false;
1524
1525 int32_t Bit = MaybeBit->Value.exactLogBase2();
1526 if (Bit < 0)
1527 return false;
1528
1529 Register TestReg = AndInst.getOperand(1).getReg();
1530
1531 // Emit a TB(N)Z.
1532 emitTestBit(TestReg, Bit, Invert, DstMBB, MIB);
1533 return true;
1534}
1535
1536MachineInstr *AArch64InstructionSelector::emitCBZ(Register CompareReg,
1537 bool IsNegative,
1538 MachineBasicBlock *DestMBB,
1539 MachineIRBuilder &MIB) const {
1540 assert(ProduceNonFlagSettingCondBr && "CBZ does not set flags!");
1541 MachineRegisterInfo &MRI = *MIB.getMRI();
1542 assert(RBI.getRegBank(CompareReg, MRI, TRI)->getID() ==
1543 AArch64::GPRRegBankID &&
1544 "Expected GPRs only?");
1545 auto Ty = MRI.getType(CompareReg);
1546 unsigned Width = Ty.getSizeInBits();
1547 assert(!Ty.isVector() && "Expected scalar only?");
1548 assert(Width <= 64 && "Expected width to be at most 64?");
1549 static const unsigned OpcTable[2][2] = {{AArch64::CBZW, AArch64::CBZX},
1550 {AArch64::CBNZW, AArch64::CBNZX}};
1551 unsigned Opc = OpcTable[IsNegative][Width == 64];
1552 auto BranchMI = MIB.buildInstr(Opc, {}, {CompareReg}).addMBB(DestMBB);
1553 constrainSelectedInstRegOperands(*BranchMI, TII, TRI, RBI);
1554 return &*BranchMI;
1555}
1556
1557bool AArch64InstructionSelector::selectCompareBranchFedByFCmp(
1558 MachineInstr &I, MachineInstr &FCmp, MachineIRBuilder &MIB) const {
1559 assert(FCmp.getOpcode() == TargetOpcode::G_FCMP);
1560 assert(I.getOpcode() == TargetOpcode::G_BRCOND);
1561 // Unfortunately, the mapping of LLVM FP CC's onto AArch64 CC's isn't
1562 // totally clean. Some of them require two branches to implement.
1564 emitFPCompare(FCmp.getOperand(2).getReg(), FCmp.getOperand(3).getReg(), MIB,
1565 Pred);
1566 AArch64CC::CondCode CC1, CC2;
1568 MachineBasicBlock *DestMBB = I.getOperand(1).getMBB();
1569 MIB.buildInstr(AArch64::Bcc, {}, {}).addImm(CC1).addMBB(DestMBB);
1570 if (CC2 != AArch64CC::AL)
1571 MIB.buildInstr(AArch64::Bcc, {}, {}).addImm(CC2).addMBB(DestMBB);
1572 I.eraseFromParent();
1573 return true;
1574}
1575
1576bool AArch64InstructionSelector::tryOptCompareBranchFedByICmp(
1577 MachineInstr &I, MachineInstr &ICmp, MachineIRBuilder &MIB) const {
1578 assert(ICmp.getOpcode() == TargetOpcode::G_ICMP);
1579 assert(I.getOpcode() == TargetOpcode::G_BRCOND);
1580 // Attempt to optimize the G_BRCOND + G_ICMP into a TB(N)Z/CB(N)Z.
1581 //
1582 // Speculation tracking/SLH assumes that optimized TB(N)Z/CB(N)Z
1583 // instructions will not be produced, as they are conditional branch
1584 // instructions that do not set flags.
1585 if (!ProduceNonFlagSettingCondBr)
1586 return false;
1587
1588 MachineRegisterInfo &MRI = *MIB.getMRI();
1589 MachineBasicBlock *DestMBB = I.getOperand(1).getMBB();
1590 auto Pred =
1591 static_cast<CmpInst::Predicate>(ICmp.getOperand(1).getPredicate());
1592 Register LHS = ICmp.getOperand(2).getReg();
1593 Register RHS = ICmp.getOperand(3).getReg();
1594
1595 // We're allowed to emit a TB(N)Z/CB(N)Z. Try to do that.
1596 auto VRegAndVal = getIConstantVRegValWithLookThrough(RHS, MRI);
1597 MachineInstr *AndInst = getOpcodeDef(TargetOpcode::G_AND, LHS, MRI);
1598
1599 // When we can emit a TB(N)Z, prefer that.
1600 //
1601 // Handle non-commutative condition codes first.
1602 // Note that we don't want to do this when we have a G_AND because it can
1603 // become a tst. The tst will make the test bit in the TB(N)Z redundant.
1604 if (VRegAndVal && !AndInst) {
1605 int64_t C = VRegAndVal->Value.getSExtValue();
1606
1607 // When we have a greater-than comparison, we can just test if the msb is
1608 // zero.
1609 if (C == -1 && Pred == CmpInst::ICMP_SGT) {
1611 emitTestBit(LHS, Bit, /*IsNegative = */ false, DestMBB, MIB);
1612 I.eraseFromParent();
1613 return true;
1614 }
1615
1616 // When we have a less than comparison, we can just test if the msb is not
1617 // zero.
1618 if (C == 0 && Pred == CmpInst::ICMP_SLT) {
1620 emitTestBit(LHS, Bit, /*IsNegative = */ true, DestMBB, MIB);
1621 I.eraseFromParent();
1622 return true;
1623 }
1624
1625 // Inversely, if we have a signed greater-than-or-equal comparison to zero,
1626 // we can test if the msb is zero.
1627 if (C == 0 && Pred == CmpInst::ICMP_SGE) {
1629 emitTestBit(LHS, Bit, /*IsNegative = */ false, DestMBB, MIB);
1630 I.eraseFromParent();
1631 return true;
1632 }
1633 }
1634
1635 // Attempt to handle commutative condition codes. Right now, that's only
1636 // eq/ne.
1638 if (!VRegAndVal) {
1639 std::swap(RHS, LHS);
1641 AndInst = getOpcodeDef(TargetOpcode::G_AND, LHS, MRI);
1642 }
1643
1644 if (VRegAndVal && VRegAndVal->Value == 0) {
1645 // If there's a G_AND feeding into this branch, try to fold it away by
1646 // emitting a TB(N)Z instead.
1647 //
1648 // Note: If we have LT, then it *is* possible to fold, but it wouldn't be
1649 // beneficial. When we have an AND and LT, we need a TST/ANDS, so folding
1650 // would be redundant.
1651 if (AndInst &&
1652 tryOptAndIntoCompareBranch(
1653 *AndInst, /*Invert = */ Pred == CmpInst::ICMP_NE, DestMBB, MIB)) {
1654 I.eraseFromParent();
1655 return true;
1656 }
1657
1658 // Otherwise, try to emit a CB(N)Z instead.
1659 auto LHSTy = MRI.getType(LHS);
1660 if (!LHSTy.isVector() && LHSTy.getSizeInBits() <= 64) {
1661 emitCBZ(LHS, /*IsNegative = */ Pred == CmpInst::ICMP_NE, DestMBB, MIB);
1662 I.eraseFromParent();
1663 return true;
1664 }
1665 }
1666 }
1667
1668 return false;
1669}
1670
1671bool AArch64InstructionSelector::selectCompareBranchFedByICmp(
1672 MachineInstr &I, MachineInstr &ICmp, MachineIRBuilder &MIB) const {
1673 assert(ICmp.getOpcode() == TargetOpcode::G_ICMP);
1674 assert(I.getOpcode() == TargetOpcode::G_BRCOND);
1675 if (tryOptCompareBranchFedByICmp(I, ICmp, MIB))
1676 return true;
1677
1678 // Couldn't optimize. Emit a compare + a Bcc.
1679 MachineBasicBlock *DestMBB = I.getOperand(1).getMBB();
1680 auto &PredOp = ICmp.getOperand(1);
1681 emitIntegerCompare(ICmp.getOperand(2), ICmp.getOperand(3), PredOp, MIB);
1683 static_cast<CmpInst::Predicate>(PredOp.getPredicate()),
1684 ICmp.getOperand(3).getReg(), MIB.getMRI());
1685 MIB.buildInstr(AArch64::Bcc, {}, {}).addImm(CC).addMBB(DestMBB);
1686 I.eraseFromParent();
1687 return true;
1688}
1689
1690bool AArch64InstructionSelector::selectCompareBranch(
1691 MachineInstr &I, MachineFunction &MF, MachineRegisterInfo &MRI) {
1692 Register CondReg = I.getOperand(0).getReg();
1693 MachineInstr *CCMI = MRI.getVRegDef(CondReg);
1694 // Try to select the G_BRCOND using whatever is feeding the condition if
1695 // possible.
1696 unsigned CCMIOpc = CCMI->getOpcode();
1697 if (CCMIOpc == TargetOpcode::G_FCMP)
1698 return selectCompareBranchFedByFCmp(I, *CCMI, MIB);
1699 if (CCMIOpc == TargetOpcode::G_ICMP)
1700 return selectCompareBranchFedByICmp(I, *CCMI, MIB);
1701
1702 // Speculation tracking/SLH assumes that optimized TB(N)Z/CB(N)Z
1703 // instructions will not be produced, as they are conditional branch
1704 // instructions that do not set flags.
1705 if (ProduceNonFlagSettingCondBr) {
1706 emitTestBit(CondReg, /*Bit = */ 0, /*IsNegative = */ true,
1707 I.getOperand(1).getMBB(), MIB);
1708 I.eraseFromParent();
1709 return true;
1710 }
1711
1712 // Can't emit TB(N)Z/CB(N)Z. Emit a tst + bcc instead.
1713 auto TstMI =
1714 MIB.buildInstr(AArch64::ANDSWri, {LLT::scalar(32)}, {CondReg}).addImm(1);
1716 auto Bcc = MIB.buildInstr(AArch64::Bcc)
1718 .addMBB(I.getOperand(1).getMBB());
1719 I.eraseFromParent();
1721 return true;
1722}
1723
1724/// Returns the element immediate value of a vector shift operand if found.
1725/// This needs to detect a splat-like operation, e.g. a G_BUILD_VECTOR.
1726static std::optional<APInt> getVectorShiftImm(Register Reg,
1728 assert(MRI.getType(Reg).isVector() && "Expected a *vector* shift operand");
1729 MachineInstr *OpMI = MRI.getVRegDef(Reg);
1730 std::optional<Register> Splat = getVectorSplat(*OpMI, MRI);
1731 if (!Splat)
1732 return std::nullopt;
1733 return getIConstantVRegVal(*Splat, MRI);
1734}
1735
1736/// Matches and returns the shift immediate value for a SHL instruction given
1737/// a shift operand.
1738static std::optional<uint64_t> getVectorSHLImm(LLT SrcTy, Register Reg,
1740 std::optional<APInt> ShiftImm = getVectorShiftImm(Reg, MRI);
1741 if (!ShiftImm)
1742 return std::nullopt;
1743 // Check the immediate is in range for a SHL.
1744 uint64_t Imm = ShiftImm->getZExtValue();
1745 if (Imm >= SrcTy.getElementType().getSizeInBits())
1746 return std::nullopt;
1747 return Imm;
1748}
1749
1750bool AArch64InstructionSelector::selectVectorSHL(MachineInstr &I,
1751 MachineRegisterInfo &MRI) {
1752 assert(I.getOpcode() == TargetOpcode::G_SHL);
1753 Register DstReg = I.getOperand(0).getReg();
1754 const LLT Ty = MRI.getType(DstReg);
1755 Register Src1Reg = I.getOperand(1).getReg();
1756 Register Src2Reg = I.getOperand(2).getReg();
1757
1758 if (!Ty.isVector())
1759 return false;
1760
1761 // Check if we have a vector of constants on RHS that we can select as the
1762 // immediate form.
1763 std::optional<uint64_t> ImmVal = getVectorSHLImm(Ty, Src2Reg, MRI);
1764
1765 unsigned Opc = 0;
1766 if (Ty == LLT::fixed_vector(2, 64)) {
1767 Opc = ImmVal ? AArch64::SHLv2i64_shift : AArch64::USHLv2i64;
1768 } else if (Ty == LLT::fixed_vector(4, 32)) {
1769 Opc = ImmVal ? AArch64::SHLv4i32_shift : AArch64::USHLv4i32;
1770 } else if (Ty == LLT::fixed_vector(2, 32)) {
1771 Opc = ImmVal ? AArch64::SHLv2i32_shift : AArch64::USHLv2i32;
1772 } else if (Ty == LLT::fixed_vector(4, 16)) {
1773 Opc = ImmVal ? AArch64::SHLv4i16_shift : AArch64::USHLv4i16;
1774 } else if (Ty == LLT::fixed_vector(8, 16)) {
1775 Opc = ImmVal ? AArch64::SHLv8i16_shift : AArch64::USHLv8i16;
1776 } else if (Ty == LLT::fixed_vector(16, 8)) {
1777 Opc = ImmVal ? AArch64::SHLv16i8_shift : AArch64::USHLv16i8;
1778 } else if (Ty == LLT::fixed_vector(8, 8)) {
1779 Opc = ImmVal ? AArch64::SHLv8i8_shift : AArch64::USHLv8i8;
1780 } else {
1781 LLVM_DEBUG(dbgs() << "Unhandled G_SHL type");
1782 return false;
1783 }
1784
1785 auto Shl = MIB.buildInstr(Opc, {DstReg}, {Src1Reg});
1786 if (ImmVal)
1787 Shl.addImm(*ImmVal);
1788 else
1789 Shl.addUse(Src2Reg);
1791 I.eraseFromParent();
1792 return true;
1793}
1794
1795bool AArch64InstructionSelector::selectVectorAshrLshr(
1796 MachineInstr &I, MachineRegisterInfo &MRI) {
1797 assert(I.getOpcode() == TargetOpcode::G_ASHR ||
1798 I.getOpcode() == TargetOpcode::G_LSHR);
1799 Register DstReg = I.getOperand(0).getReg();
1800 const LLT Ty = MRI.getType(DstReg);
1801 Register Src1Reg = I.getOperand(1).getReg();
1802 Register Src2Reg = I.getOperand(2).getReg();
1803
1804 if (!Ty.isVector())
1805 return false;
1806
1807 bool IsASHR = I.getOpcode() == TargetOpcode::G_ASHR;
1808
1809 // We expect the immediate case to be lowered in the PostLegalCombiner to
1810 // AArch64ISD::VASHR or AArch64ISD::VLSHR equivalents.
1811
1812 // There is not a shift right register instruction, but the shift left
1813 // register instruction takes a signed value, where negative numbers specify a
1814 // right shift.
1815
1816 unsigned Opc = 0;
1817 unsigned NegOpc = 0;
1818 const TargetRegisterClass *RC =
1819 getRegClassForTypeOnBank(Ty, RBI.getRegBank(AArch64::FPRRegBankID));
1820 if (Ty == LLT::fixed_vector(2, 64)) {
1821 Opc = IsASHR ? AArch64::SSHLv2i64 : AArch64::USHLv2i64;
1822 NegOpc = AArch64::NEGv2i64;
1823 } else if (Ty == LLT::fixed_vector(4, 32)) {
1824 Opc = IsASHR ? AArch64::SSHLv4i32 : AArch64::USHLv4i32;
1825 NegOpc = AArch64::NEGv4i32;
1826 } else if (Ty == LLT::fixed_vector(2, 32)) {
1827 Opc = IsASHR ? AArch64::SSHLv2i32 : AArch64::USHLv2i32;
1828 NegOpc = AArch64::NEGv2i32;
1829 } else if (Ty == LLT::fixed_vector(4, 16)) {
1830 Opc = IsASHR ? AArch64::SSHLv4i16 : AArch64::USHLv4i16;
1831 NegOpc = AArch64::NEGv4i16;
1832 } else if (Ty == LLT::fixed_vector(8, 16)) {
1833 Opc = IsASHR ? AArch64::SSHLv8i16 : AArch64::USHLv8i16;
1834 NegOpc = AArch64::NEGv8i16;
1835 } else if (Ty == LLT::fixed_vector(16, 8)) {
1836 Opc = IsASHR ? AArch64::SSHLv16i8 : AArch64::USHLv16i8;
1837 NegOpc = AArch64::NEGv16i8;
1838 } else if (Ty == LLT::fixed_vector(8, 8)) {
1839 Opc = IsASHR ? AArch64::SSHLv8i8 : AArch64::USHLv8i8;
1840 NegOpc = AArch64::NEGv8i8;
1841 } else {
1842 LLVM_DEBUG(dbgs() << "Unhandled G_ASHR type");
1843 return false;
1844 }
1845
1846 auto Neg = MIB.buildInstr(NegOpc, {RC}, {Src2Reg});
1848 auto SShl = MIB.buildInstr(Opc, {DstReg}, {Src1Reg, Neg});
1850 I.eraseFromParent();
1851 return true;
1852}
1853
1854bool AArch64InstructionSelector::selectVaStartAAPCS(
1855 MachineInstr &I, MachineFunction &MF, MachineRegisterInfo &MRI) const {
1856
1858 MF.getFunction().isVarArg()))
1859 return false;
1860
1861 // The layout of the va_list struct is specified in the AArch64 Procedure Call
1862 // Standard, section 10.1.5.
1863
1864 const AArch64FunctionInfo *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
1865 const unsigned PtrSize = STI.isTargetILP32() ? 4 : 8;
1866 const auto *PtrRegClass =
1867 STI.isTargetILP32() ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass;
1868
1869 const MCInstrDesc &MCIDAddAddr =
1870 TII.get(STI.isTargetILP32() ? AArch64::ADDWri : AArch64::ADDXri);
1871 const MCInstrDesc &MCIDStoreAddr =
1872 TII.get(STI.isTargetILP32() ? AArch64::STRWui : AArch64::STRXui);
1873
1874 /*
1875 * typedef struct va_list {
1876 * void * stack; // next stack param
1877 * void * gr_top; // end of GP arg reg save area
1878 * void * vr_top; // end of FP/SIMD arg reg save area
1879 * int gr_offs; // offset from gr_top to next GP register arg
1880 * int vr_offs; // offset from vr_top to next FP/SIMD register arg
1881 * } va_list;
1882 */
1883 const auto VAList = I.getOperand(0).getReg();
1884
1885 // Our current offset in bytes from the va_list struct (VAList).
1886 unsigned OffsetBytes = 0;
1887
1888 // Helper function to store (FrameIndex + Imm) to VAList at offset OffsetBytes
1889 // and increment OffsetBytes by PtrSize.
1890 const auto PushAddress = [&](const int FrameIndex, const int64_t Imm) {
1891 const Register Top = MRI.createVirtualRegister(PtrRegClass);
1892 auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), MCIDAddAddr)
1893 .addDef(Top)
1894 .addFrameIndex(FrameIndex)
1895 .addImm(Imm)
1896 .addImm(0);
1898
1899 const auto *MMO = *I.memoperands_begin();
1900 MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), MCIDStoreAddr)
1901 .addUse(Top)
1902 .addUse(VAList)
1903 .addImm(OffsetBytes / PtrSize)
1905 MMO->getPointerInfo().getWithOffset(OffsetBytes),
1906 MachineMemOperand::MOStore, PtrSize, MMO->getBaseAlign()));
1908
1909 OffsetBytes += PtrSize;
1910 };
1911
1912 // void* stack at offset 0
1913 PushAddress(FuncInfo->getVarArgsStackIndex(), 0);
1914
1915 // void* gr_top at offset 8 (4 on ILP32)
1916 const unsigned GPRSize = FuncInfo->getVarArgsGPRSize();
1917 PushAddress(FuncInfo->getVarArgsGPRIndex(), GPRSize);
1918
1919 // void* vr_top at offset 16 (8 on ILP32)
1920 const unsigned FPRSize = FuncInfo->getVarArgsFPRSize();
1921 PushAddress(FuncInfo->getVarArgsFPRIndex(), FPRSize);
1922
1923 // Helper function to store a 4-byte integer constant to VAList at offset
1924 // OffsetBytes, and increment OffsetBytes by 4.
1925 const auto PushIntConstant = [&](const int32_t Value) {
1926 constexpr int IntSize = 4;
1927 const Register Temp = MRI.createVirtualRegister(&AArch64::GPR32RegClass);
1928 auto MIB =
1929 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AArch64::MOVi32imm))
1930 .addDef(Temp)
1931 .addImm(Value);
1933
1934 const auto *MMO = *I.memoperands_begin();
1935 MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AArch64::STRWui))
1936 .addUse(Temp)
1937 .addUse(VAList)
1938 .addImm(OffsetBytes / IntSize)
1940 MMO->getPointerInfo().getWithOffset(OffsetBytes),
1941 MachineMemOperand::MOStore, IntSize, MMO->getBaseAlign()));
1943 OffsetBytes += IntSize;
1944 };
1945
1946 // int gr_offs at offset 24 (12 on ILP32)
1947 PushIntConstant(-static_cast<int32_t>(GPRSize));
1948
1949 // int vr_offs at offset 28 (16 on ILP32)
1950 PushIntConstant(-static_cast<int32_t>(FPRSize));
1951
1952 assert(OffsetBytes == (STI.isTargetILP32() ? 20 : 32) && "Unexpected offset");
1953
1954 I.eraseFromParent();
1955 return true;
1956}
1957
1958bool AArch64InstructionSelector::selectVaStartDarwin(
1959 MachineInstr &I, MachineFunction &MF, MachineRegisterInfo &MRI) const {
1960 AArch64FunctionInfo *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
1961 Register ListReg = I.getOperand(0).getReg();
1962
1963 Register ArgsAddrReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
1964
1965 int FrameIdx = FuncInfo->getVarArgsStackIndex();
1966 if (MF.getSubtarget<AArch64Subtarget>().isCallingConvWin64(
1968 FrameIdx = FuncInfo->getVarArgsGPRSize() > 0
1969 ? FuncInfo->getVarArgsGPRIndex()
1970 : FuncInfo->getVarArgsStackIndex();
1971 }
1972
1973 auto MIB =
1974 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AArch64::ADDXri))
1975 .addDef(ArgsAddrReg)
1976 .addFrameIndex(FrameIdx)
1977 .addImm(0)
1978 .addImm(0);
1979
1981
1982 MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AArch64::STRXui))
1983 .addUse(ArgsAddrReg)
1984 .addUse(ListReg)
1985 .addImm(0)
1986 .addMemOperand(*I.memoperands_begin());
1987
1989 I.eraseFromParent();
1990 return true;
1991}
1992
1993void AArch64InstructionSelector::materializeLargeCMVal(
1994 MachineInstr &I, const Value *V, unsigned OpFlags) {
1995 MachineBasicBlock &MBB = *I.getParent();
1996 MachineFunction &MF = *MBB.getParent();
1997 MachineRegisterInfo &MRI = MF.getRegInfo();
1998
1999 auto MovZ = MIB.buildInstr(AArch64::MOVZXi, {&AArch64::GPR64RegClass}, {});
2000 MovZ->addOperand(MF, I.getOperand(1));
2001 MovZ->getOperand(1).setTargetFlags(OpFlags | AArch64II::MO_G0 |
2003 MovZ->addOperand(MF, MachineOperand::CreateImm(0));
2005
2006 auto BuildMovK = [&](Register SrcReg, unsigned char Flags, unsigned Offset,
2007 Register ForceDstReg) {
2008 Register DstReg = ForceDstReg
2009 ? ForceDstReg
2010 : MRI.createVirtualRegister(&AArch64::GPR64RegClass);
2011 auto MovI = MIB.buildInstr(AArch64::MOVKXi).addDef(DstReg).addUse(SrcReg);
2012 if (auto *GV = dyn_cast<GlobalValue>(V)) {
2013 MovI->addOperand(MF, MachineOperand::CreateGA(
2014 GV, MovZ->getOperand(1).getOffset(), Flags));
2015 } else {
2016 MovI->addOperand(
2018 MovZ->getOperand(1).getOffset(), Flags));
2019 }
2022 return DstReg;
2023 };
2024 Register DstReg = BuildMovK(MovZ.getReg(0),
2026 DstReg = BuildMovK(DstReg, AArch64II::MO_G2 | AArch64II::MO_NC, 32, 0);
2027 BuildMovK(DstReg, AArch64II::MO_G3, 48, I.getOperand(0).getReg());
2028}
2029
2030bool AArch64InstructionSelector::preISelLower(MachineInstr &I) {
2031 MachineBasicBlock &MBB = *I.getParent();
2032 MachineFunction &MF = *MBB.getParent();
2033 MachineRegisterInfo &MRI = MF.getRegInfo();
2034
2035 switch (I.getOpcode()) {
2036 case TargetOpcode::G_CONSTANT: {
2037 Register DefReg = I.getOperand(0).getReg();
2038 const LLT DefTy = MRI.getType(DefReg);
2039 if (!DefTy.isPointer()) {
2040 if (DefTy.getSizeInBits() >= 32 ||
2041 RBI.getRegBank(DefReg, MRI, TRI)->getID() != AArch64::GPRRegBankID)
2042 return false;
2043 // Widen narrow GPR constants to s32 so imported patterns can match.
2044 APInt Val = I.getOperand(1).getCImm()->getValue().zext(32);
2045 I.getOperand(1).setCImm(
2046 ConstantInt::get(MF.getFunction().getContext(), Val));
2047
2049 MRI.setRegBank(WideReg, RBI.getRegBank(AArch64::GPRRegBankID));
2050 I.getOperand(0).setReg(WideReg);
2051
2052 MIB.setInsertPt(MBB, std::next(I.getIterator()));
2053 auto Copy = MIB.buildCopy(DefReg, WideReg);
2054 selectCopy(*Copy, TII, MRI, TRI, RBI);
2055 MIB.setInstr(I);
2056 return true;
2057 }
2058 const unsigned PtrSize = DefTy.getSizeInBits();
2059 if (PtrSize != 32 && PtrSize != 64)
2060 return false;
2061 // Convert pointer typed constants to integers so TableGen can select.
2062 MRI.setType(DefReg, LLT::integer(PtrSize));
2063 return true;
2064 }
2065 case TargetOpcode::G_STORE: {
2066 bool Changed = contractCrossBankCopyIntoStore(I, MRI);
2067 MachineOperand &SrcOp = I.getOperand(0);
2068 if (MRI.getType(SrcOp.getReg()).isPointer()) {
2069 // Allow matching with imported patterns for stores of pointers. Unlike
2070 // G_LOAD/G_PTR_ADD, we may not have selected all users. So, emit a copy
2071 // and constrain.
2072 auto Copy = MIB.buildCopy(LLT::scalar(64), SrcOp);
2073 Register NewSrc = Copy.getReg(0);
2074 SrcOp.setReg(NewSrc);
2075 RBI.constrainGenericRegister(NewSrc, AArch64::GPR64RegClass, MRI);
2076 Changed = true;
2077 }
2078 return Changed;
2079 }
2080 case TargetOpcode::G_PTR_ADD: {
2081 // If Checked Pointer Arithmetic (FEAT_CPA) is present, preserve the pointer
2082 // arithmetic semantics instead of falling back to regular arithmetic.
2083 const auto &TL = STI.getTargetLowering();
2084 if (TL->shouldPreservePtrArith(MF.getFunction(), EVT()))
2085 return false;
2086 return convertPtrAddToAdd(I, MRI);
2087 }
2088 case TargetOpcode::G_LOAD: {
2089 // For scalar loads of pointers, we try to convert the dest type from p0
2090 // to s64 so that our imported patterns can match. Like with the G_PTR_ADD
2091 // conversion, this should be ok because all users should have been
2092 // selected already, so the type doesn't matter for them.
2093 Register DstReg = I.getOperand(0).getReg();
2094 const LLT DstTy = MRI.getType(DstReg);
2095 if (!DstTy.isPointer())
2096 return false;
2097 MRI.setType(DstReg, LLT::scalar(64));
2098 return true;
2099 }
2100 case TargetOpcode::G_VECREDUCE_ADD:
2101 case TargetOpcode::G_VECREDUCE_SMAX:
2102 case TargetOpcode::G_VECREDUCE_SMIN:
2103 case TargetOpcode::G_VECREDUCE_UMAX:
2104 case TargetOpcode::G_VECREDUCE_UMIN: {
2105 // Imported patterns require an FPR result. For a GPR, use a temporary FPR
2106 // and insert a cross-bank copy.
2107 Register DstReg = I.getOperand(0).getReg();
2108 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
2109 if (DstRB.getID() != AArch64::GPRRegBankID)
2110 return false;
2111
2112 LLT DstTy = MRI.getType(DstReg);
2113 const TargetRegisterClass *DstRC =
2114 getRegClassForTypeOnBank(DstTy, DstRB, /*GetAllRegSet=*/true);
2115 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, MRI))
2116 return false;
2117
2119 MRI.setRegBank(FPRDst, RBI.getRegBank(AArch64::FPRRegBankID));
2120 I.getOperand(0).setReg(FPRDst);
2121
2122 BuildMI(MBB, std::next(I.getIterator()), MIMetadata(I),
2123 TII.get(TargetOpcode::COPY), DstReg)
2124 .addReg(FPRDst);
2125 return true;
2126 }
2127 case TargetOpcode::G_SPLAT_VECTOR: {
2128 // Convert the type from p0 to s64 to help selection.
2129 LLT DstTy = MRI.getType(I.getOperand(0).getReg());
2130 if (!DstTy.isPointerVector())
2131 return false;
2132 auto NewSrc = MIB.buildCopy(LLT::scalar(64), I.getOperand(1).getReg());
2133 MRI.setType(I.getOperand(0).getReg(),
2134 DstTy.changeElementType(LLT::scalar(64)));
2135 MRI.setRegClass(NewSrc.getReg(0), &AArch64::GPR64RegClass);
2136 I.getOperand(1).setReg(NewSrc.getReg(0));
2137 return true;
2138 }
2139 case AArch64::G_INSERT_VECTOR_ELT: {
2140 LLT DstTy = MRI.getType(I.getOperand(0).getReg());
2141 LLT SrcVecTy = MRI.getType(I.getOperand(1).getReg());
2142 if (SrcVecTy.isPointerVector()) {
2143 // Convert the type from p0 to s64 to help selection.
2144 auto NewSrc = MIB.buildCopy(LLT::scalar(64), I.getOperand(2).getReg());
2145 MRI.setType(I.getOperand(1).getReg(),
2146 DstTy.changeElementType(LLT::scalar(64)));
2147 MRI.setType(I.getOperand(0).getReg(),
2148 DstTy.changeElementType(LLT::scalar(64)));
2149 MRI.setRegClass(NewSrc.getReg(0), &AArch64::GPR64RegClass);
2150 I.getOperand(2).setReg(NewSrc.getReg(0));
2151 return true;
2152 }
2153
2154 Register EltReg = I.getOperand(2).getReg();
2155 LLT EltTy = MRI.getType(EltReg);
2156 if (EltTy.isScalar() &&
2157 (EltTy.getSizeInBits() == 8 || EltTy.getSizeInBits() == 16) &&
2158 RBI.getRegBank(EltReg, MRI, TRI)->getID() == AArch64::GPRRegBankID) {
2159 // Convert the type from s8/s16 to s32 to help selection.
2160 auto NewElt = MIB.buildCopy(LLT::scalar(32), EltReg);
2161 MRI.setRegClass(NewElt.getReg(0), &AArch64::GPR32RegClass);
2162 I.getOperand(2).setReg(NewElt.getReg(0));
2163 return true;
2164 }
2165 return false;
2166 }
2167 case TargetOpcode::G_UITOFP:
2168 case TargetOpcode::G_SITOFP: {
2169 // If both source and destination regbanks are FPR, then convert the opcode
2170 // to G_SITOF so that the importer can select it to an fpr variant.
2171 // Otherwise, it ends up matching an fpr/gpr variant and adding a cross-bank
2172 // copy.
2173 Register SrcReg = I.getOperand(1).getReg();
2174 LLT SrcTy = MRI.getType(SrcReg);
2175 LLT DstTy = MRI.getType(I.getOperand(0).getReg());
2176 if (SrcTy.isVector() || SrcTy.getSizeInBits() != DstTy.getSizeInBits())
2177 return false;
2178
2179 if (RBI.getRegBank(SrcReg, MRI, TRI)->getID() == AArch64::FPRRegBankID) {
2180 // Need to add a copy to change the type so that the existing patterns can
2181 // match when there is an integer on an FPR bank.
2182 if (SrcTy.getScalarType().isInteger()) {
2183 auto Copy = MIB.buildCopy(DstTy, SrcReg);
2184 I.getOperand(1).setReg(Copy.getReg(0));
2185 MRI.setRegClass(Copy.getReg(0),
2186 getRegClassForTypeOnBank(
2187 SrcTy, RBI.getRegBank(AArch64::FPRRegBankID)));
2188 }
2189 if (I.getOpcode() == TargetOpcode::G_SITOFP)
2190 I.setDesc(TII.get(AArch64::G_SITOF));
2191 else
2192 I.setDesc(TII.get(AArch64::G_UITOF));
2193 return true;
2194 }
2195 return false;
2196 }
2197 default:
2198 return false;
2199 }
2200}
2201
2202/// This lowering tries to look for G_PTR_ADD instructions and then converts
2203/// them to a standard G_ADD with a COPY on the source.
2204///
2205/// The motivation behind this is to expose the add semantics to the imported
2206/// tablegen patterns. We shouldn't need to check for uses being loads/stores,
2207/// because the selector works bottom up, uses before defs. By the time we
2208/// end up trying to select a G_PTR_ADD, we should have already attempted to
2209/// fold this into addressing modes and were therefore unsuccessful.
2210bool AArch64InstructionSelector::convertPtrAddToAdd(
2211 MachineInstr &I, MachineRegisterInfo &MRI) {
2212 assert(I.getOpcode() == TargetOpcode::G_PTR_ADD && "Expected G_PTR_ADD");
2213 Register DstReg = I.getOperand(0).getReg();
2214 Register AddOp1Reg = I.getOperand(1).getReg();
2215 const LLT PtrTy = MRI.getType(DstReg);
2216 if (PtrTy.getAddressSpace() != 0)
2217 return false;
2218
2219 const LLT CastPtrTy = PtrTy.isVector()
2221 : LLT::integer(64);
2222 auto PtrToInt = MIB.buildPtrToInt(CastPtrTy, AddOp1Reg);
2223 // Set regbanks on the registers.
2224 if (PtrTy.isVector())
2225 MRI.setRegBank(PtrToInt.getReg(0), RBI.getRegBank(AArch64::FPRRegBankID));
2226 else
2227 MRI.setRegBank(PtrToInt.getReg(0), RBI.getRegBank(AArch64::GPRRegBankID));
2228
2229 // Now turn the %dst(p0) = G_PTR_ADD %base, off into:
2230 // %dst(intty) = G_ADD %intbase, off
2231 I.setDesc(TII.get(TargetOpcode::G_ADD));
2232 MRI.setType(DstReg, CastPtrTy);
2233 I.getOperand(1).setReg(PtrToInt.getReg(0));
2234 if (!select(*PtrToInt)) {
2235 LLVM_DEBUG(dbgs() << "Failed to select G_PTRTOINT in convertPtrAddToAdd");
2236 return false;
2237 }
2238
2239 // Also take the opportunity here to try to do some optimization.
2240 // Try to convert this into a G_SUB if the offset is a 0-x negate idiom.
2241 Register NegatedReg;
2242 if (!mi_match(I.getOperand(2).getReg(), MRI, m_Neg(m_Reg(NegatedReg))))
2243 return true;
2244 I.getOperand(2).setReg(NegatedReg);
2245 I.setDesc(TII.get(TargetOpcode::G_SUB));
2246 return true;
2247}
2248
2249bool AArch64InstructionSelector::earlySelectSHL(MachineInstr &I,
2250 MachineRegisterInfo &MRI) {
2251 // We try to match the immediate variant of LSL, which is actually an alias
2252 // for a special case of UBFM. Otherwise, we fall back to the imported
2253 // selector which will match the register variant.
2254 assert(I.getOpcode() == TargetOpcode::G_SHL && "unexpected op");
2255 const auto &MO = I.getOperand(2);
2256 auto VRegAndVal = getIConstantVRegVal(MO.getReg(), MRI);
2257 if (!VRegAndVal)
2258 return false;
2259
2260 const LLT DstTy = MRI.getType(I.getOperand(0).getReg());
2261 if (DstTy.isVector())
2262 return false;
2263 bool Is64Bit = DstTy.getSizeInBits() == 64;
2264 auto Imm1Fn = Is64Bit ? selectShiftA_64(MO) : selectShiftA_32(MO);
2265 auto Imm2Fn = Is64Bit ? selectShiftB_64(MO) : selectShiftB_32(MO);
2266
2267 if (!Imm1Fn || !Imm2Fn)
2268 return false;
2269
2270 auto NewI =
2271 MIB.buildInstr(Is64Bit ? AArch64::UBFMXri : AArch64::UBFMWri,
2272 {I.getOperand(0).getReg()}, {I.getOperand(1).getReg()});
2273
2274 for (auto &RenderFn : *Imm1Fn)
2275 RenderFn(NewI);
2276 for (auto &RenderFn : *Imm2Fn)
2277 RenderFn(NewI);
2278
2279 I.eraseFromParent();
2281 return true;
2282}
2283
2284bool AArch64InstructionSelector::contractCrossBankCopyIntoStore(
2285 MachineInstr &I, MachineRegisterInfo &MRI) {
2286 assert(I.getOpcode() == TargetOpcode::G_STORE && "Expected G_STORE");
2287 // If we're storing a scalar, it doesn't matter what register bank that
2288 // scalar is on. All that matters is the size.
2289 //
2290 // So, if we see something like this (with a 32-bit scalar as an example):
2291 //
2292 // %x:gpr(s32) = ... something ...
2293 // %y:fpr(s32) = COPY %x:gpr(s32)
2294 // G_STORE %y:fpr(s32)
2295 //
2296 // We can fix this up into something like this:
2297 //
2298 // G_STORE %x:gpr(s32)
2299 //
2300 // And then continue the selection process normally.
2301 Register DefDstReg = getSrcRegIgnoringCopies(I.getOperand(0).getReg(), MRI);
2302 if (!DefDstReg.isValid())
2303 return false;
2304 LLT DefDstTy = MRI.getType(DefDstReg);
2305 Register StoreSrcReg = I.getOperand(0).getReg();
2306 LLT StoreSrcTy = MRI.getType(StoreSrcReg);
2307
2308 // If we get something strange like a physical register, then we shouldn't
2309 // go any further.
2310 if (!DefDstTy.isValid())
2311 return false;
2312
2313 // Are the source and dst types the same size?
2314 if (DefDstTy.getSizeInBits() != StoreSrcTy.getSizeInBits())
2315 return false;
2316
2317 if (RBI.getRegBank(StoreSrcReg, MRI, TRI) ==
2318 RBI.getRegBank(DefDstReg, MRI, TRI))
2319 return false;
2320
2321 // We have a cross-bank copy, which is entering a store. Let's fold it.
2322 I.getOperand(0).setReg(DefDstReg);
2323 return true;
2324}
2325
2326bool AArch64InstructionSelector::earlySelect(MachineInstr &I) {
2327 assert(I.getParent() && "Instruction should be in a basic block!");
2328 assert(I.getParent()->getParent() && "Instruction should be in a function!");
2329
2330 MachineBasicBlock &MBB = *I.getParent();
2331 MachineFunction &MF = *MBB.getParent();
2332 MachineRegisterInfo &MRI = MF.getRegInfo();
2333
2334 switch (I.getOpcode()) {
2335 case TargetOpcode::G_SPLAT_VECTOR: {
2336 Register Dst = I.getOperand(0).getReg();
2337 LLT DstTy = MRI.getType(Dst);
2338 if (DstTy.isScalableVector())
2339 return false;
2340 // Before selecting a DUP instruction, check if it is better selected as a
2341 // MOV or load from a constant pool.
2342 Register Src = I.getOperand(1).getReg();
2343 auto ValAndVReg = getAnyConstantVRegValWithLookThrough(
2344 Src, MRI, /*LookThroughInstrs=*/true, /*LookThroughAnyExt=*/true);
2345 if (!ValAndVReg)
2346 return false;
2347 LLVMContext &Ctx = MF.getFunction().getContext();
2349 DstTy.getNumElements(),
2350 ConstantInt::get(Type::getIntNTy(Ctx, DstTy.getScalarSizeInBits()),
2351 ValAndVReg->Value.trunc(DstTy.getScalarSizeInBits())));
2352 APInt Imm =
2354 ValAndVReg->Value.trunc(DstTy.getScalarSizeInBits()));
2355 if (!emitConstantVector(Dst, CV, Imm, MRI))
2356 return false;
2357 I.eraseFromParent();
2358 return true;
2359 }
2360 case TargetOpcode::G_SEXT:
2361 // Check for i64 sext(i32 vector_extract) prior to tablegen to select SMOV
2362 // over a normal extend.
2363 if (selectUSMovFromExtend(I, MRI))
2364 return true;
2365 return false;
2366 case TargetOpcode::G_BR:
2367 return false;
2368 case TargetOpcode::G_SHL:
2369 return earlySelectSHL(I, MRI);
2370 case TargetOpcode::G_CONSTANT: {
2371 bool IsZero = false;
2372 if (I.getOperand(1).isCImm())
2373 IsZero = I.getOperand(1).getCImm()->isZero();
2374 else if (I.getOperand(1).isImm())
2375 IsZero = I.getOperand(1).getImm() == 0;
2376
2377 if (!IsZero)
2378 return false;
2379
2380 Register DefReg = I.getOperand(0).getReg();
2381 LLT Ty = MRI.getType(DefReg);
2382 if (Ty.getSizeInBits() == 64) {
2383 I.getOperand(1).ChangeToRegister(AArch64::XZR, false);
2384 RBI.constrainGenericRegister(DefReg, AArch64::GPR64RegClass, MRI);
2385 } else if (Ty.getSizeInBits() <= 32) {
2386 I.getOperand(1).ChangeToRegister(AArch64::WZR, false);
2387 RBI.constrainGenericRegister(DefReg, AArch64::GPR32RegClass, MRI);
2388 } else
2389 return false;
2390
2391 I.setDesc(TII.get(TargetOpcode::COPY));
2392 return true;
2393 }
2394
2395 case TargetOpcode::G_ADD: {
2396 // Check if this is being fed by a G_ICMP on either side.
2397 //
2398 // (cmp pred, x, y) + z
2399 //
2400 // In the above case, when the cmp is true, we increment z by 1. So, we can
2401 // fold the add into the cset for the cmp by using cinc.
2402 //
2403 // FIXME: This would probably be a lot nicer in PostLegalizerLowering.
2404 Register AddDst = I.getOperand(0).getReg();
2405 Register AddLHS = I.getOperand(1).getReg();
2406 Register AddRHS = I.getOperand(2).getReg();
2407 // Only handle scalars.
2408 LLT Ty = MRI.getType(AddLHS);
2409 if (Ty.isVector())
2410 return false;
2411 // Since G_ICMP is modeled as ADDS/SUBS/ANDS, we can handle 32 bits or 64
2412 // bits.
2413 unsigned Size = Ty.getSizeInBits();
2414 if (Size != 32 && Size != 64)
2415 return false;
2416 auto MatchCmp = [&](Register Reg) -> MachineInstr * {
2417 if (!MRI.hasOneNonDBGUse(Reg))
2418 return nullptr;
2419 // If the LHS of the add is 32 bits, then we want to fold a 32-bit
2420 // compare.
2421 if (Size == 32)
2422 return getOpcodeDef(TargetOpcode::G_ICMP, Reg, MRI);
2423 // We model scalar compares using 32-bit destinations right now.
2424 // If it's a 64-bit compare, it'll have 64-bit sources.
2425 Register ZExt;
2426 if (!mi_match(Reg, MRI, m_OneUse(m_GZExt(m_OneUse(m_Reg(ZExt))))))
2427 return nullptr;
2428 auto *Cmp = getOpcodeDef(TargetOpcode::G_ICMP, ZExt, MRI);
2429 if (!Cmp ||
2430 MRI.getType(Cmp->getOperand(2).getReg()).getSizeInBits() != 64)
2431 return nullptr;
2432 return Cmp;
2433 };
2434 // Try to match
2435 // z + (cmp pred, x, y)
2436 MachineInstr *Cmp = MatchCmp(AddRHS);
2437 if (!Cmp) {
2438 // (cmp pred, x, y) + z
2439 std::swap(AddLHS, AddRHS);
2440 Cmp = MatchCmp(AddRHS);
2441 if (!Cmp)
2442 return false;
2443 }
2444 auto &PredOp = Cmp->getOperand(1);
2446 emitIntegerCompare(/*LHS=*/Cmp->getOperand(2),
2447 /*RHS=*/Cmp->getOperand(3), PredOp, MIB);
2448 auto Pred = static_cast<CmpInst::Predicate>(PredOp.getPredicate());
2450 CmpInst::getInversePredicate(Pred), Cmp->getOperand(3).getReg(), &MRI);
2451 emitCSINC(/*Dst=*/AddDst, /*Src =*/AddLHS, /*Src2=*/AddLHS, InvCC, MIB);
2452 I.eraseFromParent();
2453 return true;
2454 }
2455 case TargetOpcode::G_OR: {
2456 // Look for operations that take the lower `Width=Size-ShiftImm` bits of
2457 // `ShiftSrc` and insert them into the upper `Width` bits of `MaskSrc` via
2458 // shifting and masking that we can replace with a BFI (encoded as a BFM).
2459 Register Dst = I.getOperand(0).getReg();
2460 LLT Ty = MRI.getType(Dst);
2461
2462 if (!Ty.isScalar())
2463 return false;
2464
2465 unsigned Size = Ty.getSizeInBits();
2466 if (Size != 32 && Size != 64)
2467 return false;
2468
2469 Register ShiftSrc;
2470 int64_t ShiftImm;
2471 Register MaskSrc;
2472 int64_t MaskImm;
2473 if (!mi_match(Dst, MRI,
2474 m_GOr(m_OneUse(m_GShl(m_Reg(ShiftSrc), m_ICst(ShiftImm))),
2475 m_OneUse(m_GAnd(m_Reg(MaskSrc), m_ICst(MaskImm))))))
2476 return false;
2477
2478 if (ShiftImm > Size || ((1ULL << ShiftImm) - 1ULL) != uint64_t(MaskImm))
2479 return false;
2480
2481 int64_t Immr = Size - ShiftImm;
2482 int64_t Imms = Size - ShiftImm - 1;
2483 unsigned Opc = Size == 32 ? AArch64::BFMWri : AArch64::BFMXri;
2484 emitInstr(Opc, {Dst}, {MaskSrc, ShiftSrc, Immr, Imms}, MIB);
2485 I.eraseFromParent();
2486 return true;
2487 }
2488 case TargetOpcode::G_FENCE: {
2489 if (I.getOperand(1).getImm() == 0)
2490 BuildMI(MBB, I, MIMetadata(I), TII.get(TargetOpcode::MEMBARRIER));
2491 else
2492 BuildMI(MBB, I, MIMetadata(I), TII.get(AArch64::DMB))
2493 .addImm(I.getOperand(0).getImm() == 4 ? 0x9 : 0xb);
2494 I.eraseFromParent();
2495 return true;
2496 }
2497 case TargetOpcode::G_BRINDIRECT: {
2498 const Function &Fn = MF.getFunction();
2499 if (std::optional<uint16_t> BADisc =
2501 auto MI = MIB.buildInstr(AArch64::BRA, {}, {I.getOperand(0).getReg()});
2503 MI.addImm(*BADisc);
2504 MI.addReg(/*AddrDisc=*/AArch64::XZR);
2505 I.eraseFromParent();
2507 return true;
2508 }
2509 // Use table-based selection.
2510 return false;
2511 }
2512
2513 default:
2514 return false;
2515 }
2516}
2517
2518bool AArch64InstructionSelector::select(MachineInstr &I) {
2519 assert(I.getParent() && "Instruction should be in a basic block!");
2520 assert(I.getParent()->getParent() && "Instruction should be in a function!");
2521
2522 MachineBasicBlock &MBB = *I.getParent();
2523 MachineFunction &MF = *MBB.getParent();
2524 MachineRegisterInfo &MRI = MF.getRegInfo();
2525
2526 const AArch64Subtarget *Subtarget = &MF.getSubtarget<AArch64Subtarget>();
2527 if (Subtarget->requiresStrictAlign()) {
2528 // We don't support this feature yet.
2529 LLVM_DEBUG(dbgs() << "AArch64 GISel does not support strict-align yet\n");
2530 return false;
2531 }
2532
2534
2535 unsigned Opcode = I.getOpcode();
2536 // G_PHI requires same handling as PHI
2537 if (!I.isPreISelOpcode() || Opcode == TargetOpcode::G_PHI) {
2538 // Certain non-generic instructions also need some special handling.
2539
2540 if (Opcode == TargetOpcode::LOAD_STACK_GUARD) {
2542 return true;
2543 }
2544
2545 if (Opcode == TargetOpcode::PHI || Opcode == TargetOpcode::G_PHI) {
2546 const Register DefReg = I.getOperand(0).getReg();
2547 const LLT DefTy = MRI.getType(DefReg);
2548
2549 const RegClassOrRegBank &RegClassOrBank =
2550 MRI.getRegClassOrRegBank(DefReg);
2551
2552 const TargetRegisterClass *DefRC =
2554 if (!DefRC) {
2555 if (!DefTy.isValid()) {
2556 LLVM_DEBUG(dbgs() << "PHI operand has no type, not a gvreg?\n");
2557 return false;
2558 }
2559 const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
2560 DefRC = getRegClassForTypeOnBank(DefTy, RB);
2561 if (!DefRC) {
2562 LLVM_DEBUG(dbgs() << "PHI operand has unexpected size/bank\n");
2563 return false;
2564 }
2565 }
2566
2567 I.setDesc(TII.get(TargetOpcode::PHI));
2568
2569 return RBI.constrainGenericRegister(DefReg, *DefRC, MRI);
2570 }
2571
2572 if (I.isCopy())
2573 return selectCopy(I, TII, MRI, TRI, RBI);
2574
2575 return true;
2576 }
2577
2578
2579 if (I.getNumOperands() != I.getNumExplicitOperands()) {
2580 LLVM_DEBUG(
2581 dbgs() << "Generic instruction has unexpected implicit operands\n");
2582 return false;
2583 }
2584
2585 // Try to do some lowering before we start instruction selecting. These
2586 // lowerings are purely transformations on the input G_MIR and so selection
2587 // must continue after any modification of the instruction.
2588 if (preISelLower(I)) {
2589 Opcode = I.getOpcode(); // The opcode may have been modified, refresh it.
2590 }
2591
2592 // There may be patterns where the importer can't deal with them optimally,
2593 // but does select it to a suboptimal sequence so our custom C++ selection
2594 // code later never has a chance to work on it. Therefore, we have an early
2595 // selection attempt here to give priority to certain selection routines
2596 // over the imported ones.
2597 if (earlySelect(I))
2598 return true;
2599
2600 if (selectImpl(I, *CoverageInfo))
2601 return true;
2602
2603 LLT Ty =
2604 I.getOperand(0).isReg() ? MRI.getType(I.getOperand(0).getReg()) : LLT{};
2605
2606 switch (Opcode) {
2607 case TargetOpcode::G_SBFX:
2608 case TargetOpcode::G_UBFX: {
2609 static const unsigned OpcTable[2][2] = {
2610 {AArch64::UBFMWri, AArch64::UBFMXri},
2611 {AArch64::SBFMWri, AArch64::SBFMXri}};
2612 bool IsSigned = Opcode == TargetOpcode::G_SBFX;
2613 unsigned Size = Ty.getSizeInBits();
2614 unsigned Opc = OpcTable[IsSigned][Size == 64];
2615 auto Cst1 =
2616 getIConstantVRegValWithLookThrough(I.getOperand(2).getReg(), MRI);
2617 assert(Cst1 && "Should have gotten a constant for src 1?");
2618 auto Cst2 =
2619 getIConstantVRegValWithLookThrough(I.getOperand(3).getReg(), MRI);
2620 assert(Cst2 && "Should have gotten a constant for src 2?");
2621 auto LSB = Cst1->Value.getZExtValue();
2622 auto Width = Cst2->Value.getZExtValue();
2623 auto BitfieldInst =
2624 MIB.buildInstr(Opc, {I.getOperand(0)}, {I.getOperand(1)})
2625 .addImm(LSB)
2626 .addImm(LSB + Width - 1);
2627 I.eraseFromParent();
2628 constrainSelectedInstRegOperands(*BitfieldInst, TII, TRI, RBI);
2629 return true;
2630 }
2631 case TargetOpcode::G_BRCOND:
2632 return selectCompareBranch(I, MF, MRI);
2633
2634 case TargetOpcode::G_BRJT:
2635 return selectBrJT(I, MRI);
2636
2637 case AArch64::G_ADD_LOW: {
2638 // This op may have been separated from it's ADRP companion by the localizer
2639 // or some other code motion pass. Given that many CPUs will try to
2640 // macro fuse these operations anyway, select this into a MOVaddr pseudo
2641 // which will later be expanded into an ADRP+ADD pair after scheduling.
2642 MachineInstr *BaseMI = MRI.getVRegDef(I.getOperand(1).getReg());
2643 if (BaseMI->getOpcode() != AArch64::ADRP) {
2644 I.setDesc(TII.get(AArch64::ADDXri));
2645 I.addOperand(MachineOperand::CreateImm(0));
2647 return true;
2648 }
2650 "Expected small code model");
2651 auto Op1 = BaseMI->getOperand(1);
2652 auto Op2 = I.getOperand(2);
2653 auto MovAddr = MIB.buildInstr(AArch64::MOVaddr, {I.getOperand(0)}, {})
2654 .addGlobalAddress(Op1.getGlobal(), Op1.getOffset(),
2655 Op1.getTargetFlags())
2656 .addGlobalAddress(Op2.getGlobal(), Op2.getOffset(),
2657 Op2.getTargetFlags());
2658 I.eraseFromParent();
2659 constrainSelectedInstRegOperands(*MovAddr, TII, TRI, RBI);
2660 return true;
2661 }
2662
2663 case TargetOpcode::G_FCONSTANT: {
2664 const Register DefReg = I.getOperand(0).getReg();
2665 const LLT DefTy = MRI.getType(DefReg);
2666 const unsigned DefSize = DefTy.getSizeInBits();
2667 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
2668
2669 const TargetRegisterClass &FPRRC = *getRegClassForTypeOnBank(DefTy, RB);
2670 assert(
2671 (DefSize == 16 || DefSize == 32 || DefSize == 64 || DefSize == 128) &&
2672 "Unexpected destination size for G_FCONSTANT?");
2673
2674 // Try to emit as a vector movi.
2675 const ConstantFP *FPImm = I.getOperand(1).getFPImm();
2676 APInt Imm = DefSize >= 64
2677 ? FPImm->getValue().bitcastToAPInt()
2678 : APInt::getSplat(64, FPImm->getValue().bitcastToAPInt());
2679 if (auto *Mov = emitConstantMOVVector(
2680 DefSize >= 64 ? DstOp(DefReg) : DstOp(&AArch64::FPR64RegClass), Imm,
2681 MRI)) {
2682 if (DefSize < 64) {
2683 MIB.buildInstr(TargetOpcode::COPY, {DefReg}, {})
2684 .addReg(Mov->getOperand(0).getReg(), {},
2685 DefSize == 16 ? AArch64::hsub : AArch64::ssub);
2686 RBI.constrainGenericRegister(DefReg, FPRRC, MRI);
2687 }
2688 I.eraseFromParent();
2689 return true;
2690 }
2691
2692 // If TLI says that this fpimm is legal then prefer a copy from GPR movimm,
2693 // otherwise we'll expand to a constant pool load
2694 bool OptForSize = shouldOptForSize(&MF);
2695 const auto &TLI = MF.getSubtarget().getTargetLowering();
2696 if ((DefSize == 32 || DefSize == 64) &&
2697 TLI->isFPImmLegal(I.getOperand(1).getFPImm()->getValueAPF(),
2698 EVT::getFloatingPointVT(DefSize), OptForSize)) {
2699 // Emit a copy to emit a normal movimm.
2700 const Register DefGPRReg = MRI.createVirtualRegister(
2701 DefSize == 64 ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass);
2702 MachineOperand &RegOp = I.getOperand(0);
2703 RegOp.setReg(DefGPRReg);
2704 MIB.setInsertPt(MIB.getMBB(), std::next(I.getIterator()));
2705 MIB.buildCopy({DefReg}, {DefGPRReg});
2706
2707 if (!RBI.constrainGenericRegister(DefReg, FPRRC, MRI)) {
2708 LLVM_DEBUG(dbgs() << "Failed to constrain G_FCONSTANT def operand\n");
2709 return false;
2710 }
2711
2712 MachineOperand &ImmOp = I.getOperand(1);
2713 ImmOp.ChangeToImmediate(
2715
2716 const unsigned MovOpc =
2717 DefSize == 64 ? AArch64::MOVi64imm : AArch64::MOVi32imm;
2718 I.setDesc(TII.get(MovOpc));
2720 return true;
2721 }
2722
2723 // Expand to a constant pool.
2724 auto *LoadMI = emitLoadFromConstantPool(FPImm, MIB);
2725 if (!LoadMI) {
2726 LLVM_DEBUG(dbgs() << "Failed to load double constant pool entry\n");
2727 return false;
2728 }
2729 MIB.buildCopy({DefReg}, {LoadMI->getOperand(0).getReg()});
2730 I.eraseFromParent();
2731 return RBI.constrainGenericRegister(DefReg, FPRRC, MRI);
2732 }
2733 case TargetOpcode::G_EXTRACT: {
2734 Register DstReg = I.getOperand(0).getReg();
2735 Register SrcReg = I.getOperand(1).getReg();
2736 LLT SrcTy = MRI.getType(SrcReg);
2737 LLT DstTy = MRI.getType(DstReg);
2738 (void)DstTy;
2739 unsigned SrcSize = SrcTy.getSizeInBits();
2740
2741 if (SrcTy.getSizeInBits() > 64) {
2742 // This should be an extract of an s128, which is like a vector extract.
2743 if (SrcTy.getSizeInBits() != 128)
2744 return false;
2745 // Only support extracting 64 bits from an s128 at the moment.
2746 if (DstTy.getSizeInBits() != 64)
2747 return false;
2748
2749 unsigned Offset = I.getOperand(2).getImm();
2750 if (Offset % 64 != 0)
2751 return false;
2752
2753 // Check we have the right regbank always.
2754 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
2755 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
2756 assert(SrcRB.getID() == DstRB.getID() && "Wrong extract regbank!");
2757
2758 if (SrcRB.getID() == AArch64::GPRRegBankID) {
2759 auto NewI =
2760 MIB.buildInstr(TargetOpcode::COPY, {DstReg}, {})
2761 .addUse(SrcReg, {},
2762 Offset == 0 ? AArch64::sube64 : AArch64::subo64);
2763 constrainOperandRegClass(MF, TRI, MRI, TII, RBI, *NewI,
2764 AArch64::GPR64RegClass, NewI->getOperand(0));
2765 I.eraseFromParent();
2766 return true;
2767 }
2768
2769 // Emit the same code as a vector extract.
2770 // Offset must be a multiple of 64.
2771 unsigned LaneIdx = Offset / 64;
2772 MachineInstr *Extract = emitExtractVectorElt(
2773 DstReg, DstRB, LLT::scalar(64), SrcReg, LaneIdx, MIB);
2774 if (!Extract)
2775 return false;
2776 I.eraseFromParent();
2777 return true;
2778 }
2779
2780 I.setDesc(TII.get(SrcSize == 64 ? AArch64::UBFMXri : AArch64::UBFMWri));
2781 MachineInstrBuilder(MF, I).addImm(I.getOperand(2).getImm() +
2782 Ty.getSizeInBits() - 1);
2783
2784 if (SrcSize < 64) {
2785 assert(SrcSize == 32 && DstTy.getSizeInBits() == 16 &&
2786 "unexpected G_EXTRACT types");
2788 return true;
2789 }
2790
2792 MIB.setInsertPt(MIB.getMBB(), std::next(I.getIterator()));
2793 MIB.buildInstr(TargetOpcode::COPY, {I.getOperand(0).getReg()}, {})
2794 .addReg(DstReg, {}, AArch64::sub_32);
2795 RBI.constrainGenericRegister(I.getOperand(0).getReg(),
2796 AArch64::GPR32RegClass, MRI);
2797 I.getOperand(0).setReg(DstReg);
2798
2800 return true;
2801 }
2802
2803 case TargetOpcode::G_INSERT: {
2804 LLT SrcTy = MRI.getType(I.getOperand(2).getReg());
2805 LLT DstTy = MRI.getType(I.getOperand(0).getReg());
2806 unsigned DstSize = DstTy.getSizeInBits();
2807 // Larger inserts are vectors, same-size ones should be something else by
2808 // now (split up or turned into COPYs).
2809 if (Ty.getSizeInBits() > 64 || SrcTy.getSizeInBits() > 32)
2810 return false;
2811
2812 I.setDesc(TII.get(DstSize == 64 ? AArch64::BFMXri : AArch64::BFMWri));
2813 unsigned LSB = I.getOperand(3).getImm();
2814 unsigned Width = MRI.getType(I.getOperand(2).getReg()).getSizeInBits();
2815 I.getOperand(3).setImm((DstSize - LSB) % DstSize);
2816 MachineInstrBuilder(MF, I).addImm(Width - 1);
2817
2818 if (DstSize < 64) {
2819 assert(DstSize == 32 && SrcTy.getSizeInBits() == 16 &&
2820 "unexpected G_INSERT types");
2822 return true;
2823 }
2824
2826 BuildMI(MBB, I.getIterator(), I.getDebugLoc(),
2827 TII.get(AArch64::SUBREG_TO_REG))
2828 .addDef(SrcReg)
2829 .addUse(I.getOperand(2).getReg())
2830 .addImm(AArch64::sub_32);
2831 RBI.constrainGenericRegister(I.getOperand(2).getReg(),
2832 AArch64::GPR32RegClass, MRI);
2833 I.getOperand(2).setReg(SrcReg);
2834
2836 return true;
2837 }
2838 case TargetOpcode::G_FRAME_INDEX: {
2839 // allocas and G_FRAME_INDEX are only supported in addrspace(0).
2840 if (Ty != LLT::pointer(0, 64)) {
2841 LLVM_DEBUG(dbgs() << "G_FRAME_INDEX pointer has type: " << Ty
2842 << ", expected: " << LLT::pointer(0, 64) << '\n');
2843 return false;
2844 }
2845 I.setDesc(TII.get(AArch64::ADDXri));
2846
2847 // MOs for a #0 shifted immediate.
2848 I.addOperand(MachineOperand::CreateImm(0));
2849 I.addOperand(MachineOperand::CreateImm(0));
2850
2852 return true;
2853 }
2854
2855 case TargetOpcode::G_GLOBAL_VALUE: {
2856 const GlobalValue *GV = nullptr;
2857 unsigned OpFlags;
2858 if (I.getOperand(1).isSymbol()) {
2859 OpFlags = I.getOperand(1).getTargetFlags();
2860 // Currently only used by "RtLibUseGOT".
2861 assert(OpFlags == AArch64II::MO_GOT);
2862 } else {
2863 GV = I.getOperand(1).getGlobal();
2864 if (GV->isThreadLocal())
2865 return selectTLSGlobalValue(I, MRI);
2866
2867 OpFlags = STI.ClassifyGlobalReference(GV, TM);
2868 }
2869
2870 if (OpFlags & AArch64II::MO_GOT) {
2871 bool IsGOTSigned = MF.getInfo<AArch64FunctionInfo>()->hasELFSignedGOT();
2872 I.setDesc(TII.get(IsGOTSigned ? AArch64::LOADgotAUTH : AArch64::LOADgot));
2873 I.getOperand(1).setTargetFlags(OpFlags);
2874 I.addImplicitDefUseOperands(MF);
2875 I.setImplicitPhysRegDefsDead();
2876 } else if (TM.getCodeModel() == CodeModel::Large &&
2877 !TM.isPositionIndependent()) {
2878 // Materialize the global using movz/movk instructions.
2879 materializeLargeCMVal(I, GV, OpFlags);
2880 I.eraseFromParent();
2881 return true;
2882 } else if (TM.getCodeModel() == CodeModel::Tiny) {
2883 I.setDesc(TII.get(AArch64::ADR));
2884 I.getOperand(1).setTargetFlags(OpFlags);
2885 } else {
2886 I.setDesc(TII.get(AArch64::MOVaddr));
2887 I.getOperand(1).setTargetFlags(OpFlags | AArch64II::MO_PAGE);
2888 MachineInstrBuilder MIB(MF, I);
2889 MIB.addGlobalAddress(GV, I.getOperand(1).getOffset(),
2891 }
2893 return true;
2894 }
2895
2896 case TargetOpcode::G_PTRAUTH_GLOBAL_VALUE:
2897 return selectPtrAuthGlobalValue(I, MRI);
2898
2899 case TargetOpcode::G_ZEXTLOAD:
2900 case TargetOpcode::G_LOAD:
2901 case TargetOpcode::G_STORE: {
2902 GLoadStore &LdSt = cast<GLoadStore>(I);
2903 bool IsZExtLoad = I.getOpcode() == TargetOpcode::G_ZEXTLOAD;
2904 LLT PtrTy = MRI.getType(LdSt.getPointerReg());
2905
2906 // Can only handle AddressSpace 0, 64-bit pointers.
2907 if (PtrTy != LLT::pointer(0, 64)) {
2908 return false;
2909 }
2910
2911 uint64_t MemSizeInBytes = LdSt.getMemSize().getValue();
2912 unsigned MemSizeInBits = LdSt.getMemSizeInBits().getValue();
2913 AtomicOrdering Order = LdSt.getMMO().getSuccessOrdering();
2914
2915 // Need special instructions for atomics that affect ordering.
2916 if (isStrongerThanMonotonic(Order)) {
2917 assert(!isa<GZExtLoad>(LdSt));
2918 assert(MemSizeInBytes <= 8 &&
2919 "128-bit atomics should already be custom-legalized");
2920
2921 if (isa<GLoad>(LdSt)) {
2922 static constexpr unsigned LDAPROpcodes[] = {
2923 AArch64::LDAPRB, AArch64::LDAPRH, AArch64::LDAPRW, AArch64::LDAPRX};
2924 static constexpr unsigned LDAROpcodes[] = {
2925 AArch64::LDARB, AArch64::LDARH, AArch64::LDARW, AArch64::LDARX};
2926 ArrayRef<unsigned> Opcodes =
2927 STI.hasRCPC() && Order != AtomicOrdering::SequentiallyConsistent
2928 ? LDAPROpcodes
2929 : LDAROpcodes;
2930 I.setDesc(TII.get(Opcodes[Log2_32(MemSizeInBytes)]));
2931 } else {
2932 static constexpr unsigned Opcodes[] = {AArch64::STLRB, AArch64::STLRH,
2933 AArch64::STLRW, AArch64::STLRX};
2934 Register ValReg = LdSt.getReg(0);
2935 if (MRI.getType(ValReg).getSizeInBits() == 64 && MemSizeInBits != 64) {
2936 // Emit a subreg copy of 32 bits.
2937 Register NewVal = MRI.createVirtualRegister(&AArch64::GPR32RegClass);
2938 MIB.buildInstr(TargetOpcode::COPY, {NewVal}, {})
2939 .addReg(I.getOperand(0).getReg(), {}, AArch64::sub_32);
2940 I.getOperand(0).setReg(NewVal);
2941 }
2942 I.setDesc(TII.get(Opcodes[Log2_32(MemSizeInBytes)]));
2943 }
2945 return true;
2946 }
2947
2948#ifndef NDEBUG
2949 const Register PtrReg = LdSt.getPointerReg();
2950 const RegisterBank &PtrRB = *RBI.getRegBank(PtrReg, MRI, TRI);
2951 // Check that the pointer register is valid.
2952 assert(PtrRB.getID() == AArch64::GPRRegBankID &&
2953 "Load/Store pointer operand isn't a GPR");
2954 assert(MRI.getType(PtrReg).isPointer() &&
2955 "Load/Store pointer operand isn't a pointer");
2956#endif
2957
2958 const Register ValReg = LdSt.getReg(0);
2959 const RegisterBank &RB = *RBI.getRegBank(ValReg, MRI, TRI);
2960 LLT ValTy = MRI.getType(ValReg);
2961
2962 // The code below doesn't support truncating stores, so we need to split it
2963 // again.
2964 if (isa<GStore>(LdSt) && ValTy.getSizeInBits() > MemSizeInBits &&
2965 RB.getID() == AArch64::FPRRegBankID) {
2966 unsigned SubReg;
2967 LLT MemTy = LdSt.getMMO().getMemoryType();
2968 auto *RC = getRegClassForTypeOnBank(MemTy, RB);
2969 if (!getSubRegForClass(RC, TRI, SubReg))
2970 return false;
2971
2972 // Generate a subreg copy.
2973 auto Copy = MIB.buildInstr(TargetOpcode::COPY, {MemTy}, {})
2974 .addReg(ValReg, {}, SubReg)
2975 .getReg(0);
2976 RBI.constrainGenericRegister(Copy, *RC, MRI);
2977 LdSt.getOperand(0).setReg(Copy);
2978 } else if (isa<GLoad>(LdSt) && ValTy.getSizeInBits() > MemSizeInBits) {
2979 // If this is an any-extending load from the FPR bank, split it into a regular
2980 // load + extend.
2981 if (RB.getID() == AArch64::FPRRegBankID) {
2982 unsigned SubReg;
2983 LLT MemTy = LdSt.getMMO().getMemoryType();
2984 auto *RC = getRegClassForTypeOnBank(MemTy, RB);
2985 if (!getSubRegForClass(RC, TRI, SubReg))
2986 return false;
2987 Register OldDst = LdSt.getReg(0);
2988 Register NewDst =
2990 LdSt.getOperand(0).setReg(NewDst);
2991 MRI.setRegBank(NewDst, RB);
2992 // Generate a SUBREG_TO_REG to extend it.
2993 MIB.setInsertPt(MIB.getMBB(), std::next(LdSt.getIterator()));
2994 MIB.buildInstr(AArch64::SUBREG_TO_REG, {OldDst}, {})
2995 .addUse(NewDst)
2996 .addImm(SubReg);
2997 auto SubRegRC = getRegClassForTypeOnBank(MRI.getType(OldDst), RB);
2998 RBI.constrainGenericRegister(OldDst, *SubRegRC, MRI);
2999 MIB.setInstr(LdSt);
3000 ValTy = MemTy; // This is no longer an extending load.
3001 }
3002 }
3003
3004 // Helper lambda for partially selecting I. Either returns the original
3005 // instruction with an updated opcode, or a new instruction.
3006 auto SelectLoadStoreAddressingMode = [&]() -> MachineInstr * {
3007 bool IsStore = isa<GStore>(I);
3008 const unsigned NewOpc =
3009 selectLoadStoreUIOp(I.getOpcode(), RB.getID(), MemSizeInBits);
3010 if (NewOpc == I.getOpcode())
3011 return nullptr;
3012 // Check if we can fold anything into the addressing mode.
3013 auto AddrModeFns =
3014 selectAddrModeIndexed(I.getOperand(1), MemSizeInBytes);
3015 if (!AddrModeFns) {
3016 // Can't fold anything. Use the original instruction.
3017 I.setDesc(TII.get(NewOpc));
3018 I.addOperand(MachineOperand::CreateImm(0));
3019 return &I;
3020 }
3021
3022 // Folded something. Create a new instruction and return it.
3023 auto NewInst = MIB.buildInstr(NewOpc, {}, {}, I.getFlags());
3024 Register CurValReg = I.getOperand(0).getReg();
3025 IsStore ? NewInst.addUse(CurValReg) : NewInst.addDef(CurValReg);
3026 NewInst.cloneMemRefs(I);
3027 for (auto &Fn : *AddrModeFns)
3028 Fn(NewInst);
3029 I.eraseFromParent();
3030 return &*NewInst;
3031 };
3032
3033 MachineInstr *LoadStore = SelectLoadStoreAddressingMode();
3034 if (!LoadStore)
3035 return false;
3036
3037 // If we're storing a 0, use WZR/XZR.
3038 if (Opcode == TargetOpcode::G_STORE) {
3040 LoadStore->getOperand(0).getReg(), MRI);
3041 if (CVal && CVal->Value == 0) {
3042 switch (LoadStore->getOpcode()) {
3043 case AArch64::STRWui:
3044 case AArch64::STRHHui:
3045 case AArch64::STRBBui:
3046 LoadStore->getOperand(0).setReg(AArch64::WZR);
3047 break;
3048 case AArch64::STRXui:
3049 LoadStore->getOperand(0).setReg(AArch64::XZR);
3050 break;
3051 }
3052 }
3053 }
3054
3055 if (IsZExtLoad || (Opcode == TargetOpcode::G_LOAD &&
3056 ValTy == LLT::scalar(64) && MemSizeInBits == 32)) {
3057 // The any/zextload from a smaller type to i32 should be handled by the
3058 // importer.
3059 if (MRI.getType(LoadStore->getOperand(0).getReg()).getSizeInBits() != 64)
3060 return false;
3061 // If we have an extending load then change the load's type to be a
3062 // narrower reg and zero_extend with SUBREG_TO_REG.
3063 Register LdReg = MRI.createVirtualRegister(&AArch64::GPR32RegClass);
3064 Register DstReg = LoadStore->getOperand(0).getReg();
3065 LoadStore->getOperand(0).setReg(LdReg);
3066
3067 MIB.setInsertPt(MIB.getMBB(), std::next(LoadStore->getIterator()));
3068 MIB.buildInstr(AArch64::SUBREG_TO_REG, {DstReg}, {})
3069 .addUse(LdReg)
3070 .addImm(AArch64::sub_32);
3071 constrainSelectedInstRegOperands(*LoadStore, TII, TRI, RBI);
3072 return RBI.constrainGenericRegister(DstReg, AArch64::GPR64allRegClass,
3073 MRI);
3074 }
3075 constrainSelectedInstRegOperands(*LoadStore, TII, TRI, RBI);
3076 return true;
3077 }
3078
3079 case TargetOpcode::G_INDEXED_ZEXTLOAD:
3080 case TargetOpcode::G_INDEXED_SEXTLOAD:
3081 return selectIndexedExtLoad(I, MRI);
3082 case TargetOpcode::G_INDEXED_LOAD:
3083 return selectIndexedLoad(I, MRI);
3084 case TargetOpcode::G_INDEXED_STORE:
3085 return selectIndexedStore(cast<GIndexedStore>(I), MRI);
3086
3087 case TargetOpcode::G_LSHR:
3088 case TargetOpcode::G_ASHR:
3089 if (MRI.getType(I.getOperand(0).getReg()).isVector())
3090 return selectVectorAshrLshr(I, MRI);
3091 [[fallthrough]];
3092 case TargetOpcode::G_SHL: {
3093 if (Opcode == TargetOpcode::G_SHL &&
3094 MRI.getType(I.getOperand(0).getReg()).isVector())
3095 return selectVectorSHL(I, MRI);
3096
3097 // These shifts were legalized to have 64 bit shift amounts because we
3098 // want to take advantage of the selection patterns that assume the
3099 // immediates are s64s, however, selectBinaryOp will assume both operands
3100 // will have the same bit size.
3101 {
3102 Register SrcReg = I.getOperand(1).getReg();
3103 Register ShiftReg = I.getOperand(2).getReg();
3104 const LLT ShiftTy = MRI.getType(ShiftReg);
3105 const LLT SrcTy = MRI.getType(SrcReg);
3106 if (!SrcTy.isVector() && SrcTy.getSizeInBits() == 32 &&
3107 ShiftTy.getSizeInBits() == 64) {
3108 assert(!ShiftTy.isVector() && "unexpected vector shift ty");
3109 // Insert a subregister copy to implement a 64->32 trunc
3110 auto Trunc = MIB.buildInstr(TargetOpcode::COPY, {SrcTy}, {})
3111 .addReg(ShiftReg, {}, AArch64::sub_32);
3112 MRI.setRegBank(Trunc.getReg(0), RBI.getRegBank(AArch64::GPRRegBankID));
3113 I.getOperand(2).setReg(Trunc.getReg(0));
3114 }
3115 }
3116
3117 const unsigned OpSize = Ty.getSizeInBits();
3118 const Register DefReg = I.getOperand(0).getReg();
3119 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
3120
3121 const unsigned NewOpc = selectBinaryOp(I.getOpcode(), RB.getID(), OpSize);
3122 if (NewOpc == I.getOpcode())
3123 return false;
3124
3125 I.setDesc(TII.get(NewOpc));
3126 // FIXME: Should the type be always reset in setDesc?
3127
3128 // Now that we selected an opcode, we need to constrain the register
3129 // operands to use appropriate classes.
3131 return true;
3132 }
3133 case TargetOpcode::G_PTR_ADD: {
3134 emitADD(I.getOperand(0).getReg(), I.getOperand(1), I.getOperand(2), MIB);
3135 I.eraseFromParent();
3136 return true;
3137 }
3138
3139 case TargetOpcode::G_SADDE:
3140 case TargetOpcode::G_UADDE:
3141 case TargetOpcode::G_SSUBE:
3142 case TargetOpcode::G_USUBE:
3143 case TargetOpcode::G_SADDO:
3144 case TargetOpcode::G_UADDO:
3145 case TargetOpcode::G_SSUBO:
3146 case TargetOpcode::G_USUBO:
3147 return selectOverflowOp(I, MRI);
3148
3149 case TargetOpcode::G_PTRMASK: {
3150 Register MaskReg = I.getOperand(2).getReg();
3151 std::optional<int64_t> MaskVal = getIConstantVRegSExtVal(MaskReg, MRI);
3152 // TODO: Implement arbitrary cases
3153 if (!MaskVal || !isShiftedMask_64(*MaskVal))
3154 return false;
3155
3156 uint64_t Mask = *MaskVal;
3157 I.setDesc(TII.get(AArch64::ANDXri));
3158 I.getOperand(2).ChangeToImmediate(
3160
3162 return true;
3163 }
3164 case TargetOpcode::G_PTRTOINT:
3165 case TargetOpcode::G_TRUNC: {
3166 const LLT DstTy = MRI.getType(I.getOperand(0).getReg());
3167 const LLT SrcTy = MRI.getType(I.getOperand(1).getReg());
3168
3169 const Register DstReg = I.getOperand(0).getReg();
3170 const Register SrcReg = I.getOperand(1).getReg();
3171
3172 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
3173 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
3174
3175 if (DstRB.getID() != SrcRB.getID()) {
3176 LLVM_DEBUG(
3177 dbgs() << "G_TRUNC/G_PTRTOINT input/output on different banks\n");
3178 return false;
3179 }
3180
3181 if (DstRB.getID() == AArch64::GPRRegBankID) {
3182 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(DstTy, DstRB);
3183 if (!DstRC)
3184 return false;
3185
3186 const TargetRegisterClass *SrcRC = getRegClassForTypeOnBank(SrcTy, SrcRB);
3187 if (!SrcRC)
3188 return false;
3189
3190 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
3191 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
3192 LLVM_DEBUG(dbgs() << "Failed to constrain G_TRUNC/G_PTRTOINT\n");
3193 return false;
3194 }
3195
3196 if (DstRC == SrcRC) {
3197 // Nothing to be done
3198 } else if (Opcode == TargetOpcode::G_TRUNC && DstTy == LLT::scalar(32) &&
3199 SrcTy == LLT::scalar(64)) {
3200 llvm_unreachable("TableGen can import this case");
3201 return false;
3202 } else if (DstRC == &AArch64::GPR32RegClass &&
3203 SrcRC == &AArch64::GPR64RegClass) {
3204 I.getOperand(1).setSubReg(AArch64::sub_32);
3205 } else {
3206 LLVM_DEBUG(
3207 dbgs() << "Unhandled mismatched classes in G_TRUNC/G_PTRTOINT\n");
3208 return false;
3209 }
3210
3211 I.setDesc(TII.get(TargetOpcode::COPY));
3212 return true;
3213 } else if (DstRB.getID() == AArch64::FPRRegBankID) {
3214 if (DstTy == LLT::fixed_vector(4, 16) &&
3215 SrcTy == LLT::fixed_vector(4, 32)) {
3216 I.setDesc(TII.get(AArch64::XTNv4i16));
3218 return true;
3219 }
3220
3221 if (!SrcTy.isVector() && SrcTy.getSizeInBits() == 128) {
3222 MachineInstr *Extract = emitExtractVectorElt(
3223 DstReg, DstRB, LLT::scalar(DstTy.getSizeInBits()), SrcReg, 0, MIB);
3224 if (!Extract)
3225 return false;
3226 I.eraseFromParent();
3227 return true;
3228 }
3229
3230 // We might have a vector G_PTRTOINT, in which case just emit a COPY.
3231 if (Opcode == TargetOpcode::G_PTRTOINT) {
3232 assert(DstTy.isVector() && "Expected an FPR ptrtoint to be a vector");
3233 I.setDesc(TII.get(TargetOpcode::COPY));
3234 return selectCopy(I, TII, MRI, TRI, RBI);
3235 }
3236 }
3237
3238 return false;
3239 }
3240
3241 case TargetOpcode::G_ANYEXT: {
3242 if (selectUSMovFromExtend(I, MRI))
3243 return true;
3244
3245 const Register DstReg = I.getOperand(0).getReg();
3246 const Register SrcReg = I.getOperand(1).getReg();
3247
3248 const RegisterBank &RBDst = *RBI.getRegBank(DstReg, MRI, TRI);
3249 if (RBDst.getID() != AArch64::GPRRegBankID) {
3250 LLVM_DEBUG(dbgs() << "G_ANYEXT on bank: " << RBDst
3251 << ", expected: GPR\n");
3252 return false;
3253 }
3254
3255 const RegisterBank &RBSrc = *RBI.getRegBank(SrcReg, MRI, TRI);
3256 if (RBSrc.getID() != AArch64::GPRRegBankID) {
3257 LLVM_DEBUG(dbgs() << "G_ANYEXT on bank: " << RBSrc
3258 << ", expected: GPR\n");
3259 return false;
3260 }
3261
3262 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
3263
3264 if (DstSize == 0) {
3265 LLVM_DEBUG(dbgs() << "G_ANYEXT operand has no size, not a gvreg?\n");
3266 return false;
3267 }
3268
3269 if (DstSize != 64 && DstSize > 32) {
3270 LLVM_DEBUG(dbgs() << "G_ANYEXT to size: " << DstSize
3271 << ", expected: 32 or 64\n");
3272 return false;
3273 }
3274 // At this point G_ANYEXT is just like a plain COPY, but we need
3275 // to explicitly form the 64-bit value if any.
3276 if (DstSize > 32) {
3277 Register ExtSrc = MRI.createVirtualRegister(&AArch64::GPR64allRegClass);
3278 BuildMI(MBB, I, I.getDebugLoc(), TII.get(AArch64::SUBREG_TO_REG))
3279 .addDef(ExtSrc)
3280 .addUse(SrcReg)
3281 .addImm(AArch64::sub_32);
3282 I.getOperand(1).setReg(ExtSrc);
3283 }
3284 return selectCopy(I, TII, MRI, TRI, RBI);
3285 }
3286
3287 case TargetOpcode::G_ZEXT:
3288 case TargetOpcode::G_SEXT_INREG:
3289 case TargetOpcode::G_SEXT: {
3290 if (selectUSMovFromExtend(I, MRI))
3291 return true;
3292
3293 unsigned Opcode = I.getOpcode();
3294 const bool IsSigned = Opcode != TargetOpcode::G_ZEXT;
3295 const Register DefReg = I.getOperand(0).getReg();
3296 Register SrcReg = I.getOperand(1).getReg();
3297 const LLT DstTy = MRI.getType(DefReg);
3298 const LLT SrcTy = MRI.getType(SrcReg);
3299 unsigned DstSize = DstTy.getSizeInBits();
3300 unsigned SrcSize = SrcTy.getSizeInBits();
3301
3302 // SEXT_INREG has the same src reg size as dst, the size of the value to be
3303 // extended is encoded in the imm.
3304 if (Opcode == TargetOpcode::G_SEXT_INREG)
3305 SrcSize = I.getOperand(2).getImm();
3306
3307 if (DstTy.isVector())
3308 return false; // Should be handled by imported patterns.
3309
3310 assert((*RBI.getRegBank(DefReg, MRI, TRI)).getID() ==
3311 AArch64::GPRRegBankID &&
3312 "Unexpected ext regbank");
3313
3314 MachineInstr *ExtI;
3315
3316 // First check if we're extending the result of a load which has a dest type
3317 // smaller than 32 bits, then this zext is redundant. GPR32 is the smallest
3318 // GPR register on AArch64 and all loads which are smaller automatically
3319 // zero-extend the upper bits. E.g.
3320 // %v(s8) = G_LOAD %p, :: (load 1)
3321 // %v2(s32) = G_ZEXT %v(s8)
3322 if (!IsSigned) {
3323 auto *LoadMI = getOpcodeDef(TargetOpcode::G_LOAD, SrcReg, MRI);
3324 bool IsGPR =
3325 RBI.getRegBank(SrcReg, MRI, TRI)->getID() == AArch64::GPRRegBankID;
3326 if (LoadMI && IsGPR) {
3327 const MachineMemOperand *MemOp = *LoadMI->memoperands_begin();
3328 unsigned BytesLoaded = MemOp->getSize().getValue();
3329 if (BytesLoaded < 4 && SrcTy.getSizeInBytes() == BytesLoaded)
3330 return selectCopy(I, TII, MRI, TRI, RBI);
3331 }
3332
3333 // For the 32-bit -> 64-bit case, we can emit a mov (ORRWrs)
3334 // + SUBREG_TO_REG.
3335 if (IsGPR && SrcSize == 32 && DstSize == 64) {
3336 Register SubregToRegSrc =
3337 MRI.createVirtualRegister(&AArch64::GPR32RegClass);
3338 const Register ZReg = AArch64::WZR;
3339 MIB.buildInstr(AArch64::ORRWrs, {SubregToRegSrc}, {ZReg, SrcReg})
3340 .addImm(0);
3341
3342 MIB.buildInstr(AArch64::SUBREG_TO_REG, {DefReg}, {})
3343 .addUse(SubregToRegSrc)
3344 .addImm(AArch64::sub_32);
3345
3346 if (!RBI.constrainGenericRegister(DefReg, AArch64::GPR64RegClass,
3347 MRI)) {
3348 LLVM_DEBUG(dbgs() << "Failed to constrain G_ZEXT destination\n");
3349 return false;
3350 }
3351
3352 if (!RBI.constrainGenericRegister(SrcReg, AArch64::GPR32RegClass,
3353 MRI)) {
3354 LLVM_DEBUG(dbgs() << "Failed to constrain G_ZEXT source\n");
3355 return false;
3356 }
3357
3358 I.eraseFromParent();
3359 return true;
3360 }
3361 }
3362
3363 if (DstSize == 64) {
3364 if (Opcode != TargetOpcode::G_SEXT_INREG) {
3365 // FIXME: Can we avoid manually doing this?
3366 if (!RBI.constrainGenericRegister(SrcReg, AArch64::GPR32RegClass,
3367 MRI)) {
3368 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(Opcode)
3369 << " operand\n");
3370 return false;
3371 }
3372 SrcReg = MIB.buildInstr(AArch64::SUBREG_TO_REG,
3373 {&AArch64::GPR64RegClass}, {})
3374 .addUse(SrcReg)
3375 .addImm(AArch64::sub_32)
3376 .getReg(0);
3377 }
3378
3379 ExtI = MIB.buildInstr(IsSigned ? AArch64::SBFMXri : AArch64::UBFMXri,
3380 {DefReg}, {SrcReg})
3381 .addImm(0)
3382 .addImm(SrcSize - 1);
3383 } else if (DstSize <= 32) {
3384 ExtI = MIB.buildInstr(IsSigned ? AArch64::SBFMWri : AArch64::UBFMWri,
3385 {DefReg}, {SrcReg})
3386 .addImm(0)
3387 .addImm(SrcSize - 1);
3388 } else {
3389 return false;
3390 }
3391
3393 I.eraseFromParent();
3394 return true;
3395 }
3396
3397 case TargetOpcode::G_FREEZE:
3398 return selectCopy(I, TII, MRI, TRI, RBI);
3399
3400 case TargetOpcode::G_INTTOPTR:
3401 // The importer is currently unable to import pointer types since they
3402 // didn't exist in SelectionDAG.
3403 return selectCopy(I, TII, MRI, TRI, RBI);
3404
3405 case TargetOpcode::G_BITCAST:
3406 // Imported SelectionDAG rules can handle every bitcast except those that
3407 // bitcast from a type to the same type. Ideally, these shouldn't occur
3408 // but we might not run an optimizer that deletes them. The other exception
3409 // is bitcasts involving pointer types, as SelectionDAG has no knowledge
3410 // of them.
3411 return selectCopy(I, TII, MRI, TRI, RBI);
3412
3413 case TargetOpcode::G_SELECT: {
3414 auto &Sel = cast<GSelect>(I);
3415 const Register CondReg = Sel.getCondReg();
3416 const Register TReg = Sel.getTrueReg();
3417 const Register FReg = Sel.getFalseReg();
3418
3419 if (tryOptSelect(Sel))
3420 return true;
3421
3422 // Make sure to use an unused vreg instead of wzr, so that the peephole
3423 // optimizations will be able to optimize these.
3424 Register DeadVReg = MRI.createVirtualRegister(&AArch64::GPR32RegClass);
3425 auto TstMI = MIB.buildInstr(AArch64::ANDSWri, {DeadVReg}, {CondReg})
3426 .addImm(AArch64_AM::encodeLogicalImmediate(1, 32));
3428 if (!emitSelect(Sel.getReg(0), TReg, FReg, AArch64CC::NE, MIB))
3429 return false;
3430 Sel.eraseFromParent();
3431 return true;
3432 }
3433 case TargetOpcode::G_ICMP: {
3434 if (Ty.isVector())
3435 return false;
3436
3437 if (Ty != LLT::scalar(32)) {
3438 LLVM_DEBUG(dbgs() << "G_ICMP result has type: " << Ty
3439 << ", expected: " << LLT::scalar(32) << '\n');
3440 return false;
3441 }
3442
3443 auto &PredOp = I.getOperand(1);
3444 emitIntegerCompare(I.getOperand(2), I.getOperand(3), PredOp, MIB);
3445 auto Pred = static_cast<CmpInst::Predicate>(PredOp.getPredicate());
3447 CmpInst::getInversePredicate(Pred), I.getOperand(3).getReg(), &MRI);
3448 emitCSINC(/*Dst=*/I.getOperand(0).getReg(), /*Src1=*/AArch64::WZR,
3449 /*Src2=*/AArch64::WZR, InvCC, MIB);
3450 I.eraseFromParent();
3451 return true;
3452 }
3453
3454 case TargetOpcode::G_FCMP: {
3456 static_cast<CmpInst::Predicate>(I.getOperand(1).getPredicate());
3457 if (!emitFPCompare(I.getOperand(2).getReg(), I.getOperand(3).getReg(), MIB,
3458 Pred) ||
3459 !emitCSetForFCmp(I.getOperand(0).getReg(), Pred, MIB))
3460 return false;
3461 I.eraseFromParent();
3462 return true;
3463 }
3464 case TargetOpcode::G_VASTART:
3465 return STI.isTargetDarwin() ? selectVaStartDarwin(I, MF, MRI)
3466 : selectVaStartAAPCS(I, MF, MRI);
3467 case TargetOpcode::G_INTRINSIC:
3468 return selectIntrinsic(I, MRI);
3469 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
3470 return selectIntrinsicWithSideEffects(I, MRI);
3471 case TargetOpcode::G_IMPLICIT_DEF: {
3472 I.setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
3473 const LLT DstTy = MRI.getType(I.getOperand(0).getReg());
3474 const Register DstReg = I.getOperand(0).getReg();
3475 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
3476 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(DstTy, DstRB);
3477 RBI.constrainGenericRegister(DstReg, *DstRC, MRI);
3478 return true;
3479 }
3480 case TargetOpcode::G_BLOCK_ADDR: {
3481 Function *BAFn = I.getOperand(1).getBlockAddress()->getFunction();
3482 if (std::optional<uint16_t> BADisc =
3484 MIB.buildInstr(AArch64::MOVaddrPAC)
3485 .addBlockAddress(I.getOperand(1).getBlockAddress())
3487 .addReg(/*AddrDisc=*/AArch64::XZR)
3488 .addImm(*BADisc)
3489 .constrainAllUses(TII, TRI, RBI);
3490 MIB.buildCopy(I.getOperand(0).getReg(), Register(AArch64::X16));
3491 RBI.constrainGenericRegister(I.getOperand(0).getReg(),
3492 AArch64::GPR64RegClass, MRI);
3493 I.eraseFromParent();
3494 return true;
3495 }
3497 materializeLargeCMVal(I, I.getOperand(1).getBlockAddress(), 0);
3498 I.eraseFromParent();
3499 return true;
3500 } else {
3501 I.setDesc(TII.get(AArch64::MOVaddrBA));
3502 auto MovMI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(AArch64::MOVaddrBA),
3503 I.getOperand(0).getReg())
3504 .addBlockAddress(I.getOperand(1).getBlockAddress(),
3505 /* Offset */ 0, AArch64II::MO_PAGE)
3507 I.getOperand(1).getBlockAddress(), /* Offset */ 0,
3509 I.eraseFromParent();
3511 return true;
3512 }
3513 }
3514 case TargetOpcode::G_BUILD_VECTOR:
3515 return selectBuildVector(I, MRI);
3516 case TargetOpcode::G_MERGE_VALUES:
3517 return selectMergeValues(I, MRI);
3518 case TargetOpcode::G_UNMERGE_VALUES:
3519 return selectUnmergeValues(I, MRI);
3520 case TargetOpcode::G_SHUFFLE_VECTOR:
3521 return selectShuffleVector(I, MRI);
3522 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
3523 return selectExtractElt(I, MRI);
3524 case TargetOpcode::G_CONCAT_VECTORS:
3525 return selectConcatVectors(I, MRI);
3526 case TargetOpcode::G_JUMP_TABLE:
3527 return selectJumpTable(I, MRI);
3528 case TargetOpcode::G_MEMCPY:
3529 case TargetOpcode::G_MEMCPY_INLINE:
3530 case TargetOpcode::G_MEMMOVE:
3531 case TargetOpcode::G_MEMSET:
3532 case TargetOpcode::G_MEMSET_INLINE:
3533 assert(STI.hasMOPS() && "Shouldn't get here without +mops feature");
3534 return selectMOPS(I, MRI);
3535 }
3536
3537 return false;
3538}
3539
3540bool AArch64InstructionSelector::selectAndRestoreState(MachineInstr &I) {
3541 MachineIRBuilderState OldMIBState = MIB.getState();
3542 bool Success = select(I);
3543 MIB.setState(OldMIBState);
3544 return Success;
3545}
3546
3547bool AArch64InstructionSelector::selectMOPS(MachineInstr &GI,
3548 MachineRegisterInfo &MRI) {
3549 unsigned Mopcode;
3550 switch (GI.getOpcode()) {
3551 case TargetOpcode::G_MEMCPY:
3552 case TargetOpcode::G_MEMCPY_INLINE:
3553 Mopcode = AArch64::MOPSMemoryCopyPseudo;
3554 break;
3555 case TargetOpcode::G_MEMMOVE:
3556 Mopcode = AArch64::MOPSMemoryMovePseudo;
3557 break;
3558 case TargetOpcode::G_MEMSET:
3559 case TargetOpcode::G_MEMSET_INLINE:
3560 // For tagged memset see llvm.aarch64.mops.memset.tag
3561 Mopcode = AArch64::MOPSMemorySetPseudo;
3562 break;
3563 }
3564
3565 auto &DstPtr = GI.getOperand(0);
3566 auto &SrcOrVal = GI.getOperand(1);
3567 auto &Size = GI.getOperand(2);
3568
3569 // Create copies of the registers that can be clobbered.
3570 const Register DstPtrCopy = MRI.cloneVirtualRegister(DstPtr.getReg());
3571 const Register SrcValCopy = MRI.cloneVirtualRegister(SrcOrVal.getReg());
3572 const Register SizeCopy = MRI.cloneVirtualRegister(Size.getReg());
3573
3574 const bool IsSet = Mopcode == AArch64::MOPSMemorySetPseudo;
3575 const auto &SrcValRegClass =
3576 IsSet ? AArch64::GPR64RegClass : AArch64::GPR64commonRegClass;
3577
3578 // Constrain to specific registers
3579 RBI.constrainGenericRegister(DstPtrCopy, AArch64::GPR64commonRegClass, MRI);
3580 RBI.constrainGenericRegister(SrcValCopy, SrcValRegClass, MRI);
3581 RBI.constrainGenericRegister(SizeCopy, AArch64::GPR64RegClass, MRI);
3582
3583 MIB.buildCopy(DstPtrCopy, DstPtr);
3584 MIB.buildCopy(SrcValCopy, SrcOrVal);
3585 MIB.buildCopy(SizeCopy, Size);
3586
3587 // New instruction uses the copied registers because it must update them.
3588 // The defs are not used since they don't exist in G_MEM*. They are still
3589 // tied.
3590 // Note: order of operands is different from G_MEMSET, G_MEMCPY, G_MEMMOVE
3591 Register DefDstPtr = MRI.createVirtualRegister(&AArch64::GPR64commonRegClass);
3592 Register DefSize = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3593 if (IsSet) {
3594 MIB.buildInstr(Mopcode, {DefDstPtr, DefSize},
3595 {DstPtrCopy, SizeCopy, SrcValCopy})
3596 .setOperandDead(5); // implicit-def $nzcv
3597 } else {
3598 Register DefSrcPtr = MRI.createVirtualRegister(&SrcValRegClass);
3599 MIB.buildInstr(Mopcode, {DefDstPtr, DefSrcPtr, DefSize},
3600 {DstPtrCopy, SrcValCopy, SizeCopy})
3601 .setOperandDead(6); // implicit-def $nzcv
3602 }
3603
3604 GI.eraseFromParent();
3605 return true;
3606}
3607
3608bool AArch64InstructionSelector::selectBrJT(MachineInstr &I,
3609 MachineRegisterInfo &MRI) {
3610 assert(I.getOpcode() == TargetOpcode::G_BRJT && "Expected G_BRJT");
3611 Register JTAddr = I.getOperand(0).getReg();
3612 unsigned JTI = I.getOperand(1).getIndex();
3613 Register Index = I.getOperand(2).getReg();
3614
3615 MF->getInfo<AArch64FunctionInfo>()->setJumpTableEntryInfo(JTI, 4, nullptr);
3616
3617 // With aarch64-jump-table-hardening, we only expand the jump table dispatch
3618 // sequence later, to guarantee the integrity of the intermediate values.
3619 if (MF->getFunction().hasFnAttribute("aarch64-jump-table-hardening")) {
3621 if (STI.isTargetMachO()) {
3622 if (CM != CodeModel::Small && CM != CodeModel::Large)
3623 report_fatal_error("Unsupported code-model for hardened jump-table");
3624 } else {
3625 // Note that COFF support would likely also need JUMP_TABLE_DEBUG_INFO.
3626 assert(STI.isTargetELF() &&
3627 "jump table hardening only supported on MachO/ELF");
3628 if (CM != CodeModel::Small)
3629 report_fatal_error("Unsupported code-model for hardened jump-table");
3630 }
3631
3632 MIB.buildCopy({AArch64::X16}, I.getOperand(2).getReg());
3633 MIB.buildInstr(AArch64::BR_JumpTable)
3634 .addJumpTableIndex(I.getOperand(1).getIndex());
3635 I.eraseFromParent();
3636 return true;
3637 }
3638
3639 Register TargetReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3640 Register ScratchReg = MRI.createVirtualRegister(&AArch64::GPR64spRegClass);
3641
3642 auto JumpTableInst = MIB.buildInstr(AArch64::JumpTableDest32,
3643 {TargetReg, ScratchReg}, {JTAddr, Index})
3644 .addJumpTableIndex(JTI);
3645 // Save the jump table info.
3646 MIB.buildInstr(TargetOpcode::JUMP_TABLE_DEBUG_INFO, {},
3647 {static_cast<int64_t>(JTI)});
3648 // Build the indirect branch.
3649 MIB.buildInstr(AArch64::BR, {}, {TargetReg});
3650 I.eraseFromParent();
3651 constrainSelectedInstRegOperands(*JumpTableInst, TII, TRI, RBI);
3652 return true;
3653}
3654
3655bool AArch64InstructionSelector::selectJumpTable(MachineInstr &I,
3656 MachineRegisterInfo &MRI) {
3657 assert(I.getOpcode() == TargetOpcode::G_JUMP_TABLE && "Expected jump table");
3658 assert(I.getOperand(1).isJTI() && "Jump table op should have a JTI!");
3659
3660 Register DstReg = I.getOperand(0).getReg();
3661 unsigned JTI = I.getOperand(1).getIndex();
3662 // We generate a MOVaddrJT which will get expanded to an ADRP + ADD later.
3663 auto MovMI =
3664 MIB.buildInstr(AArch64::MOVaddrJT, {DstReg}, {})
3665 .addJumpTableIndex(JTI, AArch64II::MO_PAGE)
3667 I.eraseFromParent();
3669 return true;
3670}
3671
3672bool AArch64InstructionSelector::selectTLSLocalExecELF(
3673 const GlobalValue *GV, MachineInstr &I, MachineRegisterInfo &MRI) {
3674 auto ConstrainRegOps = [&](MachineInstrBuilder MIB) {
3676 };
3678 ConstrainRegOps(MIB.buildInstr(AArch64::MOVbaseTLS, {ThreadBase}, {}));
3679
3680 switch (MF->getTarget().Options.TLSSize) {
3681 default:
3682 llvm_unreachable("Unexpected TLS size");
3683 case 12: {
3684 // add x0, x0, :tprel_lo12:a
3685 ConstrainRegOps(
3686 MIB.buildInstr(AArch64::ADDXri, {I.getOperand(0).getReg()},
3687 {ThreadBase})
3689 .addImm(0));
3690 break;
3691 }
3692 case 24: {
3693 // add x0, x0, :tprel_hi12:a
3694 // add x0, x0, :tprel_lo12_nc:a
3695 Register Addr = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3696 ConstrainRegOps(
3697 MIB.buildInstr(AArch64::ADDXri, {Addr}, {ThreadBase})
3699 .addImm(0));
3700 ConstrainRegOps(
3701 MIB.buildInstr(AArch64::ADDXri, {I.getOperand(0).getReg()}, {Addr})
3702 .addGlobalAddress(GV, 0,
3705 .addImm(0));
3706 break;
3707 }
3708 case 32: {
3709 // movz x0, #:tprel_g1:a
3710 // movk x0, #:tprel_g0_nc:a
3711 // add x0, x1, x0
3712 Register Addr = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3713 ConstrainRegOps(
3714 MIB.buildInstr(AArch64::MOVZXi, {Addr}, {})
3716 .addImm(16));
3717 Register Addr2 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3718 ConstrainRegOps(MIB.buildInstr(AArch64::MOVKXi, {Addr2}, {Addr})
3719 .addGlobalAddress(GV, 0,
3722 .addImm(0));
3723 ConstrainRegOps(MIB.buildInstr(AArch64::ADDXrr, {I.getOperand(0).getReg()},
3724 {ThreadBase, Addr2}));
3725 break;
3726 }
3727 case 48: {
3728 // movz x0, #:tprel_g2:a
3729 // movk x0, #:tprel_g1_nc:a
3730 // movk x0, #:tprel_g0_nc:a
3731 // add x0, x1, x0
3732 Register Addr = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3733 ConstrainRegOps(
3734 MIB.buildInstr(AArch64::MOVZXi, {Addr}, {})
3736 .addImm(32));
3737 Register Addr2 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3738 ConstrainRegOps(MIB.buildInstr(AArch64::MOVKXi, {Addr2}, {Addr})
3739 .addGlobalAddress(GV, 0,
3742 .addImm(16));
3743 Register Addr3 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3744 ConstrainRegOps(MIB.buildInstr(AArch64::MOVKXi, {Addr3}, {Addr2})
3745 .addGlobalAddress(GV, 0,
3748 .addImm(0));
3749 ConstrainRegOps(MIB.buildInstr(AArch64::ADDXrr, {I.getOperand(0).getReg()},
3750 {ThreadBase, Addr3}));
3751 break;
3752 }
3753 }
3754 I.eraseFromParent();
3755 return true;
3756}
3757
3758// TLS lowering below mirrors the corresponding DAGISel implementation.
3759// See LowerELFTLSModel() for details.
3760bool AArch64InstructionSelector::selectTLSGlobalValueELF(
3761 MachineInstr &I, MachineRegisterInfo &MRI) {
3762 const GlobalValue *GV = I.getOperand(1).getGlobal();
3763 auto *FuncInfo = MF->getInfo<AArch64FunctionInfo>();
3765 AArch64::getELFTLSModel(GV, TM, FuncInfo->hasELFSignedGOT());
3766
3767 Register TPOff = MRI.createVirtualRegister(&AArch64::GPR64commonRegClass);
3768 switch (Model) {
3770 return selectTLSLocalExecELF(GV, I, MRI);
3772 MIB.buildInstr(AArch64::LOADgot, {TPOff}, {})
3773 .addGlobalAddress(GV, 0, AArch64II::MO_TLS);
3774 break;
3777#ifndef NDEBUG
3778 SMEAttrs Attrs = MF->getInfo<AArch64FunctionInfo>()->getSMEFnAttrs();
3779 assert(!Attrs.hasZAState() && !Attrs.hasStreamingInterfaceOrBody() &&
3780 !Attrs.hasStreamingCompatibleInterface() &&
3781 "unsupported SME features reached GlobalISel TLS lowering");
3782#endif
3783 unsigned Opcode = FuncInfo->hasELFSignedGOT()
3784 ? AArch64::TLSDESC_AUTH_CALLSEQ
3785 : AArch64::TLSDESC_CALLSEQ;
3786
3787 if (TLSModel::GeneralDynamic == Model) {
3788 MIB.buildInstr(Opcode, {}, {}).addGlobalAddress(GV, 0, AArch64II::MO_TLS);
3789 MIB.buildCopy(TPOff, Register(AArch64::X0));
3790 break;
3791 }
3793 // These accesses will need deduplicating if there's more than one.
3795
3796 MIB.buildInstr(Opcode, {}, {})
3797 .addExternalSymbol("_TLS_MODULE_BASE_", AArch64II::MO_TLS);
3798 auto Copy = MIB.buildCopy(LLT::scalar(64), Register(AArch64::X0));
3799 auto Add1 =
3800 MIB.buildInstr(AArch64::ADDXri, {LLT::scalar(64)}, {Copy.getReg(0)})
3801 .addGlobalAddress(GV, 0, AArch64II::MO_TLS | AArch64II::MO_HI12)
3802 .addImm(0);
3803 auto Add2 =
3804 MIB.buildInstr(AArch64::ADDXri, {TPOff}, {Add1.getReg(0)})
3805 .addGlobalAddress(GV, 0,
3808 .addImm(0);
3811 }
3812 }
3814 MIB.buildInstr(AArch64::MOVbaseTLS, {ThreadBase}, {});
3815 auto Add = MIB.buildInstr(AArch64::ADDXrr, {I.getOperand(0).getReg()},
3816 {ThreadBase, TPOff});
3818
3819 I.eraseFromParent();
3820 return true;
3821}
3822
3823bool AArch64InstructionSelector::selectTLSGlobalValueMachO(
3824 MachineInstr &I, MachineRegisterInfo &MRI) {
3825 const auto &GlobalOp = I.getOperand(1);
3826 assert(GlobalOp.getOffset() == 0 &&
3827 "Shouldn't have an offset on TLS globals!");
3828
3829 const GlobalValue &GV = *GlobalOp.getGlobal();
3830 MF->getFrameInfo().setAdjustsStack(true);
3831 auto LoadGOT =
3832 MIB.buildInstr(AArch64::LOADgot, {&AArch64::GPR64commonRegClass}, {})
3833 .addGlobalAddress(&GV, 0, AArch64II::MO_TLS);
3834
3835 auto Load = MIB.buildInstr(AArch64::LDRXui, {&AArch64::GPR64commonRegClass},
3836 {LoadGOT.getReg(0)})
3837 .addImm(0);
3838
3839 MIB.buildCopy(Register(AArch64::X0), LoadGOT.getReg(0));
3840 // TLS calls preserve all registers except those that absolutely must be
3841 // trashed: X0 (it takes an argument), LR (it's a call) and NZCV (let's not be
3842 // silly).
3843 unsigned Opcode = getBLRCallOpcode(*MF);
3844
3845 // With ptrauth-calls, the tlv access thunk pointer is authenticated (IA, 0).
3846 if (MF->getFunction().hasFnAttribute("ptrauth-calls")) {
3847 assert(Opcode == AArch64::BLR);
3848 Opcode = AArch64::BLRAAZ;
3849 }
3850
3851 MIB.buildInstr(Opcode, {}, {Load})
3852 .setOperandDead(1) // implicit-def $lr
3853 .addUse(AArch64::X0, RegState::Implicit)
3854 .addDef(AArch64::X0, RegState::Implicit)
3855 .addRegMask(TRI.getTLSCallPreservedMask());
3856
3857 MIB.buildCopy(I.getOperand(0).getReg(), Register(AArch64::X0));
3858 RBI.constrainGenericRegister(I.getOperand(0).getReg(), AArch64::GPR64RegClass,
3859 MRI);
3860 I.eraseFromParent();
3861 return true;
3862}
3863
3864bool AArch64InstructionSelector::selectTLSGlobalValue(
3865 MachineInstr &I, MachineRegisterInfo &MRI) {
3866 // We don't support instructions with emulated TLS variables yet.
3867 if (TM.useEmulatedTLS())
3868 return false;
3869
3870 if (STI.isTargetELF())
3871 return selectTLSGlobalValueELF(I, MRI);
3872
3873 if (STI.isTargetMachO())
3874 return selectTLSGlobalValueMachO(I, MRI);
3875
3876 return false;
3877}
3878
3879MachineInstr *AArch64InstructionSelector::emitScalarToVector(
3880 unsigned EltSize, const TargetRegisterClass *DstRC, Register Scalar,
3881 MachineIRBuilder &MIRBuilder) const {
3882 auto Undef = MIRBuilder.buildInstr(TargetOpcode::IMPLICIT_DEF, {DstRC}, {});
3883
3884 auto BuildFn = [&](unsigned SubregIndex) {
3885 auto Ins =
3886 MIRBuilder
3887 .buildInstr(TargetOpcode::INSERT_SUBREG, {DstRC}, {Undef, Scalar})
3888 .addImm(SubregIndex);
3891 return &*Ins;
3892 };
3893
3894 switch (EltSize) {
3895 case 8:
3896 return BuildFn(AArch64::bsub);
3897 case 16:
3898 return BuildFn(AArch64::hsub);
3899 case 32:
3900 return BuildFn(AArch64::ssub);
3901 case 64:
3902 return BuildFn(AArch64::dsub);
3903 default:
3904 return nullptr;
3905 }
3906}
3907
3908MachineInstr *
3909AArch64InstructionSelector::emitNarrowVector(Register DstReg, Register SrcReg,
3910 MachineIRBuilder &MIB,
3911 MachineRegisterInfo &MRI) const {
3912 LLT DstTy = MRI.getType(DstReg);
3913 const TargetRegisterClass *RC =
3914 getRegClassForTypeOnBank(DstTy, *RBI.getRegBank(SrcReg, MRI, TRI));
3915 if (RC != &AArch64::FPR32RegClass && RC != &AArch64::FPR64RegClass) {
3916 LLVM_DEBUG(dbgs() << "Unsupported register class!\n");
3917 return nullptr;
3918 }
3919 unsigned SubReg = 0;
3920 if (!getSubRegForClass(RC, TRI, SubReg))
3921 return nullptr;
3922 if (SubReg != AArch64::ssub && SubReg != AArch64::dsub) {
3923 LLVM_DEBUG(dbgs() << "Unsupported destination size! ("
3924 << DstTy.getSizeInBits() << "\n");
3925 return nullptr;
3926 }
3927 auto Copy = MIB.buildInstr(TargetOpcode::COPY, {DstReg}, {})
3928 .addReg(SrcReg, {}, SubReg);
3929 RBI.constrainGenericRegister(DstReg, *RC, MRI);
3930 return Copy;
3931}
3932
3933bool AArch64InstructionSelector::selectMergeValues(
3934 MachineInstr &I, MachineRegisterInfo &MRI) {
3935 assert(I.getOpcode() == TargetOpcode::G_MERGE_VALUES && "unexpected opcode");
3936 const LLT DstTy = MRI.getType(I.getOperand(0).getReg());
3937 const LLT SrcTy = MRI.getType(I.getOperand(1).getReg());
3938 assert(!DstTy.isVector() && !SrcTy.isVector() && "invalid merge operation");
3939 const RegisterBank &RB = *RBI.getRegBank(I.getOperand(1).getReg(), MRI, TRI);
3940
3941 if (I.getNumOperands() != 3)
3942 return false;
3943
3944 // Merging 2 s64s into an s128.
3945 if (DstTy == LLT::scalar(128)) {
3946 if (SrcTy.getSizeInBits() != 64)
3947 return false;
3948 Register DstReg = I.getOperand(0).getReg();
3949 Register Src1Reg = I.getOperand(1).getReg();
3950 Register Src2Reg = I.getOperand(2).getReg();
3951 auto Tmp = MIB.buildInstr(TargetOpcode::IMPLICIT_DEF, {DstTy}, {});
3952 MachineInstr *InsMI = emitLaneInsert(std::nullopt, Tmp.getReg(0), Src1Reg,
3953 /* LaneIdx */ 0, RB, MIB);
3954 if (!InsMI)
3955 return false;
3956 MachineInstr *Ins2MI = emitLaneInsert(DstReg, InsMI->getOperand(0).getReg(),
3957 Src2Reg, /* LaneIdx */ 1, RB, MIB);
3958 if (!Ins2MI)
3959 return false;
3962 I.eraseFromParent();
3963 return true;
3964 }
3965
3966 if (RB.getID() != AArch64::GPRRegBankID)
3967 return false;
3968
3969 if (DstTy.getSizeInBits() != 64 || SrcTy.getSizeInBits() != 32)
3970 return false;
3971
3972 auto *DstRC = &AArch64::GPR64RegClass;
3973 Register SubToRegDef = MRI.createVirtualRegister(DstRC);
3974 MachineInstr &SubRegMI = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
3975 TII.get(TargetOpcode::SUBREG_TO_REG))
3976 .addDef(SubToRegDef)
3977 .addUse(I.getOperand(1).getReg())
3978 .addImm(AArch64::sub_32);
3979 Register SubToRegDef2 = MRI.createVirtualRegister(DstRC);
3980 // Need to anyext the second scalar before we can use bfm
3981 MachineInstr &SubRegMI2 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
3982 TII.get(TargetOpcode::SUBREG_TO_REG))
3983 .addDef(SubToRegDef2)
3984 .addUse(I.getOperand(2).getReg())
3985 .addImm(AArch64::sub_32);
3986 MachineInstr &BFM =
3987 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AArch64::BFMXri))
3988 .addDef(I.getOperand(0).getReg())
3989 .addUse(SubToRegDef)
3990 .addUse(SubToRegDef2)
3991 .addImm(32)
3992 .addImm(31);
3993 constrainSelectedInstRegOperands(SubRegMI, TII, TRI, RBI);
3994 constrainSelectedInstRegOperands(SubRegMI2, TII, TRI, RBI);
3996 I.eraseFromParent();
3997 return true;
3998}
3999
4000static bool getLaneCopyOpcode(unsigned &CopyOpc, unsigned &ExtractSubReg,
4001 const unsigned EltSize) {
4002 // Choose a lane copy opcode and subregister based off of the size of the
4003 // vector's elements.
4004 switch (EltSize) {
4005 case 8:
4006 CopyOpc = AArch64::DUPi8;
4007 ExtractSubReg = AArch64::bsub;
4008 break;
4009 case 16:
4010 CopyOpc = AArch64::DUPi16;
4011 ExtractSubReg = AArch64::hsub;
4012 break;
4013 case 32:
4014 CopyOpc = AArch64::DUPi32;
4015 ExtractSubReg = AArch64::ssub;
4016 break;
4017 case 64:
4018 CopyOpc = AArch64::DUPi64;
4019 ExtractSubReg = AArch64::dsub;
4020 break;
4021 default:
4022 // Unknown size, bail out.
4023 LLVM_DEBUG(dbgs() << "Elt size '" << EltSize << "' unsupported.\n");
4024 return false;
4025 }
4026 return true;
4027}
4028
4029MachineInstr *AArch64InstructionSelector::emitExtractVectorElt(
4030 std::optional<Register> DstReg, const RegisterBank &DstRB, LLT ScalarTy,
4031 Register VecReg, unsigned LaneIdx, MachineIRBuilder &MIRBuilder) const {
4032 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
4033 unsigned CopyOpc = 0;
4034 unsigned ExtractSubReg = 0;
4035 if (!getLaneCopyOpcode(CopyOpc, ExtractSubReg, ScalarTy.getSizeInBits())) {
4036 LLVM_DEBUG(
4037 dbgs() << "Couldn't determine lane copy opcode for instruction.\n");
4038 return nullptr;
4039 }
4040
4041 const TargetRegisterClass *DstRC =
4042 getRegClassForTypeOnBank(ScalarTy, DstRB, true);
4043 if (!DstRC) {
4044 LLVM_DEBUG(dbgs() << "Could not determine destination register class.\n");
4045 return nullptr;
4046 }
4047
4048 const RegisterBank &VecRB = *RBI.getRegBank(VecReg, MRI, TRI);
4049 const LLT &VecTy = MRI.getType(VecReg);
4050 const TargetRegisterClass *VecRC =
4051 getRegClassForTypeOnBank(VecTy, VecRB, true);
4052 if (!VecRC) {
4053 LLVM_DEBUG(dbgs() << "Could not determine source register class.\n");
4054 return nullptr;
4055 }
4056
4057 // The register that we're going to copy into.
4058 Register InsertReg = VecReg;
4059 if (!DstReg)
4060 DstReg = MRI.createVirtualRegister(DstRC);
4061 // If the lane index is 0, we just use a subregister COPY.
4062 if (LaneIdx == 0) {
4063 auto Copy = MIRBuilder.buildInstr(TargetOpcode::COPY, {*DstReg}, {})
4064 .addReg(VecReg, {}, ExtractSubReg);
4065 RBI.constrainGenericRegister(*DstReg, *DstRC, MRI);
4066 return &*Copy;
4067 }
4068
4069 // Lane copies require 128-bit wide registers. If we're dealing with an
4070 // unpacked vector, then we need to move up to that width. Insert an implicit
4071 // def and a subregister insert to get us there.
4072 if (VecTy.getSizeInBits() != 128) {
4073 MachineInstr *ScalarToVector = emitScalarToVector(
4074 VecTy.getSizeInBits(), &AArch64::FPR128RegClass, VecReg, MIRBuilder);
4075 if (!ScalarToVector)
4076 return nullptr;
4077 InsertReg = ScalarToVector->getOperand(0).getReg();
4078 }
4079
4080 MachineInstr *LaneCopyMI =
4081 MIRBuilder.buildInstr(CopyOpc, {*DstReg}, {InsertReg}).addImm(LaneIdx);
4082 constrainSelectedInstRegOperands(*LaneCopyMI, TII, TRI, RBI);
4083
4084 // Make sure that we actually constrain the initial copy.
4085 RBI.constrainGenericRegister(*DstReg, *DstRC, MRI);
4086 return LaneCopyMI;
4087}
4088
4089bool AArch64InstructionSelector::selectExtractElt(
4090 MachineInstr &I, MachineRegisterInfo &MRI) {
4091 assert(I.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT &&
4092 "unexpected opcode!");
4093 Register DstReg = I.getOperand(0).getReg();
4094 const LLT NarrowTy = MRI.getType(DstReg);
4095 const Register SrcReg = I.getOperand(1).getReg();
4096 const LLT WideTy = MRI.getType(SrcReg);
4097 assert(WideTy.getSizeInBits() >= NarrowTy.getSizeInBits() &&
4098 "source register size too small!");
4099 assert(!NarrowTy.isVector() && "cannot extract vector into vector!");
4100
4101 // Need the lane index to determine the correct copy opcode.
4102 MachineOperand &LaneIdxOp = I.getOperand(2);
4103 assert(LaneIdxOp.isReg() && "Lane index operand was not a register?");
4104
4105 // Find the index to extract from.
4106 auto VRegAndVal = getIConstantVRegValWithLookThrough(LaneIdxOp.getReg(), MRI);
4107 if (!VRegAndVal)
4108 return false;
4109 unsigned LaneIdx = VRegAndVal->Value.getSExtValue();
4110
4111 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
4112 if (DstRB.getID() == AArch64::GPRRegBankID) {
4113 unsigned Opcode;
4114 switch (WideTy.getScalarSizeInBits()) {
4115 case 8:
4116 Opcode = AArch64::UMOVvi8;
4117 break;
4118 case 16:
4119 Opcode = AArch64::UMOVvi16;
4120 break;
4121 case 32:
4122 Opcode = AArch64::UMOVvi32;
4123 break;
4124 default:
4125 return false;
4126 }
4127
4128 if (WideTy.getSizeInBits() != 128) {
4129 MachineInstr *ScalarToVector = emitScalarToVector(
4130 WideTy.getSizeInBits(), &AArch64::FPR128RegClass, SrcReg, MIB);
4131 assert(ScalarToVector && "Didn't expect emitScalarToVector to fail!");
4132 I.getOperand(1).setReg(ScalarToVector->getOperand(0).getReg());
4133 }
4134
4135 I.setDesc(TII.get(Opcode));
4136 I.getOperand(2).ChangeToImmediate(LaneIdx);
4138 return true;
4139 }
4140
4141 MachineInstr *Extract = emitExtractVectorElt(DstReg, DstRB, NarrowTy, SrcReg,
4142 LaneIdx, MIB);
4143 if (!Extract)
4144 return false;
4145
4146 I.eraseFromParent();
4147 return true;
4148}
4149
4150bool AArch64InstructionSelector::selectSplitVectorUnmerge(
4151 MachineInstr &I, MachineRegisterInfo &MRI) {
4152 unsigned NumElts = I.getNumOperands() - 1;
4153 Register SrcReg = I.getOperand(NumElts).getReg();
4154 const LLT NarrowTy = MRI.getType(I.getOperand(0).getReg());
4155 const LLT SrcTy = MRI.getType(SrcReg);
4156
4157 assert(NarrowTy.isVector() && "Expected an unmerge into vectors");
4158 if (SrcTy.getSizeInBits() > 128) {
4159 LLVM_DEBUG(dbgs() << "Unexpected vector type for vec split unmerge");
4160 return false;
4161 }
4162
4163 // We implement a split vector operation by treating the sub-vectors as
4164 // scalars and extracting them.
4165 const RegisterBank &DstRB =
4166 *RBI.getRegBank(I.getOperand(0).getReg(), MRI, TRI);
4167 for (unsigned OpIdx = 0; OpIdx < NumElts; ++OpIdx) {
4168 Register Dst = I.getOperand(OpIdx).getReg();
4169 MachineInstr *Extract =
4170 emitExtractVectorElt(Dst, DstRB, NarrowTy, SrcReg, OpIdx, MIB);
4171 if (!Extract)
4172 return false;
4173 }
4174 I.eraseFromParent();
4175 return true;
4176}
4177
4178bool AArch64InstructionSelector::selectUnmergeValues(MachineInstr &I,
4179 MachineRegisterInfo &MRI) {
4180 assert(I.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
4181 "unexpected opcode");
4182
4183 // The last operand is the vector source register, and every other operand is
4184 // a register to unpack into.
4185 unsigned NumElts = I.getNumOperands() - 1;
4186 Register SrcReg = I.getOperand(NumElts).getReg();
4187 Register LoReg = I.getOperand(0).getReg();
4188 Register HiReg = I.getOperand(1).getReg();
4189 const LLT NarrowTy = MRI.getType(LoReg);
4190 const LLT WideTy = MRI.getType(SrcReg);
4191 const RegisterBank &LoRB = *RBI.getRegBank(LoReg, MRI, TRI);
4192 const RegisterBank &HiRB = *RBI.getRegBank(HiReg, MRI, TRI);
4193 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
4194
4195 // Handle unmerging a 128-bit FPR value into two 64-bit GPR values.
4196 if (NarrowTy == LLT::scalar(64) && WideTy == LLT::scalar(128) &&
4197 LoRB.getID() == AArch64::GPRRegBankID &&
4198 HiRB.getID() == AArch64::GPRRegBankID &&
4199 SrcRB.getID() == AArch64::FPRRegBankID) {
4200 MachineInstr &Lo = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
4201 TII.get(AArch64::UMOVvi64), LoReg)
4202 .addUse(SrcReg)
4203 .addImm(0);
4204 MachineInstr &Hi = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
4205 TII.get(AArch64::UMOVvi64), HiReg)
4206 .addUse(SrcReg)
4207 .addImm(1);
4210 I.eraseFromParent();
4211 return true;
4212 }
4213
4214 // TODO: Handle other unmerges into GPRs and from scalars to scalars.
4215 if (LoRB.getID() != AArch64::FPRRegBankID ||
4216 HiRB.getID() != AArch64::FPRRegBankID) {
4217 LLVM_DEBUG(dbgs() << "Unmerging vector-to-gpr and scalar-to-scalar "
4218 "currently unsupported.\n");
4219 return false;
4220 }
4221
4222 assert(WideTy.getSizeInBits() > NarrowTy.getSizeInBits() &&
4223 "source register size too small!");
4224
4225 if (!NarrowTy.isScalar())
4226 return selectSplitVectorUnmerge(I, MRI);
4227
4228 // Choose a lane copy opcode and subregister based off of the size of the
4229 // vector's elements.
4230 unsigned CopyOpc = 0;
4231 unsigned ExtractSubReg = 0;
4232 if (!getLaneCopyOpcode(CopyOpc, ExtractSubReg, NarrowTy.getSizeInBits()))
4233 return false;
4234
4235 // Set up for the lane copies.
4236 MachineBasicBlock &MBB = *I.getParent();
4237
4238 // Stores the registers we'll be copying from.
4239 SmallVector<Register, 4> InsertRegs;
4240
4241 // We'll use the first register twice, so we only need NumElts-1 registers.
4242 unsigned NumInsertRegs = NumElts - 1;
4243
4244 // If our elements fit into exactly 128 bits, then we can copy from the source
4245 // directly. Otherwise, we need to do a bit of setup with some subregister
4246 // inserts.
4247 if (NarrowTy.getSizeInBits() * NumElts == 128) {
4248 InsertRegs.assign(NumInsertRegs, SrcReg);
4249 } else {
4250 // No. We have to perform subregister inserts. For each insert, create an
4251 // implicit def and a subregister insert, and save the register we create.
4252 // For scalar sources, treat as a pseudo-vector of NarrowTy elements.
4253 unsigned EltSize = WideTy.isVector() ? WideTy.getScalarSizeInBits()
4254 : NarrowTy.getSizeInBits();
4255 const TargetRegisterClass *RC = getRegClassForTypeOnBank(
4256 LLT::fixed_vector(NumElts, EltSize), *RBI.getRegBank(SrcReg, MRI, TRI));
4257 unsigned SubReg = 0;
4258 bool Found = getSubRegForClass(RC, TRI, SubReg);
4259 (void)Found;
4260 assert(Found && "expected to find last operand's subeg idx");
4261 for (unsigned Idx = 0; Idx < NumInsertRegs; ++Idx) {
4262 Register ImpDefReg = MRI.createVirtualRegister(&AArch64::FPR128RegClass);
4263 MachineInstr &ImpDefMI =
4264 *BuildMI(MBB, I, I.getDebugLoc(), TII.get(TargetOpcode::IMPLICIT_DEF),
4265 ImpDefReg);
4266
4267 // Now, create the subregister insert from SrcReg.
4268 Register InsertReg = MRI.createVirtualRegister(&AArch64::FPR128RegClass);
4269 MachineInstr &InsMI =
4270 *BuildMI(MBB, I, I.getDebugLoc(),
4271 TII.get(TargetOpcode::INSERT_SUBREG), InsertReg)
4272 .addUse(ImpDefReg)
4273 .addUse(SrcReg)
4274 .addImm(SubReg);
4275
4276 constrainSelectedInstRegOperands(ImpDefMI, TII, TRI, RBI);
4278
4279 // Save the register so that we can copy from it after.
4280 InsertRegs.push_back(InsertReg);
4281 }
4282 }
4283
4284 // Now that we've created any necessary subregister inserts, we can
4285 // create the copies.
4286 //
4287 // Perform the first copy separately as a subregister copy.
4288 Register CopyTo = I.getOperand(0).getReg();
4289 auto FirstCopy = MIB.buildInstr(TargetOpcode::COPY, {CopyTo}, {})
4290 .addReg(InsertRegs[0], {}, ExtractSubReg);
4291 constrainSelectedInstRegOperands(*FirstCopy, TII, TRI, RBI);
4292
4293 // Now, perform the remaining copies as vector lane copies.
4294 unsigned LaneIdx = 1;
4295 for (Register InsReg : InsertRegs) {
4296 Register CopyTo = I.getOperand(LaneIdx).getReg();
4297 MachineInstr &CopyInst =
4298 *BuildMI(MBB, I, I.getDebugLoc(), TII.get(CopyOpc), CopyTo)
4299 .addUse(InsReg)
4300 .addImm(LaneIdx);
4301 constrainSelectedInstRegOperands(CopyInst, TII, TRI, RBI);
4302 ++LaneIdx;
4303 }
4304
4305 // Separately constrain the first copy's destination. Because of the
4306 // limitation in constrainOperandRegClass, we can't guarantee that this will
4307 // actually be constrained. So, do it ourselves using the second operand.
4308 const TargetRegisterClass *RC =
4309 MRI.getRegClassOrNull(I.getOperand(1).getReg());
4310 if (!RC) {
4311 LLVM_DEBUG(dbgs() << "Couldn't constrain copy destination.\n");
4312 return false;
4313 }
4314
4315 RBI.constrainGenericRegister(CopyTo, *RC, MRI);
4316 I.eraseFromParent();
4317 return true;
4318}
4319
4320bool AArch64InstructionSelector::selectConcatVectors(
4321 MachineInstr &I, MachineRegisterInfo &MRI) {
4322 assert(I.getOpcode() == TargetOpcode::G_CONCAT_VECTORS &&
4323 "Unexpected opcode");
4324 Register Dst = I.getOperand(0).getReg();
4325 Register Op1 = I.getOperand(1).getReg();
4326 Register Op2 = I.getOperand(2).getReg();
4327 MachineInstr *ConcatMI = emitVectorConcat(Dst, Op1, Op2, MIB);
4328 if (!ConcatMI)
4329 return false;
4330 I.eraseFromParent();
4331 return true;
4332}
4333
4334unsigned
4335AArch64InstructionSelector::emitConstantPoolEntry(const Constant *CPVal,
4336 MachineFunction &MF) const {
4337 Type *CPTy = CPVal->getType();
4339
4340 MachineConstantPool *MCP = MF.getConstantPool();
4341 return MCP->getConstantPoolIndex(CPVal, Alignment);
4342}
4343
4344MachineInstr *AArch64InstructionSelector::emitLoadFromConstantPool(
4345 const Constant *CPVal, MachineIRBuilder &MIRBuilder) const {
4346 const TargetRegisterClass *RC;
4347 unsigned Opc;
4348 bool IsTiny = TM.getCodeModel() == CodeModel::Tiny;
4349 unsigned Size = MIRBuilder.getDataLayout().getTypeStoreSize(CPVal->getType());
4350 switch (Size) {
4351 case 16:
4352 RC = &AArch64::FPR128RegClass;
4353 Opc = IsTiny ? AArch64::LDRQl : AArch64::LDRQui;
4354 break;
4355 case 8:
4356 RC = &AArch64::FPR64RegClass;
4357 Opc = IsTiny ? AArch64::LDRDl : AArch64::LDRDui;
4358 break;
4359 case 4:
4360 RC = &AArch64::FPR32RegClass;
4361 Opc = IsTiny ? AArch64::LDRSl : AArch64::LDRSui;
4362 break;
4363 case 2:
4364 RC = &AArch64::FPR16RegClass;
4365 Opc = AArch64::LDRHui;
4366 break;
4367 default:
4368 LLVM_DEBUG(dbgs() << "Could not load from constant pool of type "
4369 << *CPVal->getType());
4370 return nullptr;
4371 }
4372
4373 MachineInstr *LoadMI = nullptr;
4374 auto &MF = MIRBuilder.getMF();
4375 unsigned CPIdx = emitConstantPoolEntry(CPVal, MF);
4376 if (IsTiny && (Size == 16 || Size == 8 || Size == 4)) {
4377 // Use load(literal) for tiny code model.
4378 LoadMI = &*MIRBuilder.buildInstr(Opc, {RC}, {}).addConstantPoolIndex(CPIdx);
4379 } else {
4380 auto Adrp =
4381 MIRBuilder.buildInstr(AArch64::ADRP, {&AArch64::GPR64RegClass}, {})
4382 .addConstantPoolIndex(CPIdx, 0, AArch64II::MO_PAGE);
4383
4384 LoadMI = &*MIRBuilder.buildInstr(Opc, {RC}, {Adrp})
4385 .addConstantPoolIndex(
4387
4389 }
4390
4391 MachinePointerInfo PtrInfo = MachinePointerInfo::getConstantPool(MF);
4392 LoadMI->addMemOperand(MF, MF.getMachineMemOperand(PtrInfo,
4394 Size, Align(Size)));
4396 return LoadMI;
4397}
4398
4399/// Return an <Opcode, SubregIndex> pair to do an vector elt insert of a given
4400/// size and RB.
4401static std::pair<unsigned, unsigned>
4402getInsertVecEltOpInfo(const RegisterBank &RB, unsigned EltSize) {
4403 unsigned Opc, SubregIdx;
4404 if (RB.getID() == AArch64::GPRRegBankID) {
4405 if (EltSize == 8) {
4406 Opc = AArch64::INSvi8gpr;
4407 SubregIdx = AArch64::bsub;
4408 } else if (EltSize == 16) {
4409 Opc = AArch64::INSvi16gpr;
4410 SubregIdx = AArch64::ssub;
4411 } else if (EltSize == 32) {
4412 Opc = AArch64::INSvi32gpr;
4413 SubregIdx = AArch64::ssub;
4414 } else if (EltSize == 64) {
4415 Opc = AArch64::INSvi64gpr;
4416 SubregIdx = AArch64::dsub;
4417 } else {
4418 llvm_unreachable("invalid elt size!");
4419 }
4420 } else {
4421 if (EltSize == 8) {
4422 Opc = AArch64::INSvi8lane;
4423 SubregIdx = AArch64::bsub;
4424 } else if (EltSize == 16) {
4425 Opc = AArch64::INSvi16lane;
4426 SubregIdx = AArch64::hsub;
4427 } else if (EltSize == 32) {
4428 Opc = AArch64::INSvi32lane;
4429 SubregIdx = AArch64::ssub;
4430 } else if (EltSize == 64) {
4431 Opc = AArch64::INSvi64lane;
4432 SubregIdx = AArch64::dsub;
4433 } else {
4434 llvm_unreachable("invalid elt size!");
4435 }
4436 }
4437 return std::make_pair(Opc, SubregIdx);
4438}
4439
4440MachineInstr *AArch64InstructionSelector::emitInstr(
4441 unsigned Opcode, std::initializer_list<llvm::DstOp> DstOps,
4442 std::initializer_list<llvm::SrcOp> SrcOps, MachineIRBuilder &MIRBuilder,
4443 const ComplexRendererFns &RenderFns) const {
4444 assert(Opcode && "Expected an opcode?");
4445 assert(!isPreISelGenericOpcode(Opcode) &&
4446 "Function should only be used to produce selected instructions!");
4447 auto MI = MIRBuilder.buildInstr(Opcode, DstOps, SrcOps);
4448 if (RenderFns)
4449 for (auto &Fn : *RenderFns)
4450 Fn(MI);
4452 return &*MI;
4453}
4454
4455MachineInstr *AArch64InstructionSelector::emitAddSub(
4456 const std::array<std::array<unsigned, 2>, 5> &AddrModeAndSizeToOpcode,
4457 Register Dst, MachineOperand &LHS, MachineOperand &RHS,
4458 MachineIRBuilder &MIRBuilder) const {
4459 MachineRegisterInfo &MRI = MIRBuilder.getMF().getRegInfo();
4460 assert(LHS.isReg() && RHS.isReg() && "Expected register operands?");
4461 auto Ty = MRI.getType(LHS.getReg());
4462 assert(!Ty.isVector() && "Expected a scalar or pointer?");
4463 unsigned Size = Ty.getSizeInBits();
4464 assert((Size == 32 || Size == 64) && "Expected a 32-bit or 64-bit type only");
4465 bool Is32Bit = Size == 32;
4466
4467 // INSTRri form with positive arithmetic immediate.
4468 if (auto Fns = selectArithImmed(RHS))
4469 return emitInstr(AddrModeAndSizeToOpcode[0][Is32Bit], {Dst}, {LHS},
4470 MIRBuilder, Fns);
4471
4472 // INSTRri form with negative arithmetic immediate.
4473 if (auto Fns = selectNegArithImmed(RHS))
4474 return emitInstr(AddrModeAndSizeToOpcode[3][Is32Bit], {Dst}, {LHS},
4475 MIRBuilder, Fns);
4476
4477 // INSTRrx form.
4478 if (auto Fns = selectArithExtendedRegister(RHS))
4479 return emitInstr(AddrModeAndSizeToOpcode[4][Is32Bit], {Dst}, {LHS},
4480 MIRBuilder, Fns);
4481
4482 // INSTRrs form.
4483 if (auto Fns = selectShiftedRegister(RHS))
4484 return emitInstr(AddrModeAndSizeToOpcode[1][Is32Bit], {Dst}, {LHS},
4485 MIRBuilder, Fns);
4486 return emitInstr(AddrModeAndSizeToOpcode[2][Is32Bit], {Dst}, {LHS, RHS},
4487 MIRBuilder);
4488}
4489
4490MachineInstr *
4491AArch64InstructionSelector::emitADD(Register DefReg, MachineOperand &LHS,
4492 MachineOperand &RHS,
4493 MachineIRBuilder &MIRBuilder) const {
4494 const std::array<std::array<unsigned, 2>, 5> OpcTable{
4495 {{AArch64::ADDXri, AArch64::ADDWri},
4496 {AArch64::ADDXrs, AArch64::ADDWrs},
4497 {AArch64::ADDXrr, AArch64::ADDWrr},
4498 {AArch64::SUBXri, AArch64::SUBWri},
4499 {AArch64::ADDXrx, AArch64::ADDWrx}}};
4500 return emitAddSub(OpcTable, DefReg, LHS, RHS, MIRBuilder);
4501}
4502
4503MachineInstr *
4504AArch64InstructionSelector::emitADDS(Register Dst, MachineOperand &LHS,
4505 MachineOperand &RHS,
4506 MachineIRBuilder &MIRBuilder) const {
4507 const std::array<std::array<unsigned, 2>, 5> OpcTable{
4508 {{AArch64::ADDSXri, AArch64::ADDSWri},
4509 {AArch64::ADDSXrs, AArch64::ADDSWrs},
4510 {AArch64::ADDSXrr, AArch64::ADDSWrr},
4511 {AArch64::SUBSXri, AArch64::SUBSWri},
4512 {AArch64::ADDSXrx, AArch64::ADDSWrx}}};
4513 return emitAddSub(OpcTable, Dst, LHS, RHS, MIRBuilder);
4514}
4515
4516MachineInstr *
4517AArch64InstructionSelector::emitSUBS(Register Dst, MachineOperand &LHS,
4518 MachineOperand &RHS,
4519 MachineIRBuilder &MIRBuilder) const {
4520 const std::array<std::array<unsigned, 2>, 5> OpcTable{
4521 {{AArch64::SUBSXri, AArch64::SUBSWri},
4522 {AArch64::SUBSXrs, AArch64::SUBSWrs},
4523 {AArch64::SUBSXrr, AArch64::SUBSWrr},
4524 {AArch64::ADDSXri, AArch64::ADDSWri},
4525 {AArch64::SUBSXrx, AArch64::SUBSWrx}}};
4526 return emitAddSub(OpcTable, Dst, LHS, RHS, MIRBuilder);
4527}
4528
4529MachineInstr *
4530AArch64InstructionSelector::emitADCS(Register Dst, MachineOperand &LHS,
4531 MachineOperand &RHS,
4532 MachineIRBuilder &MIRBuilder) const {
4533 assert(LHS.isReg() && RHS.isReg() && "Expected register operands?");
4534 MachineRegisterInfo *MRI = MIRBuilder.getMRI();
4535 bool Is32Bit = (MRI->getType(LHS.getReg()).getSizeInBits() == 32);
4536 static const unsigned OpcTable[2] = {AArch64::ADCSXr, AArch64::ADCSWr};
4537 return emitInstr(OpcTable[Is32Bit], {Dst}, {LHS, RHS}, MIRBuilder);
4538}
4539
4540MachineInstr *
4541AArch64InstructionSelector::emitSBCS(Register Dst, MachineOperand &LHS,
4542 MachineOperand &RHS,
4543 MachineIRBuilder &MIRBuilder) const {
4544 assert(LHS.isReg() && RHS.isReg() && "Expected register operands?");
4545 MachineRegisterInfo *MRI = MIRBuilder.getMRI();
4546 bool Is32Bit = (MRI->getType(LHS.getReg()).getSizeInBits() == 32);
4547 static const unsigned OpcTable[2] = {AArch64::SBCSXr, AArch64::SBCSWr};
4548 return emitInstr(OpcTable[Is32Bit], {Dst}, {LHS, RHS}, MIRBuilder);
4549}
4550
4551MachineInstr *
4552AArch64InstructionSelector::emitCMP(MachineOperand &LHS, MachineOperand &RHS,
4553 MachineIRBuilder &MIRBuilder) const {
4554 MachineRegisterInfo &MRI = MIRBuilder.getMF().getRegInfo();
4555 bool Is32Bit = MRI.getType(LHS.getReg()).getSizeInBits() == 32;
4556 auto RC = Is32Bit ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass;
4557 return emitSUBS(MRI.createVirtualRegister(RC), LHS, RHS, MIRBuilder);
4558}
4559
4560MachineInstr *
4561AArch64InstructionSelector::emitCMN(MachineOperand &LHS, MachineOperand &RHS,
4562 MachineIRBuilder &MIRBuilder) const {
4563 MachineRegisterInfo &MRI = MIRBuilder.getMF().getRegInfo();
4564 bool Is32Bit = (MRI.getType(LHS.getReg()).getSizeInBits() == 32);
4565 auto RC = Is32Bit ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass;
4566 return emitADDS(MRI.createVirtualRegister(RC), LHS, RHS, MIRBuilder);
4567}
4568
4569MachineInstr *
4570AArch64InstructionSelector::emitTST(MachineOperand &LHS, MachineOperand &RHS,
4571 MachineIRBuilder &MIRBuilder) const {
4572 assert(LHS.isReg() && RHS.isReg() && "Expected register operands?");
4573 MachineRegisterInfo &MRI = MIRBuilder.getMF().getRegInfo();
4574 LLT Ty = MRI.getType(LHS.getReg());
4575 unsigned RegSize = Ty.getSizeInBits();
4576 bool Is32Bit = (RegSize == 32);
4577 const unsigned OpcTable[3][2] = {{AArch64::ANDSXri, AArch64::ANDSWri},
4578 {AArch64::ANDSXrs, AArch64::ANDSWrs},
4579 {AArch64::ANDSXrr, AArch64::ANDSWrr}};
4580 // ANDS needs a logical immediate for its immediate form. Check if we can
4581 // fold one in.
4582 if (auto ValAndVReg = getIConstantVRegValWithLookThrough(RHS.getReg(), MRI)) {
4583 int64_t Imm = ValAndVReg->Value.getSExtValue();
4584
4586 auto TstMI = MIRBuilder.buildInstr(OpcTable[0][Is32Bit], {Ty}, {LHS});
4589 return &*TstMI;
4590 }
4591 }
4592
4593 if (auto Fns = selectLogicalShiftedRegister(RHS))
4594 return emitInstr(OpcTable[1][Is32Bit], {Ty}, {LHS}, MIRBuilder, Fns);
4595 return emitInstr(OpcTable[2][Is32Bit], {Ty}, {LHS, RHS}, MIRBuilder);
4596}
4597
4598MachineInstr *AArch64InstructionSelector::emitIntegerCompare(
4599 MachineOperand &LHS, MachineOperand &RHS, MachineOperand &Predicate,
4600 MachineIRBuilder &MIRBuilder) const {
4601 assert(LHS.isReg() && RHS.isReg() && "Expected LHS and RHS to be registers!");
4602 assert(Predicate.isPredicate() && "Expected predicate?");
4603 MachineRegisterInfo &MRI = MIRBuilder.getMF().getRegInfo();
4604 LLT CmpTy = MRI.getType(LHS.getReg());
4605 assert(!CmpTy.isVector() && "Expected scalar or pointer");
4606 unsigned Size = CmpTy.getSizeInBits();
4607 (void)Size;
4608 assert((Size == 32 || Size == 64) && "Expected a 32-bit or 64-bit LHS/RHS?");
4609 // Fold the compare into a cmn or tst if possible.
4610 if (auto FoldCmp = tryFoldIntegerCompare(LHS, RHS, Predicate, MIRBuilder))
4611 return FoldCmp;
4612 return emitCMP(LHS, RHS, MIRBuilder);
4613}
4614
4615MachineInstr *AArch64InstructionSelector::emitCSetForFCmp(
4616 Register Dst, CmpInst::Predicate Pred, MachineIRBuilder &MIRBuilder) const {
4617 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
4618#ifndef NDEBUG
4619 LLT Ty = MRI.getType(Dst);
4620 assert(!Ty.isVector() && Ty.getSizeInBits() == 32 &&
4621 "Expected a 32-bit scalar register?");
4622#endif
4623 const Register ZReg = AArch64::WZR;
4624 AArch64CC::CondCode CC1, CC2;
4626 auto InvCC1 = AArch64CC::getInvertedCondCode(CC1);
4627 if (CC2 == AArch64CC::AL)
4628 return emitCSINC(/*Dst=*/Dst, /*Src1=*/ZReg, /*Src2=*/ZReg, InvCC1,
4629 MIRBuilder);
4630 const TargetRegisterClass *RC = &AArch64::GPR32RegClass;
4631 Register Def1Reg = MRI.createVirtualRegister(RC);
4632 Register Def2Reg = MRI.createVirtualRegister(RC);
4633 auto InvCC2 = AArch64CC::getInvertedCondCode(CC2);
4634 emitCSINC(/*Dst=*/Def1Reg, /*Src1=*/ZReg, /*Src2=*/ZReg, InvCC1, MIRBuilder);
4635 emitCSINC(/*Dst=*/Def2Reg, /*Src1=*/ZReg, /*Src2=*/ZReg, InvCC2, MIRBuilder);
4636 auto OrMI = MIRBuilder.buildInstr(AArch64::ORRWrr, {Dst}, {Def1Reg, Def2Reg});
4638 return &*OrMI;
4639}
4640
4641MachineInstr *AArch64InstructionSelector::emitFPCompare(
4642 Register LHS, Register RHS, MachineIRBuilder &MIRBuilder,
4643 std::optional<CmpInst::Predicate> Pred) const {
4644 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
4645 LLT Ty = MRI.getType(LHS);
4646 if (Ty.isVector())
4647 return nullptr;
4648 unsigned OpSize = Ty.getSizeInBits();
4649 assert(OpSize == 16 || OpSize == 32 || OpSize == 64);
4650
4651 // If this is a compare against +0.0, then we don't have
4652 // to explicitly materialize a constant.
4653 bool ShouldUseImm = mi_match(RHS, MRI, m_PosZeroFP());
4654
4655 auto IsEqualityPred = [](CmpInst::Predicate P) {
4656 return P == CmpInst::FCMP_OEQ || P == CmpInst::FCMP_ONE ||
4658 };
4659 if (!ShouldUseImm && Pred && IsEqualityPred(*Pred)) {
4660 // Try commuting the operands.
4661 if (mi_match(LHS, MRI, m_PosZeroFP())) {
4662 ShouldUseImm = true;
4663 std::swap(LHS, RHS);
4664 }
4665 }
4666 unsigned CmpOpcTbl[2][3] = {
4667 {AArch64::FCMPHrr, AArch64::FCMPSrr, AArch64::FCMPDrr},
4668 {AArch64::FCMPHri, AArch64::FCMPSri, AArch64::FCMPDri}};
4669 unsigned CmpOpc =
4670 CmpOpcTbl[ShouldUseImm][OpSize == 16 ? 0 : (OpSize == 32 ? 1 : 2)];
4671
4672 // Partially build the compare. Decide if we need to add a use for the
4673 // third operand based off whether or not we're comparing against 0.0.
4674 auto CmpMI = MIRBuilder.buildInstr(CmpOpc).addUse(LHS);
4676 if (!ShouldUseImm)
4677 CmpMI.addUse(RHS);
4679 return &*CmpMI;
4680}
4681
4682MachineInstr *AArch64InstructionSelector::emitVectorConcat(
4683 std::optional<Register> Dst, Register Op1, Register Op2,
4684 MachineIRBuilder &MIRBuilder) const {
4685 // We implement a vector concat by:
4686 // 1. Use scalar_to_vector to insert the lower vector into the larger dest
4687 // 2. Insert the upper vector into the destination's upper element
4688 // TODO: some of this code is common with G_BUILD_VECTOR handling.
4689 MachineRegisterInfo &MRI = MIRBuilder.getMF().getRegInfo();
4690
4691 const LLT Op1Ty = MRI.getType(Op1);
4692 const LLT Op2Ty = MRI.getType(Op2);
4693
4694 if (Op1Ty != Op2Ty) {
4695 LLVM_DEBUG(dbgs() << "Could not do vector concat of differing vector tys");
4696 return nullptr;
4697 }
4698 assert(Op1Ty.isVector() && "Expected a vector for vector concat");
4699
4700 if (Op1Ty.getSizeInBits() >= 128) {
4701 LLVM_DEBUG(dbgs() << "Vector concat not supported for full size vectors");
4702 return nullptr;
4703 }
4704
4705 // At the moment we just support 64 bit vector concats.
4706 if (Op1Ty.getSizeInBits() != 64) {
4707 LLVM_DEBUG(dbgs() << "Vector concat supported for 64b vectors");
4708 return nullptr;
4709 }
4710
4711 const LLT ScalarTy = LLT::scalar(Op1Ty.getSizeInBits());
4712 const RegisterBank &FPRBank = *RBI.getRegBank(Op1, MRI, TRI);
4713 const TargetRegisterClass *DstRC =
4714 getRegClassForTypeOnBank(Op1Ty.multiplyElements(2), FPRBank);
4715
4716 MachineInstr *WidenedOp1 =
4717 emitScalarToVector(ScalarTy.getSizeInBits(), DstRC, Op1, MIRBuilder);
4718 MachineInstr *WidenedOp2 =
4719 emitScalarToVector(ScalarTy.getSizeInBits(), DstRC, Op2, MIRBuilder);
4720 if (!WidenedOp1 || !WidenedOp2) {
4721 LLVM_DEBUG(dbgs() << "Could not emit a vector from scalar value");
4722 return nullptr;
4723 }
4724
4725 // Now do the insert of the upper element.
4726 unsigned InsertOpc, InsSubRegIdx;
4727 std::tie(InsertOpc, InsSubRegIdx) =
4728 getInsertVecEltOpInfo(FPRBank, ScalarTy.getSizeInBits());
4729
4730 if (!Dst)
4731 Dst = MRI.createVirtualRegister(DstRC);
4732 auto InsElt =
4733 MIRBuilder
4734 .buildInstr(InsertOpc, {*Dst}, {WidenedOp1->getOperand(0).getReg()})
4735 .addImm(1) /* Lane index */
4736 .addUse(WidenedOp2->getOperand(0).getReg())
4737 .addImm(0);
4739 return &*InsElt;
4740}
4741
4742MachineInstr *
4743AArch64InstructionSelector::emitCSINC(Register Dst, Register Src1,
4745 MachineIRBuilder &MIRBuilder) const {
4746 auto &MRI = *MIRBuilder.getMRI();
4747 const RegClassOrRegBank &RegClassOrBank = MRI.getRegClassOrRegBank(Dst);
4748 // If we used a register class, then this won't necessarily have an LLT.
4749 // Compute the size based off whether or not we have a class or bank.
4750 unsigned Size;
4751 if (const auto *RC = dyn_cast<const TargetRegisterClass *>(RegClassOrBank))
4752 Size = TRI.getRegSizeInBits(*RC);
4753 else
4754 Size = MRI.getType(Dst).getSizeInBits();
4755 // Some opcodes use s1.
4756 assert(Size <= 64 && "Expected 64 bits or less only!");
4757 static const unsigned OpcTable[2] = {AArch64::CSINCWr, AArch64::CSINCXr};
4758 unsigned Opc = OpcTable[Size == 64];
4759 auto CSINC = MIRBuilder.buildInstr(Opc, {Dst}, {Src1, Src2}).addImm(Pred);
4761 return &*CSINC;
4762}
4763
4764MachineInstr *AArch64InstructionSelector::emitCarryIn(MachineInstr &I,
4765 Register CarryReg) {
4766 MachineRegisterInfo *MRI = MIB.getMRI();
4767 unsigned Opcode = I.getOpcode();
4768
4769 // If the instruction is a SUB, we need to negate the carry,
4770 // because borrowing is indicated by carry-flag == 0.
4771 bool NeedsNegatedCarry =
4772 (Opcode == TargetOpcode::G_USUBE || Opcode == TargetOpcode::G_SSUBE);
4773
4774 // If the previous instruction will already produce the correct carry, do not
4775 // emit a carry generating instruction. E.g. for G_UADDE/G_USUBE sequences
4776 // generated during legalization of wide add/sub. This optimization depends on
4777 // these sequences not being interrupted by other instructions.
4778 // We have to select the previous instruction before the carry-using
4779 // instruction is deleted by the calling function, otherwise the previous
4780 // instruction might become dead and would get deleted.
4781 MachineInstr *SrcMI = MRI->getVRegDef(CarryReg);
4782
4783 // Debug instructions (e.g., DBG_VALUE) do not modify NZCV, so skip all that
4784 // immediately precede I.
4785 MachineInstr *PrevMI = I.getPrevNode();
4786 while (PrevMI && PrevMI->isDebugInstr())
4787 PrevMI = PrevMI->getPrevNode();
4788
4789 if (SrcMI == PrevMI) {
4790 if (auto *CarrySrcMI = dyn_cast<GAddSubCarryOut>(SrcMI)) {
4791 bool ProducesNegatedCarry = CarrySrcMI->isSub();
4792 if (NeedsNegatedCarry == ProducesNegatedCarry &&
4793 CarrySrcMI->isUnsigned() &&
4794 CarrySrcMI->getCarryOutReg() == CarryReg &&
4795 selectAndRestoreState(*SrcMI))
4796 return nullptr;
4797 }
4798 }
4799
4800 Register DeadReg = MRI->createVirtualRegister(&AArch64::GPR32RegClass);
4801
4802 if (NeedsNegatedCarry) {
4803 // (0 - Carry) sets !C in NZCV when Carry == 1
4804 Register ZReg = AArch64::WZR;
4805 return emitInstr(AArch64::SUBSWrr, {DeadReg}, {ZReg, CarryReg}, MIB);
4806 }
4807
4808 // (Carry - 1) sets !C in NZCV when Carry == 0
4809 auto Fns = select12BitValueWithLeftShift(1);
4810 return emitInstr(AArch64::SUBSWri, {DeadReg}, {CarryReg}, MIB, Fns);
4811}
4812
4813bool AArch64InstructionSelector::selectOverflowOp(MachineInstr &I,
4814 MachineRegisterInfo &MRI) {
4815 auto &CarryMI = cast<GAddSubCarryOut>(I);
4816
4817 if (auto *CarryInMI = dyn_cast<GAddSubCarryInOut>(&I)) {
4818 // Set NZCV carry according to carry-in VReg
4819 emitCarryIn(I, CarryInMI->getCarryInReg());
4820 }
4821
4822 // Emit the operation and get the correct condition code.
4823 auto OpAndCC = emitOverflowOp(I.getOpcode(), CarryMI.getDstReg(),
4824 CarryMI.getLHS(), CarryMI.getRHS(), MIB);
4825
4826 Register CarryOutReg = CarryMI.getCarryOutReg();
4827
4828 // Don't convert carry-out to VReg if it is never used
4829 if (MRI.use_nodbg_empty(CarryOutReg)) {
4830 OpAndCC.first->addRegisterDead(AArch64::NZCV, &TRI);
4831 } else {
4832 // Now, put the overflow result in the register given by the first operand
4833 // to the overflow op. CSINC increments the result when the predicate is
4834 // false, so to get the increment when it's true, we need to use the
4835 // inverse. In this case, we want to increment when carry is set.
4836 Register ZReg = AArch64::WZR;
4837 emitCSINC(/*Dst=*/CarryOutReg, /*Src1=*/ZReg, /*Src2=*/ZReg,
4838 getInvertedCondCode(OpAndCC.second), MIB);
4839 }
4840
4841 I.eraseFromParent();
4842 return true;
4843}
4844
4845std::pair<MachineInstr *, AArch64CC::CondCode>
4846AArch64InstructionSelector::emitOverflowOp(unsigned Opcode, Register Dst,
4847 MachineOperand &LHS,
4848 MachineOperand &RHS,
4849 MachineIRBuilder &MIRBuilder) const {
4850 switch (Opcode) {
4851 default:
4852 llvm_unreachable("Unexpected opcode!");
4853 case TargetOpcode::G_SADDO:
4854 return std::make_pair(emitADDS(Dst, LHS, RHS, MIRBuilder), AArch64CC::VS);
4855 case TargetOpcode::G_UADDO:
4856 return std::make_pair(emitADDS(Dst, LHS, RHS, MIRBuilder), AArch64CC::HS);
4857 case TargetOpcode::G_SSUBO:
4858 return std::make_pair(emitSUBS(Dst, LHS, RHS, MIRBuilder), AArch64CC::VS);
4859 case TargetOpcode::G_USUBO:
4860 return std::make_pair(emitSUBS(Dst, LHS, RHS, MIRBuilder), AArch64CC::LO);
4861 case TargetOpcode::G_SADDE:
4862 return std::make_pair(emitADCS(Dst, LHS, RHS, MIRBuilder), AArch64CC::VS);
4863 case TargetOpcode::G_UADDE:
4864 return std::make_pair(emitADCS(Dst, LHS, RHS, MIRBuilder), AArch64CC::HS);
4865 case TargetOpcode::G_SSUBE:
4866 return std::make_pair(emitSBCS(Dst, LHS, RHS, MIRBuilder), AArch64CC::VS);
4867 case TargetOpcode::G_USUBE:
4868 return std::make_pair(emitSBCS(Dst, LHS, RHS, MIRBuilder), AArch64CC::LO);
4869 }
4870}
4871
4872/// Returns true if @p Val is a tree of AND/OR/CMP operations that can be
4873/// expressed as a conjunction.
4874/// \param CanNegate Set to true if we can negate the whole sub-tree just by
4875/// changing the conditions on the CMP tests.
4876/// (this means we can call emitConjunctionRec() with
4877/// Negate==true on this sub-tree)
4878/// \param MustBeFirst Set to true if this subtree needs to be negated and we
4879/// cannot do the negation naturally. We are required to
4880/// emit the subtree first in this case.
4881/// \param WillNegate Is true if are called when the result of this
4882/// subexpression must be negated. This happens when the
4883/// outer expression is an OR. We can use this fact to know
4884/// that we have a double negation (or (or ...) ...) that
4885/// can be implemented for free.
4886static bool canEmitConjunction(Register Val, bool &CanNegate, bool &MustBeFirst,
4887 bool WillNegate, MachineRegisterInfo &MRI,
4888 unsigned Depth = 0) {
4889 if (!MRI.hasOneNonDBGUse(Val))
4890 return false;
4891 MachineInstr *ValDef = MRI.getVRegDef(Val);
4892 unsigned Opcode = ValDef->getOpcode();
4893 if (isa<GAnyCmp>(ValDef)) {
4894 CanNegate = true;
4895 MustBeFirst = false;
4896 return true;
4897 }
4898 // Protect against exponential runtime and stack overflow.
4899 if (Depth > 6)
4900 return false;
4901 if (Opcode == TargetOpcode::G_AND || Opcode == TargetOpcode::G_OR) {
4902 bool IsOR = Opcode == TargetOpcode::G_OR;
4903 Register O0 = ValDef->getOperand(1).getReg();
4904 Register O1 = ValDef->getOperand(2).getReg();
4905 bool CanNegateL;
4906 bool MustBeFirstL;
4907 if (!canEmitConjunction(O0, CanNegateL, MustBeFirstL, IsOR, MRI, Depth + 1))
4908 return false;
4909 bool CanNegateR;
4910 bool MustBeFirstR;
4911 if (!canEmitConjunction(O1, CanNegateR, MustBeFirstR, IsOR, MRI, Depth + 1))
4912 return false;
4913
4914 if (MustBeFirstL && MustBeFirstR)
4915 return false;
4916
4917 if (IsOR) {
4918 // For an OR expression we need to be able to naturally negate at least
4919 // one side or we cannot do the transformation at all.
4920 if (!CanNegateL && !CanNegateR)
4921 return false;
4922 // If we the result of the OR will be negated and we can naturally negate
4923 // the leaves, then this sub-tree as a whole negates naturally.
4924 CanNegate = WillNegate && CanNegateL && CanNegateR;
4925 // If we cannot naturally negate the whole sub-tree, then this must be
4926 // emitted first.
4927 MustBeFirst = !CanNegate;
4928 } else {
4929 assert(Opcode == TargetOpcode::G_AND && "Must be G_AND");
4930 // We cannot naturally negate an AND operation.
4931 CanNegate = false;
4932 MustBeFirst = MustBeFirstL || MustBeFirstR;
4933 }
4934 return true;
4935 }
4936 return false;
4937}
4938
4939MachineInstr *AArch64InstructionSelector::emitConditionalComparison(
4942 MachineIRBuilder &MIB) const {
4943 auto &MRI = *MIB.getMRI();
4944 LLT OpTy = MRI.getType(LHS);
4945 unsigned CCmpOpc;
4946 std::optional<ValueAndVReg> C;
4948 assert(OpTy.getSizeInBits() == 32 || OpTy.getSizeInBits() == 64);
4950 if (!C || C->Value.sgt(31) || C->Value.slt(-31))
4951 CCmpOpc = OpTy.getSizeInBits() == 32 ? AArch64::CCMPWr : AArch64::CCMPXr;
4952 else if (C->Value.ule(31))
4953 CCmpOpc = OpTy.getSizeInBits() == 32 ? AArch64::CCMPWi : AArch64::CCMPXi;
4954 else
4955 CCmpOpc = OpTy.getSizeInBits() == 32 ? AArch64::CCMNWi : AArch64::CCMNXi;
4956 } else {
4957 assert(OpTy.getSizeInBits() == 16 || OpTy.getSizeInBits() == 32 ||
4958 OpTy.getSizeInBits() == 64);
4959 switch (OpTy.getSizeInBits()) {
4960 case 16:
4961 assert(STI.hasFullFP16() && "Expected Full FP16 for fp16 comparisons");
4962 CCmpOpc = AArch64::FCCMPHrr;
4963 break;
4964 case 32:
4965 CCmpOpc = AArch64::FCCMPSrr;
4966 break;
4967 case 64:
4968 CCmpOpc = AArch64::FCCMPDrr;
4969 break;
4970 default:
4971 return nullptr;
4972 }
4973 }
4975 unsigned NZCV = AArch64CC::getNZCVToSatisfyCondCode(InvOutCC);
4976 auto CCmp =
4977 MIB.buildInstr(CCmpOpc, {}, {LHS});
4978 if (CCmpOpc == AArch64::CCMPWi || CCmpOpc == AArch64::CCMPXi)
4979 CCmp.addImm(C->Value.getZExtValue());
4980 else if (CCmpOpc == AArch64::CCMNWi || CCmpOpc == AArch64::CCMNXi)
4981 CCmp.addImm(C->Value.abs().getZExtValue());
4982 else
4983 CCmp.addReg(RHS);
4984 CCmp.addImm(NZCV).addImm(Predicate);
4986 return &*CCmp;
4987}
4988
4989MachineInstr *AArch64InstructionSelector::emitConjunctionRec(
4990 Register Val, AArch64CC::CondCode &OutCC, bool Negate, Register CCOp,
4991 AArch64CC::CondCode Predicate, MachineIRBuilder &MIB) const {
4992 // We're at a tree leaf, produce a conditional comparison operation.
4993 auto &MRI = *MIB.getMRI();
4994 MachineInstr *ValDef = MRI.getVRegDef(Val);
4995 unsigned Opcode = ValDef->getOpcode();
4996 if (auto *Cmp = dyn_cast<GAnyCmp>(ValDef)) {
4997 Register LHS = Cmp->getLHSReg();
4998 Register RHS = Cmp->getRHSReg();
4999 CmpInst::Predicate CC = Cmp->getCond();
5000 if (Negate)
5002 if (isa<GICmp>(Cmp)) {
5003 OutCC = changeICMPPredToAArch64CC(CC, RHS, MIB.getMRI());
5004 } else {
5005 // Handle special FP cases.
5006 AArch64CC::CondCode ExtraCC;
5007 changeFPCCToANDAArch64CC(CC, OutCC, ExtraCC);
5008 // Some floating point conditions can't be tested with a single condition
5009 // code. Construct an additional comparison in this case.
5010 if (ExtraCC != AArch64CC::AL) {
5011 MachineInstr *ExtraCmp;
5012 if (!CCOp)
5013 ExtraCmp = emitFPCompare(LHS, RHS, MIB, CC);
5014 else
5015 ExtraCmp =
5016 emitConditionalComparison(LHS, RHS, CC, Predicate, ExtraCC, MIB);
5017 CCOp = ExtraCmp->getOperand(0).getReg();
5018 Predicate = ExtraCC;
5019 }
5020 }
5021
5022 // Produce a normal comparison if we are first in the chain
5023 if (!CCOp) {
5024 if (isa<GICmp>(Cmp))
5025 return emitCMP(Cmp->getOperand(2), Cmp->getOperand(3), MIB);
5026 return emitFPCompare(Cmp->getOperand(2).getReg(),
5027 Cmp->getOperand(3).getReg(), MIB);
5028 }
5029 // Otherwise produce a ccmp.
5030 return emitConditionalComparison(LHS, RHS, CC, Predicate, OutCC, MIB);
5031 }
5032 assert(MRI.hasOneNonDBGUse(Val) && "Valid conjunction/disjunction tree");
5033
5034 bool IsOR = Opcode == TargetOpcode::G_OR;
5035
5036 Register LHS = ValDef->getOperand(1).getReg();
5037 bool CanNegateL;
5038 bool MustBeFirstL;
5039 bool ValidL = canEmitConjunction(LHS, CanNegateL, MustBeFirstL, IsOR, MRI);
5040 assert(ValidL && "Valid conjunction/disjunction tree");
5041 (void)ValidL;
5042
5043 Register RHS = ValDef->getOperand(2).getReg();
5044 bool CanNegateR;
5045 bool MustBeFirstR;
5046 bool ValidR = canEmitConjunction(RHS, CanNegateR, MustBeFirstR, IsOR, MRI);
5047 assert(ValidR && "Valid conjunction/disjunction tree");
5048 (void)ValidR;
5049
5050 // Swap sub-tree that must come first to the right side.
5051 if (MustBeFirstL) {
5052 assert(!MustBeFirstR && "Valid conjunction/disjunction tree");
5053 std::swap(LHS, RHS);
5054 std::swap(CanNegateL, CanNegateR);
5055 std::swap(MustBeFirstL, MustBeFirstR);
5056 }
5057
5058 bool NegateR;
5059 bool NegateAfterR;
5060 bool NegateL;
5061 bool NegateAfterAll;
5062 if (Opcode == TargetOpcode::G_OR) {
5063 // Swap the sub-tree that we can negate naturally to the left.
5064 if (!CanNegateL) {
5065 assert(CanNegateR && "at least one side must be negatable");
5066 assert(!MustBeFirstR && "invalid conjunction/disjunction tree");
5067 assert(!Negate);
5068 std::swap(LHS, RHS);
5069 NegateR = false;
5070 NegateAfterR = true;
5071 } else {
5072 // Negate the left sub-tree if possible, otherwise negate the result.
5073 NegateR = CanNegateR;
5074 NegateAfterR = !CanNegateR;
5075 }
5076 NegateL = true;
5077 NegateAfterAll = !Negate;
5078 } else {
5079 assert(Opcode == TargetOpcode::G_AND &&
5080 "Valid conjunction/disjunction tree");
5081 assert(!Negate && "Valid conjunction/disjunction tree");
5082
5083 NegateL = false;
5084 NegateR = false;
5085 NegateAfterR = false;
5086 NegateAfterAll = false;
5087 }
5088
5089 // Emit sub-trees.
5090 AArch64CC::CondCode RHSCC;
5091 MachineInstr *CmpR =
5092 emitConjunctionRec(RHS, RHSCC, NegateR, CCOp, Predicate, MIB);
5093 if (NegateAfterR)
5094 RHSCC = AArch64CC::getInvertedCondCode(RHSCC);
5095 MachineInstr *CmpL = emitConjunctionRec(
5096 LHS, OutCC, NegateL, CmpR->getOperand(0).getReg(), RHSCC, MIB);
5097 if (NegateAfterAll)
5098 OutCC = AArch64CC::getInvertedCondCode(OutCC);
5099 return CmpL;
5100}
5101
5102MachineInstr *AArch64InstructionSelector::emitConjunction(
5103 Register Val, AArch64CC::CondCode &OutCC, MachineIRBuilder &MIB) const {
5104 bool DummyCanNegate;
5105 bool DummyMustBeFirst;
5106 if (!canEmitConjunction(Val, DummyCanNegate, DummyMustBeFirst, false,
5107 *MIB.getMRI()))
5108 return nullptr;
5109 return emitConjunctionRec(Val, OutCC, false, Register(), AArch64CC::AL, MIB);
5110}
5111
5112bool AArch64InstructionSelector::tryOptSelectConjunction(GSelect &SelI,
5113 MachineInstr &CondMI) {
5114 AArch64CC::CondCode AArch64CC;
5115 MachineInstr *ConjMI = emitConjunction(SelI.getCondReg(), AArch64CC, MIB);
5116 if (!ConjMI)
5117 return false;
5118
5119 emitSelect(SelI.getReg(0), SelI.getTrueReg(), SelI.getFalseReg(), AArch64CC, MIB);
5120 SelI.eraseFromParent();
5121 return true;
5122}
5123
5124bool AArch64InstructionSelector::tryOptSelect(GSelect &I) {
5125 MachineRegisterInfo &MRI = *MIB.getMRI();
5126 // We want to recognize this pattern:
5127 //
5128 // $z = G_FCMP pred, $x, $y
5129 // ...
5130 // $w = G_SELECT $z, $a, $b
5131 //
5132 // Where the value of $z is *only* ever used by the G_SELECT (possibly with
5133 // some copies/truncs in between.)
5134 //
5135 // If we see this, then we can emit something like this:
5136 //
5137 // fcmp $x, $y
5138 // fcsel $w, $a, $b, pred
5139 //
5140 // Rather than emitting both of the rather long sequences in the standard
5141 // G_FCMP/G_SELECT select methods.
5142
5143 // First, check if the condition is defined by a compare.
5144 MachineInstr *CondDef = MRI.getVRegDef(I.getOperand(1).getReg());
5145
5146 // We can only fold if all of the defs have one use.
5147 Register CondDefReg = CondDef->getOperand(0).getReg();
5148 if (!MRI.hasOneNonDBGUse(CondDefReg)) {
5149 // Unless it's another select.
5150 for (const MachineInstr &UI : MRI.use_nodbg_instructions(CondDefReg)) {
5151 if (CondDef == &UI)
5152 continue;
5153 if (UI.getOpcode() != TargetOpcode::G_SELECT)
5154 return false;
5155 }
5156 }
5157
5158 // Is the condition defined by a compare?
5159 unsigned CondOpc = CondDef->getOpcode();
5160 if (CondOpc != TargetOpcode::G_ICMP && CondOpc != TargetOpcode::G_FCMP) {
5161 if (tryOptSelectConjunction(I, *CondDef))
5162 return true;
5163 return false;
5164 }
5165
5167 if (CondOpc == TargetOpcode::G_ICMP) {
5168 auto &PredOp = CondDef->getOperand(1);
5169 emitIntegerCompare(CondDef->getOperand(2), CondDef->getOperand(3), PredOp,
5170 MIB);
5171 auto Pred = static_cast<CmpInst::Predicate>(PredOp.getPredicate());
5172 CondCode =
5174 } else {
5175 // Get the condition code for the select.
5176 auto Pred =
5177 static_cast<CmpInst::Predicate>(CondDef->getOperand(1).getPredicate());
5178 AArch64CC::CondCode CondCode2;
5179 changeFCMPPredToAArch64CC(Pred, CondCode, CondCode2);
5180
5181 // changeFCMPPredToAArch64CC sets CondCode2 to AL when we require two
5182 // instructions to emit the comparison.
5183 // TODO: Handle FCMP_UEQ and FCMP_ONE. After that, this check will be
5184 // unnecessary.
5185 if (CondCode2 != AArch64CC::AL)
5186 return false;
5187
5188 if (!emitFPCompare(CondDef->getOperand(2).getReg(),
5189 CondDef->getOperand(3).getReg(), MIB)) {
5190 LLVM_DEBUG(dbgs() << "Couldn't emit compare for select!\n");
5191 return false;
5192 }
5193 }
5194
5195 // Emit the select.
5196 emitSelect(I.getOperand(0).getReg(), I.getOperand(2).getReg(),
5197 I.getOperand(3).getReg(), CondCode, MIB);
5198 I.eraseFromParent();
5199 return true;
5200}
5201
5202MachineInstr *AArch64InstructionSelector::tryFoldIntegerCompare(
5203 MachineOperand &LHS, MachineOperand &RHS, MachineOperand &Predicate,
5204 MachineIRBuilder &MIRBuilder) const {
5205 assert(LHS.isReg() && RHS.isReg() && Predicate.isPredicate() &&
5206 "Unexpected MachineOperand");
5207 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
5208 // We want to find this sort of thing:
5209 // x = G_SUB 0, y
5210 // G_ICMP z, x
5211 //
5212 // In this case, we can fold the G_SUB into the G_ICMP using a CMN instead.
5213 // e.g:
5214 //
5215 // cmn z, y
5216
5217 // Check if the RHS or LHS of the G_ICMP is defined by a SUB
5218 MachineInstr *LHSDef = getDefIgnoringCopies(LHS.getReg(), MRI);
5219 MachineInstr *RHSDef = getDefIgnoringCopies(RHS.getReg(), MRI);
5220 auto P = static_cast<CmpInst::Predicate>(Predicate.getPredicate());
5221
5222 // Given this:
5223 //
5224 // x = G_SUB 0, y
5225 // G_ICMP z, x
5226 //
5227 // Produce this:
5228 //
5229 // cmn z, y
5230 if (isCMN(RHSDef, P, MRI))
5231 return emitCMN(LHS, RHSDef->getOperand(2), MIRBuilder);
5232
5233 // Same idea here, but with the LHS of the compare instead:
5234 //
5235 // Given this:
5236 //
5237 // x = G_SUB 0, y
5238 // G_ICMP x, z
5239 //
5240 // Produce this:
5241 //
5242 // cmn y, z
5243 //
5244 // But be careful! We need to swap the predicate!
5245 if (isCMN(LHSDef, P, MRI)) {
5246 if (!CmpInst::isEquality(P)) {
5249 }
5250 return emitCMN(LHSDef->getOperand(2), RHS, MIRBuilder);
5251 }
5252
5253 // Given this:
5254 //
5255 // z = G_AND x, y
5256 // G_ICMP z, 0
5257 //
5258 // Produce this if the compare is signed:
5259 //
5260 // tst x, y
5261 if (!CmpInst::isUnsigned(P) && LHSDef &&
5262 LHSDef->getOpcode() == TargetOpcode::G_AND) {
5263 // Make sure that the RHS is 0.
5264 auto ValAndVReg = getIConstantVRegValWithLookThrough(RHS.getReg(), MRI);
5265 if (!ValAndVReg || ValAndVReg->Value != 0)
5266 return nullptr;
5267
5268 return emitTST(LHSDef->getOperand(1),
5269 LHSDef->getOperand(2), MIRBuilder);
5270 }
5271
5272 return nullptr;
5273}
5274
5275bool AArch64InstructionSelector::selectShuffleVector(
5276 MachineInstr &I, MachineRegisterInfo &MRI) {
5277 const LLT DstTy = MRI.getType(I.getOperand(0).getReg());
5278 Register Src1Reg = I.getOperand(1).getReg();
5279 Register Src2Reg = I.getOperand(2).getReg();
5280 ArrayRef<int> Mask = I.getOperand(3).getShuffleMask();
5281 assert(DstTy == MRI.getType(Src1Reg) &&
5282 "Expected equal shuffle types during selection");
5283
5284 MachineBasicBlock &MBB = *I.getParent();
5285 MachineFunction &MF = *MBB.getParent();
5286 LLVMContext &Ctx = MF.getFunction().getContext();
5287
5288 unsigned BytesPerElt = DstTy.getElementType().getSizeInBits() / 8;
5289 int NumElts = DstTy.getNumElements();
5290
5291 SmallVector<int> NewMask;
5292 bool FirstUsed = false;
5293 bool SecondUsed = false;
5294 for (int M : Mask) {
5295 // Map any undef or zero lanes to 255.
5296 if (M < 0 || VT->getKnownBits(M < NumElts ? Src1Reg : Src2Reg,
5297 APInt::getOneBitSet(NumElts, M % NumElts))
5298 .isZero()) {
5299 for (unsigned Byte = 0; Byte < BytesPerElt; ++Byte)
5300 NewMask.push_back(255);
5301 continue;
5302 }
5303
5304 FirstUsed |= M < NumElts;
5305 SecondUsed |= M >= NumElts;
5306 for (unsigned Byte = 0; Byte < BytesPerElt; ++Byte) {
5307 unsigned Offset = Byte + M * BytesPerElt;
5308 NewMask.push_back(Offset);
5309 }
5310 }
5311
5312 // If the first is unused or all zeros, use the second src in a tbl1.
5313 if (!FirstUsed) {
5314 int ByteLanes = DstTy.getSizeInBits() == 128 ? 16 : 8;
5315 for (int &M : NewMask) {
5316 if (M != 255) {
5317 assert(M >= ByteLanes && M < 2 * ByteLanes);
5318 M -= ByteLanes;
5319 }
5320 }
5321 std::swap(Src1Reg, Src2Reg);
5322 std::swap(FirstUsed, SecondUsed);
5323 }
5324
5325 // Use a constant pool to load the index vector for TBL.
5327 transform(NewMask, std::back_inserter(CstIdxs), [&Ctx](int M) {
5328 return ConstantInt::get(Type::getInt8Ty(Ctx), M);
5329 });
5330 Constant *CPVal = ConstantVector::get(CstIdxs);
5331 MachineInstr *IndexLoad = emitLoadFromConstantPool(CPVal, MIB);
5332 if (!IndexLoad) {
5333 LLVM_DEBUG(dbgs() << "Could not load from a constant pool");
5334 return false;
5335 }
5336
5337 if (DstTy.getSizeInBits() != 128) {
5338 assert(DstTy.getSizeInBits() == 64 && "Unexpected shuffle result ty");
5339 // This case can be done with TBL1.
5340 MachineInstr *Concat =
5341 emitVectorConcat(std::nullopt, Src1Reg, Src2Reg, MIB);
5342 if (!Concat) {
5343 LLVM_DEBUG(dbgs() << "Could not do vector concat for tbl1");
5344 return false;
5345 }
5346
5347 // The constant pool load will be 64 bits, so need to convert to FPR128 reg.
5348 IndexLoad = emitScalarToVector(64, &AArch64::FPR128RegClass,
5349 IndexLoad->getOperand(0).getReg(), MIB);
5350
5351 auto TBL1 = MIB.buildInstr(
5352 AArch64::TBLv16i8One, {&AArch64::FPR128RegClass},
5353 {Concat->getOperand(0).getReg(), IndexLoad->getOperand(0).getReg()});
5355
5356 auto Copy =
5357 MIB.buildInstr(TargetOpcode::COPY, {I.getOperand(0).getReg()}, {})
5358 .addReg(TBL1.getReg(0), {}, AArch64::dsub);
5359 RBI.constrainGenericRegister(Copy.getReg(0), AArch64::FPR64RegClass, MRI);
5360 I.eraseFromParent();
5361 return true;
5362 }
5363
5364 if (!SecondUsed) {
5365 auto TBL1 = MIB.buildInstr(AArch64::TBLv16i8One, {I.getOperand(0)},
5366 {Src1Reg, IndexLoad->getOperand(0)});
5368 I.eraseFromParent();
5369 return true;
5370 }
5371
5372 // For TBL2 we need to emit a REG_SEQUENCE to tie together two consecutive
5373 // Q registers for regalloc.
5374 SmallVector<Register, 2> Regs = {Src1Reg, Src2Reg};
5375 auto RegSeq = createQTuple(Regs, MIB);
5376 auto TBL2 = MIB.buildInstr(AArch64::TBLv16i8Two, {I.getOperand(0)},
5377 {RegSeq, IndexLoad->getOperand(0)});
5379 I.eraseFromParent();
5380 return true;
5381}
5382
5383MachineInstr *AArch64InstructionSelector::emitLaneInsert(
5384 std::optional<Register> DstReg, Register SrcReg, Register EltReg,
5385 unsigned LaneIdx, const RegisterBank &RB,
5386 MachineIRBuilder &MIRBuilder) const {
5387 MachineInstr *InsElt = nullptr;
5388 const TargetRegisterClass *DstRC = &AArch64::FPR128RegClass;
5389 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
5390
5391 // Create a register to define with the insert if one wasn't passed in.
5392 if (!DstReg)
5393 DstReg = MRI.createVirtualRegister(DstRC);
5394
5395 unsigned EltSize = MRI.getType(EltReg).getSizeInBits();
5396 unsigned Opc = getInsertVecEltOpInfo(RB, EltSize).first;
5397
5398 if (RB.getID() == AArch64::FPRRegBankID) {
5399 auto InsSub = emitScalarToVector(EltSize, DstRC, EltReg, MIRBuilder);
5400 InsElt = MIRBuilder.buildInstr(Opc, {*DstReg}, {SrcReg})
5401 .addImm(LaneIdx)
5402 .addUse(InsSub->getOperand(0).getReg())
5403 .addImm(0);
5404 } else {
5405 InsElt = MIRBuilder.buildInstr(Opc, {*DstReg}, {SrcReg})
5406 .addImm(LaneIdx)
5407 .addUse(EltReg);
5408 }
5409
5411 return InsElt;
5412}
5413
5414bool AArch64InstructionSelector::selectUSMovFromExtend(
5415 MachineInstr &MI, MachineRegisterInfo &MRI) {
5416 if (MI.getOpcode() != TargetOpcode::G_SEXT &&
5417 MI.getOpcode() != TargetOpcode::G_ZEXT &&
5418 MI.getOpcode() != TargetOpcode::G_ANYEXT)
5419 return false;
5420 bool IsSigned = MI.getOpcode() == TargetOpcode::G_SEXT;
5421 const Register DefReg = MI.getOperand(0).getReg();
5422 const LLT DstTy = MRI.getType(DefReg);
5423 unsigned DstSize = DstTy.getSizeInBits();
5424
5425 if (DstSize != 32 && DstSize != 64)
5426 return false;
5427
5428 MachineInstr *Extract = getOpcodeDef(TargetOpcode::G_EXTRACT_VECTOR_ELT,
5429 MI.getOperand(1).getReg(), MRI);
5430 int64_t Lane;
5431 if (!Extract || !mi_match(Extract->getOperand(2).getReg(), MRI, m_ICst(Lane)))
5432 return false;
5433 Register Src0 = Extract->getOperand(1).getReg();
5434
5435 const LLT VecTy = MRI.getType(Src0);
5436 if (VecTy.isScalableVector())
5437 return false;
5438
5439 if (VecTy.getSizeInBits() != 128) {
5440 const MachineInstr *ScalarToVector = emitScalarToVector(
5441 VecTy.getSizeInBits(), &AArch64::FPR128RegClass, Src0, MIB);
5442 assert(ScalarToVector && "Didn't expect emitScalarToVector to fail!");
5443 Src0 = ScalarToVector->getOperand(0).getReg();
5444 }
5445
5446 unsigned Opcode;
5447 if (DstSize == 64 && VecTy.getScalarSizeInBits() == 32)
5448 Opcode = IsSigned ? AArch64::SMOVvi32to64 : AArch64::UMOVvi32;
5449 else if (DstSize == 64 && VecTy.getScalarSizeInBits() == 16)
5450 Opcode = IsSigned ? AArch64::SMOVvi16to64 : AArch64::UMOVvi16;
5451 else if (DstSize == 64 && VecTy.getScalarSizeInBits() == 8)
5452 Opcode = IsSigned ? AArch64::SMOVvi8to64 : AArch64::UMOVvi8;
5453 else if (DstSize == 32 && VecTy.getScalarSizeInBits() == 16)
5454 Opcode = IsSigned ? AArch64::SMOVvi16to32 : AArch64::UMOVvi16;
5455 else if (DstSize == 32 && VecTy.getScalarSizeInBits() == 8)
5456 Opcode = IsSigned ? AArch64::SMOVvi8to32 : AArch64::UMOVvi8;
5457 else
5458 llvm_unreachable("Unexpected type combo for S/UMov!");
5459
5460 // We may need to generate one of these, depending on the type and sign of the
5461 // input:
5462 // DstReg = SMOV Src0, Lane;
5463 // NewReg = UMOV Src0, Lane; DstReg = SUBREG_TO_REG NewReg, sub_32;
5464 MachineInstr *ExtI = nullptr;
5465 if (DstSize == 64 && !IsSigned) {
5466 Register NewReg = MRI.createVirtualRegister(&AArch64::GPR32RegClass);
5467 MIB.buildInstr(Opcode, {NewReg}, {Src0}).addImm(Lane);
5468 ExtI = MIB.buildInstr(AArch64::SUBREG_TO_REG, {DefReg}, {})
5469 .addUse(NewReg)
5470 .addImm(AArch64::sub_32);
5471 RBI.constrainGenericRegister(DefReg, AArch64::GPR64RegClass, MRI);
5472 } else
5473 ExtI = MIB.buildInstr(Opcode, {DefReg}, {Src0}).addImm(Lane);
5474
5476 MI.eraseFromParent();
5477 return true;
5478}
5479
5480bool AArch64InstructionSelector::selectIndexedExtLoad(
5481 MachineInstr &MI, MachineRegisterInfo &MRI) {
5482 auto &ExtLd = cast<GIndexedAnyExtLoad>(MI);
5483 Register Dst = ExtLd.getDstReg();
5484 Register WriteBack = ExtLd.getWritebackReg();
5485 Register Base = ExtLd.getBaseReg();
5486 Register Offset = ExtLd.getOffsetReg();
5487 LLT Ty = MRI.getType(Dst);
5488 assert(Ty.getSizeInBits() <= 64); // Only for scalar GPRs.
5489 unsigned MemSizeBits = ExtLd.getMMO().getMemoryType().getSizeInBits();
5490 bool IsPre = ExtLd.isPre();
5491 bool IsSExt = isa<GIndexedSExtLoad>(ExtLd);
5492 unsigned InsertIntoSubReg = 0;
5493 bool IsDst64 = Ty.getSizeInBits() == 64;
5494
5495 // ZExt/SExt should be on gpr but can handle extload and zextload of fpr, so
5496 // long as they are scalar.
5497 bool IsFPR = RBI.getRegBank(Dst, MRI, TRI)->getID() == AArch64::FPRRegBankID;
5498 if ((IsSExt && IsFPR) || Ty.isVector())
5499 return false;
5500
5501 unsigned Opc = 0;
5502 LLT NewLdDstTy;
5503 LLT s32 = LLT::scalar(32);
5504 LLT s64 = LLT::scalar(64);
5505
5506 if (MemSizeBits == 8) {
5507 if (IsSExt) {
5508 if (IsDst64)
5509 Opc = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost;
5510 else
5511 Opc = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost;
5512 NewLdDstTy = IsDst64 ? s64 : s32;
5513 } else if (IsFPR) {
5514 Opc = IsPre ? AArch64::LDRBpre : AArch64::LDRBpost;
5515 InsertIntoSubReg = AArch64::bsub;
5516 NewLdDstTy = LLT::scalar(MemSizeBits);
5517 } else {
5518 Opc = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost;
5519 InsertIntoSubReg = IsDst64 ? AArch64::sub_32 : 0;
5520 NewLdDstTy = s32;
5521 }
5522 } else if (MemSizeBits == 16) {
5523 if (IsSExt) {
5524 if (IsDst64)
5525 Opc = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost;
5526 else
5527 Opc = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost;
5528 NewLdDstTy = IsDst64 ? s64 : s32;
5529 } else if (IsFPR) {
5530 Opc = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
5531 InsertIntoSubReg = AArch64::hsub;
5532 NewLdDstTy = LLT::scalar(MemSizeBits);
5533 } else {
5534 Opc = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost;
5535 InsertIntoSubReg = IsDst64 ? AArch64::sub_32 : 0;
5536 NewLdDstTy = s32;
5537 }
5538 } else if (MemSizeBits == 32) {
5539 if (IsSExt) {
5540 Opc = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost;
5541 NewLdDstTy = s64;
5542 } else if (IsFPR) {
5543 Opc = IsPre ? AArch64::LDRSpre : AArch64::LDRSpost;
5544 InsertIntoSubReg = AArch64::ssub;
5545 NewLdDstTy = LLT::scalar(MemSizeBits);
5546 } else {
5547 Opc = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
5548 InsertIntoSubReg = IsDst64 ? AArch64::sub_32 : 0;
5549 NewLdDstTy = s32;
5550 }
5551 } else {
5552 llvm_unreachable("Unexpected size for indexed load");
5553 }
5554
5555 auto Cst = getIConstantVRegVal(Offset, MRI);
5556 if (!Cst)
5557 return false; // Shouldn't happen, but just in case.
5558
5559 auto LdMI = MIB.buildInstr(Opc, {WriteBack, NewLdDstTy}, {Base})
5560 .addImm(Cst->getSExtValue());
5561 LdMI.cloneMemRefs(ExtLd);
5563 // Make sure to select the load with the MemTy as the dest type, and then
5564 // insert into a larger reg if needed.
5565 if (InsertIntoSubReg) {
5566 // Generate a SUBREG_TO_REG.
5567 auto SubToReg = MIB.buildInstr(TargetOpcode::SUBREG_TO_REG, {Dst}, {})
5568 .addUse(LdMI.getReg(1))
5569 .addImm(InsertIntoSubReg);
5571 SubToReg.getReg(0),
5572 *getRegClassForTypeOnBank(MRI.getType(Dst),
5573 *RBI.getRegBank(Dst, MRI, TRI)),
5574 MRI);
5575 } else {
5576 auto Copy = MIB.buildCopy(Dst, LdMI.getReg(1));
5577 selectCopy(*Copy, TII, MRI, TRI, RBI);
5578 }
5579 MI.eraseFromParent();
5580
5581 return true;
5582}
5583
5584bool AArch64InstructionSelector::selectIndexedLoad(MachineInstr &MI,
5585 MachineRegisterInfo &MRI) {
5586 auto &Ld = cast<GIndexedLoad>(MI);
5587 Register Dst = Ld.getDstReg();
5588 Register WriteBack = Ld.getWritebackReg();
5589 Register Base = Ld.getBaseReg();
5590 Register Offset = Ld.getOffsetReg();
5591 assert(MRI.getType(Dst).getSizeInBits() <= 128 &&
5592 "Unexpected type for indexed load");
5593 unsigned MemSize = Ld.getMMO().getMemoryType().getSizeInBytes();
5594
5595 if (MemSize < MRI.getType(Dst).getSizeInBytes())
5596 return selectIndexedExtLoad(MI, MRI);
5597
5598 unsigned Opc = 0;
5599 if (Ld.isPre()) {
5600 static constexpr unsigned GPROpcodes[] = {
5601 AArch64::LDRBBpre, AArch64::LDRHHpre, AArch64::LDRWpre,
5602 AArch64::LDRXpre};
5603 static constexpr unsigned FPROpcodes[] = {
5604 AArch64::LDRBpre, AArch64::LDRHpre, AArch64::LDRSpre, AArch64::LDRDpre,
5605 AArch64::LDRQpre};
5606 Opc = (RBI.getRegBank(Dst, MRI, TRI)->getID() == AArch64::FPRRegBankID)
5607 ? FPROpcodes[Log2_32(MemSize)]
5608 : GPROpcodes[Log2_32(MemSize)];
5609 ;
5610 } else {
5611 static constexpr unsigned GPROpcodes[] = {
5612 AArch64::LDRBBpost, AArch64::LDRHHpost, AArch64::LDRWpost,
5613 AArch64::LDRXpost};
5614 static constexpr unsigned FPROpcodes[] = {
5615 AArch64::LDRBpost, AArch64::LDRHpost, AArch64::LDRSpost,
5616 AArch64::LDRDpost, AArch64::LDRQpost};
5617 Opc = (RBI.getRegBank(Dst, MRI, TRI)->getID() == AArch64::FPRRegBankID)
5618 ? FPROpcodes[Log2_32(MemSize)]
5619 : GPROpcodes[Log2_32(MemSize)];
5620 ;
5621 }
5622 auto Cst = getIConstantVRegVal(Offset, MRI);
5623 if (!Cst)
5624 return false; // Shouldn't happen, but just in case.
5625 auto LdMI =
5626 MIB.buildInstr(Opc, {WriteBack, Dst}, {Base}).addImm(Cst->getSExtValue());
5627 LdMI.cloneMemRefs(Ld);
5629 MI.eraseFromParent();
5630 return true;
5631}
5632
5633bool AArch64InstructionSelector::selectIndexedStore(GIndexedStore &I,
5634 MachineRegisterInfo &MRI) {
5635 Register Dst = I.getWritebackReg();
5636 Register Val = I.getValueReg();
5637 Register Base = I.getBaseReg();
5638 Register Offset = I.getOffsetReg();
5639 assert(MRI.getType(Val).getSizeInBits() <= 128 &&
5640 "Unexpected type for indexed store");
5641
5642 LocationSize MemSize = I.getMMO().getSize();
5643 unsigned MemSizeInBytes = MemSize.getValue();
5644
5645 assert(MemSizeInBytes && MemSizeInBytes <= 16 &&
5646 "Unexpected indexed store size");
5647 unsigned MemSizeLog2 = Log2_32(MemSizeInBytes);
5648
5649 unsigned Opc = 0;
5650 if (I.isPre()) {
5651 static constexpr unsigned GPROpcodes[] = {
5652 AArch64::STRBBpre, AArch64::STRHHpre, AArch64::STRWpre,
5653 AArch64::STRXpre};
5654 static constexpr unsigned FPROpcodes[] = {
5655 AArch64::STRBpre, AArch64::STRHpre, AArch64::STRSpre, AArch64::STRDpre,
5656 AArch64::STRQpre};
5657
5658 if (RBI.getRegBank(Val, MRI, TRI)->getID() == AArch64::FPRRegBankID)
5659 Opc = FPROpcodes[MemSizeLog2];
5660 else
5661 Opc = GPROpcodes[MemSizeLog2];
5662 } else {
5663 static constexpr unsigned GPROpcodes[] = {
5664 AArch64::STRBBpost, AArch64::STRHHpost, AArch64::STRWpost,
5665 AArch64::STRXpost};
5666 static constexpr unsigned FPROpcodes[] = {
5667 AArch64::STRBpost, AArch64::STRHpost, AArch64::STRSpost,
5668 AArch64::STRDpost, AArch64::STRQpost};
5669
5670 if (RBI.getRegBank(Val, MRI, TRI)->getID() == AArch64::FPRRegBankID)
5671 Opc = FPROpcodes[MemSizeLog2];
5672 else
5673 Opc = GPROpcodes[MemSizeLog2];
5674 }
5675
5676 auto Cst = getIConstantVRegVal(Offset, MRI);
5677 if (!Cst)
5678 return false; // Shouldn't happen, but just in case.
5679 auto Str =
5680 MIB.buildInstr(Opc, {Dst}, {Val, Base}).addImm(Cst->getSExtValue());
5681 Str.cloneMemRefs(I);
5683 I.eraseFromParent();
5684 return true;
5685}
5686
5687MachineInstr *
5688AArch64InstructionSelector::emitConstantMOVVector(DstOp Dst, APInt Imm,
5689 MachineRegisterInfo &MRI) {
5690 unsigned DstSize = Imm.getBitWidth();
5691 assert((DstSize == 64 || DstSize == 128) &&
5692 "Unexpected vector constant size");
5693
5695 if (AArch64_IMM::expandVectorMOVImm(Imm, Insns, STI)) {
5696 for (AArch64_IMM::ImmInsnModel Insn : Insns) {
5697 switch (Insn.Opcode) {
5698 case AArch64::FMOVD0: {
5699 // Currently emit a MOVIv2d_ns in both cases to match SDAG.
5700 auto Mov =
5701 MIB.buildInstr(
5702 AArch64::MOVIv2d_ns,
5703 {DstSize == 128 ? Dst : DstOp(&AArch64::FPR128RegClass)}, {})
5704 .addImm(0);
5706 if (DstSize != 128) {
5707 Mov = MIB.buildInstr(TargetOpcode::COPY, {Dst}, {})
5708 .addReg(Mov.getReg(0), {}, AArch64::dsub);
5709 RBI.constrainGenericRegister(Mov.getReg(0), AArch64::FPR64RegClass,
5710 MRI);
5711 }
5712 return &*Mov;
5713 }
5714 case AArch64::FMOVDi:
5715 case AArch64::FMOVv2f32_ns:
5716 case AArch64::FMOVv2f64_ns:
5717 case AArch64::FMOVv4f32_ns:
5718 case AArch64::FMOVv4f16_ns:
5719 case AArch64::FMOVv8f16_ns:
5720 case AArch64::MOVID:
5721 case AArch64::MOVIv16b_ns:
5722 case AArch64::MOVIv2d_ns:
5723 case AArch64::MOVIv2i32:
5724 case AArch64::MOVIv2s_msl:
5725 case AArch64::MOVIv4i16:
5726 case AArch64::MOVIv4i32:
5727 case AArch64::MOVIv4s_msl:
5728 case AArch64::MOVIv8b_ns:
5729 case AArch64::MOVIv8i16:
5730 case AArch64::MVNIv2i32:
5731 case AArch64::MVNIv2s_msl:
5732 case AArch64::MVNIv4i16:
5733 case AArch64::MVNIv4i32:
5734 case AArch64::MVNIv4s_msl:
5735 case AArch64::MVNIv8i16: {
5736 auto Mov = MIB.buildInstr(Insn.Opcode, {Dst}, {});
5737 if (Insn.Op1)
5738 Mov.addImm(*Insn.Op1);
5739 if (Insn.Op2)
5740 Mov.addImm(*Insn.Op2);
5742 return &*Mov;
5743 }
5744 case AArch64::DUPM_ZI: {
5745 auto Mov = MIB.buildInstr(Insn.Opcode, {&AArch64::ZPRRegClass}, {})
5746 .addImm(*Insn.Op1);
5748 Mov = MIB.buildInstr(TargetOpcode::COPY, {Dst}, {})
5749 .addReg(Mov.getReg(0), {},
5750 DstSize == 64 ? AArch64::dsub : AArch64::zsub);
5751 RBI.constrainGenericRegister(Mov.getReg(0),
5752 DstSize == 64 ? AArch64::FPR64RegClass
5753 : AArch64::FPR128RegClass,
5754 MRI);
5755 return &*Mov;
5756 }
5757 case AArch64::DUP_ZI_D: {
5758 auto Mov = MIB.buildInstr(Insn.Opcode, {&AArch64::ZPRRegClass}, {})
5759 .addImm(*Insn.Op1)
5760 .addImm(*Insn.Op2);
5762 Mov = MIB.buildInstr(TargetOpcode::COPY, {Dst}, {})
5763 .addReg(Mov.getReg(0), {},
5764 DstSize == 64 ? AArch64::dsub : AArch64::zsub);
5765 RBI.constrainGenericRegister(Mov.getReg(0),
5766 DstSize == 64 ? AArch64::FPR64RegClass
5767 : AArch64::FPR128RegClass,
5768 MRI);
5769 return &*Mov;
5770 }
5771 default:
5772 llvm_unreachable("Unexpected node in expandVectorMOVImm\n");
5773 }
5774 }
5775 }
5776 return nullptr;
5777}
5778
5779MachineInstr *AArch64InstructionSelector::emitConstantVector(
5780 Register Dst, Constant *CV, APInt Imm, MachineRegisterInfo &MRI) {
5781 if (auto *MovI = emitConstantMOVVector(Dst, Imm, MRI))
5782 return MovI;
5783
5784 auto *CPLoad = emitLoadFromConstantPool(CV, MIB);
5785 if (!CPLoad) {
5786 LLVM_DEBUG(dbgs() << "Could not generate cp load for constant vector!");
5787 return nullptr;
5788 }
5789
5790 auto Copy = MIB.buildCopy(Dst, CPLoad->getOperand(0));
5792 Dst, *MRI.getRegClass(CPLoad->getOperand(0).getReg()), MRI);
5793 return &*Copy;
5794}
5795
5796bool AArch64InstructionSelector::tryOptConstantBuildVec(
5797 MachineInstr &I, LLT DstTy, MachineRegisterInfo &MRI) {
5798 assert(I.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
5799 unsigned DstSize = DstTy.getSizeInBits();
5800 assert(DstSize <= 128 && "Unexpected build_vec type!");
5801 if (DstSize < 32)
5802 return false;
5803 // Check if we're building a constant vector, in which case we want to
5804 // generate a constant pool load instead of a vector insert sequence.
5806 APInt Imm(DstSize, 0);
5807 for (unsigned Idx = 1; Idx < I.getNumOperands(); ++Idx) {
5808 Register OpReg = I.getOperand(Idx).getReg();
5809 if (auto AnyConst = getAnyConstantVRegValWithLookThrough(
5810 OpReg, MRI, /*LookThroughInstrs=*/true,
5811 /*LookThroughAnyExt=*/true)) {
5812 MachineInstr *DefMI = MRI.getVRegDef(AnyConst->VReg);
5813 Imm |= AnyConst->Value.trunc(DstTy.getScalarSizeInBits())
5814 .zext(DstSize)
5815 .shl((Idx - 1) * DstTy.getScalarSizeInBits());
5816
5817 if (DefMI->getOpcode() == TargetOpcode::G_CONSTANT) {
5818 Csts.emplace_back(
5819 ConstantInt::get(MIB.getMF().getFunction().getContext(),
5820 std::move(AnyConst->Value)));
5821 continue;
5822 }
5823
5824 if (DefMI->getOpcode() == TargetOpcode::G_FCONSTANT) {
5825 Csts.emplace_back(
5826 const_cast<ConstantFP *>(DefMI->getOperand(1).getFPImm()));
5827 continue;
5828 }
5829 }
5830 return false;
5831 }
5832 Constant *CV = ConstantVector::get(Csts);
5833 if (!emitConstantVector(I.getOperand(0).getReg(), CV, Imm, MRI))
5834 return false;
5835 I.eraseFromParent();
5836 return true;
5837}
5838
5839bool AArch64InstructionSelector::tryOptBuildVecToSubregToReg(
5840 MachineInstr &I, MachineRegisterInfo &MRI) {
5841 // Given:
5842 // %vec = G_BUILD_VECTOR %elt, %undef, %undef, ... %undef
5843 //
5844 // Select the G_BUILD_VECTOR as a SUBREG_TO_REG from %elt.
5845 Register Dst = I.getOperand(0).getReg();
5846 Register EltReg = I.getOperand(1).getReg();
5847 LLT EltTy = MRI.getType(EltReg);
5848 // If the index isn't on the same bank as its elements, then this can't be a
5849 // SUBREG_TO_REG.
5850 const RegisterBank &EltRB = *RBI.getRegBank(EltReg, MRI, TRI);
5851 const RegisterBank &DstRB = *RBI.getRegBank(Dst, MRI, TRI);
5852 if (EltRB != DstRB)
5853 return false;
5854 if (any_of(drop_begin(I.operands(), 2), [&MRI](const MachineOperand &Op) {
5855 return !getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Op.getReg(), MRI);
5856 }))
5857 return false;
5858 unsigned SubReg;
5859 const TargetRegisterClass *EltRC = getRegClassForTypeOnBank(EltTy, EltRB);
5860 if (!EltRC)
5861 return false;
5862 const TargetRegisterClass *DstRC =
5863 getRegClassForTypeOnBank(MRI.getType(Dst), DstRB);
5864 if (!DstRC)
5865 return false;
5866 if (!getSubRegForClass(EltRC, TRI, SubReg))
5867 return false;
5868 auto SubregToReg = MIB.buildInstr(AArch64::SUBREG_TO_REG, {Dst}, {})
5869 .addUse(EltReg)
5870 .addImm(SubReg);
5871 I.eraseFromParent();
5872 constrainSelectedInstRegOperands(*SubregToReg, TII, TRI, RBI);
5873 return RBI.constrainGenericRegister(Dst, *DstRC, MRI);
5874}
5875
5876bool AArch64InstructionSelector::selectBuildVector(MachineInstr &I,
5877 MachineRegisterInfo &MRI) {
5878 assert(I.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
5879 // Until we port more of the optimized selections, for now just use a vector
5880 // insert sequence.
5881 const LLT DstTy = MRI.getType(I.getOperand(0).getReg());
5882 const LLT EltTy = MRI.getType(I.getOperand(1).getReg());
5883 unsigned EltSize = EltTy.getSizeInBits();
5884
5885 if (tryOptConstantBuildVec(I, DstTy, MRI))
5886 return true;
5887 if (tryOptBuildVecToSubregToReg(I, MRI))
5888 return true;
5889
5890 if (EltSize != 8 && EltSize != 16 && EltSize != 32 && EltSize != 64)
5891 return false; // Don't support all element types yet.
5892 const RegisterBank &RB = *RBI.getRegBank(I.getOperand(1).getReg(), MRI, TRI);
5893
5894 const TargetRegisterClass *DstRC = &AArch64::FPR128RegClass;
5895 MachineInstr *ScalarToVec =
5896 emitScalarToVector(DstTy.getElementType().getSizeInBits(), DstRC,
5897 I.getOperand(1).getReg(), MIB);
5898 if (!ScalarToVec)
5899 return false;
5900
5901 Register DstVec = ScalarToVec->getOperand(0).getReg();
5902 unsigned DstSize = DstTy.getSizeInBits();
5903
5904 // Keep track of the last MI we inserted. Later on, we might be able to save
5905 // a copy using it.
5906 MachineInstr *PrevMI = ScalarToVec;
5907 for (unsigned i = 2, e = DstSize / EltSize + 1; i < e; ++i) {
5908 // Note that if we don't do a subregister copy, we can end up making an
5909 // extra register.
5910 Register OpReg = I.getOperand(i).getReg();
5911 // Do not emit inserts for undefs
5912 if (!getOpcodeDef<GImplicitDef>(OpReg, MRI)) {
5913 PrevMI = &*emitLaneInsert(std::nullopt, DstVec, OpReg, i - 1, RB, MIB);
5914 DstVec = PrevMI->getOperand(0).getReg();
5915 }
5916 }
5917
5918 // If DstTy's size in bits is less than 128, then emit a subregister copy
5919 // from DstVec to the last register we've defined.
5920 if (DstSize < 128) {
5921 // Force this to be FPR using the destination vector.
5922 const TargetRegisterClass *RC =
5923 getRegClassForTypeOnBank(DstTy, *RBI.getRegBank(DstVec, MRI, TRI));
5924 if (!RC)
5925 return false;
5926 if (RC != &AArch64::FPR32RegClass && RC != &AArch64::FPR64RegClass) {
5927 LLVM_DEBUG(dbgs() << "Unsupported register class!\n");
5928 return false;
5929 }
5930
5931 unsigned SubReg = 0;
5932 if (!getSubRegForClass(RC, TRI, SubReg))
5933 return false;
5934 if (SubReg != AArch64::ssub && SubReg != AArch64::dsub) {
5935 LLVM_DEBUG(dbgs() << "Unsupported destination size! (" << DstSize
5936 << "\n");
5937 return false;
5938 }
5939
5941 Register DstReg = I.getOperand(0).getReg();
5942
5943 MIB.buildInstr(TargetOpcode::COPY, {DstReg}, {}).addReg(DstVec, {}, SubReg);
5944 MachineOperand &RegOp = I.getOperand(1);
5945 RegOp.setReg(Reg);
5946 RBI.constrainGenericRegister(DstReg, *RC, MRI);
5947 } else {
5948 // We either have a vector with all elements (except the first one) undef or
5949 // at least one non-undef non-first element. In the first case, we need to
5950 // constrain the output register ourselves as we may have generated an
5951 // INSERT_SUBREG operation which is a generic operation for which the
5952 // output regclass cannot be automatically chosen.
5953 //
5954 // In the second case, there is no need to do this as it may generate an
5955 // instruction like INSvi32gpr where the regclass can be automatically
5956 // chosen.
5957 //
5958 // Also, we save a copy by re-using the destination register on the final
5959 // insert.
5960 PrevMI->getOperand(0).setReg(I.getOperand(0).getReg());
5962
5963 Register DstReg = PrevMI->getOperand(0).getReg();
5964 if (PrevMI == ScalarToVec && DstReg.isVirtual()) {
5965 const TargetRegisterClass *RC =
5966 getRegClassForTypeOnBank(DstTy, *RBI.getRegBank(DstVec, MRI, TRI));
5967 RBI.constrainGenericRegister(DstReg, *RC, MRI);
5968 }
5969 }
5970
5972 return true;
5973}
5974
5975bool AArch64InstructionSelector::selectVectorLoadIntrinsic(unsigned Opc,
5976 unsigned NumVecs,
5977 MachineInstr &I) {
5978 assert(I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS);
5979 assert(Opc && "Expected an opcode?");
5980 assert(NumVecs > 1 && NumVecs < 5 && "Only support 2, 3, or 4 vectors");
5981 auto &MRI = *MIB.getMRI();
5982 LLT Ty = MRI.getType(I.getOperand(0).getReg());
5983 unsigned Size = Ty.getSizeInBits();
5984 assert((Size == 64 || Size == 128) &&
5985 "Destination must be 64 bits or 128 bits?");
5986 unsigned SubReg = Size == 64 ? AArch64::dsub0 : AArch64::qsub0;
5987 auto Ptr = I.getOperand(I.getNumOperands() - 1).getReg();
5988 assert(MRI.getType(Ptr).isPointer() && "Expected a pointer type?");
5989 auto Load = MIB.buildInstr(Opc, {Ty}, {Ptr});
5992 Register SelectedLoadDst = Load->getOperand(0).getReg();
5993 for (unsigned Idx = 0; Idx < NumVecs; ++Idx) {
5994 auto Vec = MIB.buildInstr(TargetOpcode::COPY, {I.getOperand(Idx)}, {})
5995 .addReg(SelectedLoadDst, {}, SubReg + Idx);
5996 // Emit the subreg copies and immediately select them.
5997 // FIXME: We should refactor our copy code into an emitCopy helper and
5998 // clean up uses of this pattern elsewhere in the selector.
5999 selectCopy(*Vec, TII, MRI, TRI, RBI);
6000 }
6001 return true;
6002}
6003
6004bool AArch64InstructionSelector::selectVectorLoadLaneIntrinsic(
6005 unsigned Opc, unsigned NumVecs, MachineInstr &I) {
6006 assert(I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS);
6007 assert(Opc && "Expected an opcode?");
6008 assert(NumVecs > 1 && NumVecs < 5 && "Only support 2, 3, or 4 vectors");
6009 auto &MRI = *MIB.getMRI();
6010 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6011 bool Narrow = Ty.getSizeInBits() == 64;
6012
6013 auto FirstSrcRegIt = I.operands_begin() + NumVecs + 1;
6014 SmallVector<Register, 4> Regs(NumVecs);
6015 std::transform(FirstSrcRegIt, FirstSrcRegIt + NumVecs, Regs.begin(),
6016 [](auto MO) { return MO.getReg(); });
6017
6018 if (Narrow) {
6019 transform(Regs, Regs.begin(), [this](Register Reg) {
6020 return emitScalarToVector(64, &AArch64::FPR128RegClass, Reg, MIB)
6021 ->getOperand(0)
6022 .getReg();
6023 });
6024 Ty = Ty.multiplyElements(2);
6025 }
6026
6027 Register Tuple = createQTuple(Regs, MIB);
6028 auto LaneNo = getIConstantVRegVal((FirstSrcRegIt + NumVecs)->getReg(), MRI);
6029 if (!LaneNo)
6030 return false;
6031
6032 Register Ptr = (FirstSrcRegIt + NumVecs + 1)->getReg();
6033 auto Load = MIB.buildInstr(Opc, {Ty}, {})
6034 .addReg(Tuple)
6035 .addImm(LaneNo->getZExtValue())
6036 .addReg(Ptr);
6039 Register SelectedLoadDst = Load->getOperand(0).getReg();
6040 unsigned SubReg = AArch64::qsub0;
6041 for (unsigned Idx = 0; Idx < NumVecs; ++Idx) {
6042 auto Vec = MIB.buildInstr(TargetOpcode::COPY,
6043 {Narrow ? DstOp(&AArch64::FPR128RegClass)
6044 : DstOp(I.getOperand(Idx).getReg())},
6045 {})
6046 .addReg(SelectedLoadDst, {}, SubReg + Idx);
6047 Register WideReg = Vec.getReg(0);
6048 // Emit the subreg copies and immediately select them.
6049 selectCopy(*Vec, TII, MRI, TRI, RBI);
6050 if (Narrow &&
6051 !emitNarrowVector(I.getOperand(Idx).getReg(), WideReg, MIB, MRI))
6052 return false;
6053 }
6054 return true;
6055}
6056
6057void AArch64InstructionSelector::selectVectorStoreIntrinsic(MachineInstr &I,
6058 unsigned NumVecs,
6059 unsigned Opc) {
6060 MachineRegisterInfo &MRI = I.getParent()->getParent()->getRegInfo();
6061 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6062 Register Ptr = I.getOperand(1 + NumVecs).getReg();
6063
6064 SmallVector<Register, 2> Regs(NumVecs);
6065 std::transform(I.operands_begin() + 1, I.operands_begin() + 1 + NumVecs,
6066 Regs.begin(), [](auto MO) { return MO.getReg(); });
6067
6068 Register Tuple = Ty.getSizeInBits() == 128 ? createQTuple(Regs, MIB)
6069 : createDTuple(Regs, MIB);
6070 auto Store = MIB.buildInstr(Opc, {}, {Tuple, Ptr});
6073}
6074
6075bool AArch64InstructionSelector::selectVectorStoreLaneIntrinsic(
6076 MachineInstr &I, unsigned NumVecs, unsigned Opc) {
6077 MachineRegisterInfo &MRI = I.getParent()->getParent()->getRegInfo();
6078 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6079 bool Narrow = Ty.getSizeInBits() == 64;
6080
6081 SmallVector<Register, 2> Regs(NumVecs);
6082 std::transform(I.operands_begin() + 1, I.operands_begin() + 1 + NumVecs,
6083 Regs.begin(), [](auto MO) { return MO.getReg(); });
6084
6085 if (Narrow)
6086 transform(Regs, Regs.begin(), [this](Register Reg) {
6087 return emitScalarToVector(64, &AArch64::FPR128RegClass, Reg, MIB)
6088 ->getOperand(0)
6089 .getReg();
6090 });
6091
6092 Register Tuple = createQTuple(Regs, MIB);
6093
6094 auto LaneNo = getIConstantVRegVal(I.getOperand(1 + NumVecs).getReg(), MRI);
6095 if (!LaneNo)
6096 return false;
6097 Register Ptr = I.getOperand(1 + NumVecs + 1).getReg();
6098 auto Store = MIB.buildInstr(Opc, {}, {})
6099 .addReg(Tuple)
6100 .addImm(LaneNo->getZExtValue())
6101 .addReg(Ptr);
6104 return true;
6105}
6106
6107bool AArch64InstructionSelector::selectIntrinsicWithSideEffects(
6108 MachineInstr &I, MachineRegisterInfo &MRI) {
6109 // Find the intrinsic ID.
6110 unsigned IntrinID = cast<GIntrinsic>(I).getIntrinsicID();
6111
6112 const LLT S8 = LLT::scalar(8);
6113 const LLT S16 = LLT::scalar(16);
6114 const LLT S32 = LLT::scalar(32);
6115 const LLT S64 = LLT::scalar(64);
6116 const LLT P0 = LLT::pointer(0, 64);
6117 // Select the instruction.
6118 switch (IntrinID) {
6119 default:
6120 return false;
6121 case Intrinsic::aarch64_ldxp:
6122 case Intrinsic::aarch64_ldaxp: {
6123 auto NewI = MIB.buildInstr(
6124 IntrinID == Intrinsic::aarch64_ldxp ? AArch64::LDXPX : AArch64::LDAXPX,
6125 {I.getOperand(0).getReg(), I.getOperand(1).getReg()},
6126 {I.getOperand(3)});
6127 NewI.cloneMemRefs(I);
6129 break;
6130 }
6131 case Intrinsic::aarch64_neon_ld1x2: {
6132 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6133 unsigned Opc = 0;
6134 if (Ty == LLT::fixed_vector(8, S8))
6135 Opc = AArch64::LD1Twov8b;
6136 else if (Ty == LLT::fixed_vector(16, S8))
6137 Opc = AArch64::LD1Twov16b;
6138 else if (Ty == LLT::fixed_vector(4, S16))
6139 Opc = AArch64::LD1Twov4h;
6140 else if (Ty == LLT::fixed_vector(8, S16))
6141 Opc = AArch64::LD1Twov8h;
6142 else if (Ty == LLT::fixed_vector(2, S32))
6143 Opc = AArch64::LD1Twov2s;
6144 else if (Ty == LLT::fixed_vector(4, S32))
6145 Opc = AArch64::LD1Twov4s;
6146 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6147 Opc = AArch64::LD1Twov2d;
6148 else if (Ty == S64 || Ty == P0)
6149 Opc = AArch64::LD1Twov1d;
6150 else
6151 llvm_unreachable("Unexpected type for ld1x2!");
6152 selectVectorLoadIntrinsic(Opc, 2, I);
6153 break;
6154 }
6155 case Intrinsic::aarch64_neon_ld1x3: {
6156 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6157 unsigned Opc = 0;
6158 if (Ty == LLT::fixed_vector(8, S8))
6159 Opc = AArch64::LD1Threev8b;
6160 else if (Ty == LLT::fixed_vector(16, S8))
6161 Opc = AArch64::LD1Threev16b;
6162 else if (Ty == LLT::fixed_vector(4, S16))
6163 Opc = AArch64::LD1Threev4h;
6164 else if (Ty == LLT::fixed_vector(8, S16))
6165 Opc = AArch64::LD1Threev8h;
6166 else if (Ty == LLT::fixed_vector(2, S32))
6167 Opc = AArch64::LD1Threev2s;
6168 else if (Ty == LLT::fixed_vector(4, S32))
6169 Opc = AArch64::LD1Threev4s;
6170 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6171 Opc = AArch64::LD1Threev2d;
6172 else if (Ty == S64 || Ty == P0)
6173 Opc = AArch64::LD1Threev1d;
6174 else
6175 llvm_unreachable("Unexpected type for ld1x3!");
6176 selectVectorLoadIntrinsic(Opc, 3, I);
6177 break;
6178 }
6179 case Intrinsic::aarch64_neon_ld1x4: {
6180 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6181 unsigned Opc = 0;
6182 if (Ty == LLT::fixed_vector(8, S8))
6183 Opc = AArch64::LD1Fourv8b;
6184 else if (Ty == LLT::fixed_vector(16, S8))
6185 Opc = AArch64::LD1Fourv16b;
6186 else if (Ty == LLT::fixed_vector(4, S16))
6187 Opc = AArch64::LD1Fourv4h;
6188 else if (Ty == LLT::fixed_vector(8, S16))
6189 Opc = AArch64::LD1Fourv8h;
6190 else if (Ty == LLT::fixed_vector(2, S32))
6191 Opc = AArch64::LD1Fourv2s;
6192 else if (Ty == LLT::fixed_vector(4, S32))
6193 Opc = AArch64::LD1Fourv4s;
6194 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6195 Opc = AArch64::LD1Fourv2d;
6196 else if (Ty == S64 || Ty == P0)
6197 Opc = AArch64::LD1Fourv1d;
6198 else
6199 llvm_unreachable("Unexpected type for ld1x4!");
6200 selectVectorLoadIntrinsic(Opc, 4, I);
6201 break;
6202 }
6203 case Intrinsic::aarch64_neon_ld2: {
6204 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6205 unsigned Opc = 0;
6206 if (Ty == LLT::fixed_vector(8, S8))
6207 Opc = AArch64::LD2Twov8b;
6208 else if (Ty == LLT::fixed_vector(16, S8))
6209 Opc = AArch64::LD2Twov16b;
6210 else if (Ty == LLT::fixed_vector(4, S16))
6211 Opc = AArch64::LD2Twov4h;
6212 else if (Ty == LLT::fixed_vector(8, S16))
6213 Opc = AArch64::LD2Twov8h;
6214 else if (Ty == LLT::fixed_vector(2, S32))
6215 Opc = AArch64::LD2Twov2s;
6216 else if (Ty == LLT::fixed_vector(4, S32))
6217 Opc = AArch64::LD2Twov4s;
6218 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6219 Opc = AArch64::LD2Twov2d;
6220 else if (Ty == S64 || Ty == P0)
6221 Opc = AArch64::LD1Twov1d;
6222 else
6223 llvm_unreachable("Unexpected type for ld2!");
6224 selectVectorLoadIntrinsic(Opc, 2, I);
6225 break;
6226 }
6227 case Intrinsic::aarch64_neon_ld2lane: {
6228 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6229 unsigned Opc;
6230 if (Ty == LLT::fixed_vector(8, S8) || Ty == LLT::fixed_vector(16, S8))
6231 Opc = AArch64::LD2i8;
6232 else if (Ty == LLT::fixed_vector(4, S16) || Ty == LLT::fixed_vector(8, S16))
6233 Opc = AArch64::LD2i16;
6234 else if (Ty == LLT::fixed_vector(2, S32) || Ty == LLT::fixed_vector(4, S32))
6235 Opc = AArch64::LD2i32;
6236 else if (Ty == LLT::fixed_vector(2, S64) ||
6237 Ty == LLT::fixed_vector(2, P0) || Ty == S64 || Ty == P0)
6238 Opc = AArch64::LD2i64;
6239 else
6240 llvm_unreachable("Unexpected type for ld2lane!");
6241 if (!selectVectorLoadLaneIntrinsic(Opc, 2, I))
6242 return false;
6243 break;
6244 }
6245 case Intrinsic::aarch64_neon_ld2r: {
6246 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6247 unsigned Opc = 0;
6248 if (Ty == LLT::fixed_vector(8, S8))
6249 Opc = AArch64::LD2Rv8b;
6250 else if (Ty == LLT::fixed_vector(16, S8))
6251 Opc = AArch64::LD2Rv16b;
6252 else if (Ty == LLT::fixed_vector(4, S16))
6253 Opc = AArch64::LD2Rv4h;
6254 else if (Ty == LLT::fixed_vector(8, S16))
6255 Opc = AArch64::LD2Rv8h;
6256 else if (Ty == LLT::fixed_vector(2, S32))
6257 Opc = AArch64::LD2Rv2s;
6258 else if (Ty == LLT::fixed_vector(4, S32))
6259 Opc = AArch64::LD2Rv4s;
6260 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6261 Opc = AArch64::LD2Rv2d;
6262 else if (Ty == S64 || Ty == P0)
6263 Opc = AArch64::LD2Rv1d;
6264 else
6265 llvm_unreachable("Unexpected type for ld2r!");
6266 selectVectorLoadIntrinsic(Opc, 2, I);
6267 break;
6268 }
6269 case Intrinsic::aarch64_neon_ld3: {
6270 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6271 unsigned Opc = 0;
6272 if (Ty == LLT::fixed_vector(8, S8))
6273 Opc = AArch64::LD3Threev8b;
6274 else if (Ty == LLT::fixed_vector(16, S8))
6275 Opc = AArch64::LD3Threev16b;
6276 else if (Ty == LLT::fixed_vector(4, S16))
6277 Opc = AArch64::LD3Threev4h;
6278 else if (Ty == LLT::fixed_vector(8, S16))
6279 Opc = AArch64::LD3Threev8h;
6280 else if (Ty == LLT::fixed_vector(2, S32))
6281 Opc = AArch64::LD3Threev2s;
6282 else if (Ty == LLT::fixed_vector(4, S32))
6283 Opc = AArch64::LD3Threev4s;
6284 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6285 Opc = AArch64::LD3Threev2d;
6286 else if (Ty == S64 || Ty == P0)
6287 Opc = AArch64::LD1Threev1d;
6288 else
6289 llvm_unreachable("Unexpected type for ld3!");
6290 selectVectorLoadIntrinsic(Opc, 3, I);
6291 break;
6292 }
6293 case Intrinsic::aarch64_neon_ld3lane: {
6294 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6295 unsigned Opc;
6296 if (Ty == LLT::fixed_vector(8, S8) || Ty == LLT::fixed_vector(16, S8))
6297 Opc = AArch64::LD3i8;
6298 else if (Ty == LLT::fixed_vector(4, S16) || Ty == LLT::fixed_vector(8, S16))
6299 Opc = AArch64::LD3i16;
6300 else if (Ty == LLT::fixed_vector(2, S32) || Ty == LLT::fixed_vector(4, S32))
6301 Opc = AArch64::LD3i32;
6302 else if (Ty == LLT::fixed_vector(2, S64) ||
6303 Ty == LLT::fixed_vector(2, P0) || Ty == S64 || Ty == P0)
6304 Opc = AArch64::LD3i64;
6305 else
6306 llvm_unreachable("Unexpected type for ld3lane!");
6307 if (!selectVectorLoadLaneIntrinsic(Opc, 3, I))
6308 return false;
6309 break;
6310 }
6311 case Intrinsic::aarch64_neon_ld3r: {
6312 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6313 unsigned Opc = 0;
6314 if (Ty == LLT::fixed_vector(8, S8))
6315 Opc = AArch64::LD3Rv8b;
6316 else if (Ty == LLT::fixed_vector(16, S8))
6317 Opc = AArch64::LD3Rv16b;
6318 else if (Ty == LLT::fixed_vector(4, S16))
6319 Opc = AArch64::LD3Rv4h;
6320 else if (Ty == LLT::fixed_vector(8, S16))
6321 Opc = AArch64::LD3Rv8h;
6322 else if (Ty == LLT::fixed_vector(2, S32))
6323 Opc = AArch64::LD3Rv2s;
6324 else if (Ty == LLT::fixed_vector(4, S32))
6325 Opc = AArch64::LD3Rv4s;
6326 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6327 Opc = AArch64::LD3Rv2d;
6328 else if (Ty == S64 || Ty == P0)
6329 Opc = AArch64::LD3Rv1d;
6330 else
6331 llvm_unreachable("Unexpected type for ld3r!");
6332 selectVectorLoadIntrinsic(Opc, 3, I);
6333 break;
6334 }
6335 case Intrinsic::aarch64_neon_ld4: {
6336 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6337 unsigned Opc = 0;
6338 if (Ty == LLT::fixed_vector(8, S8))
6339 Opc = AArch64::LD4Fourv8b;
6340 else if (Ty == LLT::fixed_vector(16, S8))
6341 Opc = AArch64::LD4Fourv16b;
6342 else if (Ty == LLT::fixed_vector(4, S16))
6343 Opc = AArch64::LD4Fourv4h;
6344 else if (Ty == LLT::fixed_vector(8, S16))
6345 Opc = AArch64::LD4Fourv8h;
6346 else if (Ty == LLT::fixed_vector(2, S32))
6347 Opc = AArch64::LD4Fourv2s;
6348 else if (Ty == LLT::fixed_vector(4, S32))
6349 Opc = AArch64::LD4Fourv4s;
6350 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6351 Opc = AArch64::LD4Fourv2d;
6352 else if (Ty == S64 || Ty == P0)
6353 Opc = AArch64::LD1Fourv1d;
6354 else
6355 llvm_unreachable("Unexpected type for ld4!");
6356 selectVectorLoadIntrinsic(Opc, 4, I);
6357 break;
6358 }
6359 case Intrinsic::aarch64_neon_ld4lane: {
6360 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6361 unsigned Opc;
6362 if (Ty == LLT::fixed_vector(8, S8) || Ty == LLT::fixed_vector(16, S8))
6363 Opc = AArch64::LD4i8;
6364 else if (Ty == LLT::fixed_vector(4, S16) || Ty == LLT::fixed_vector(8, S16))
6365 Opc = AArch64::LD4i16;
6366 else if (Ty == LLT::fixed_vector(2, S32) || Ty == LLT::fixed_vector(4, S32))
6367 Opc = AArch64::LD4i32;
6368 else if (Ty == LLT::fixed_vector(2, S64) ||
6369 Ty == LLT::fixed_vector(2, P0) || Ty == S64 || Ty == P0)
6370 Opc = AArch64::LD4i64;
6371 else
6372 llvm_unreachable("Unexpected type for ld4lane!");
6373 if (!selectVectorLoadLaneIntrinsic(Opc, 4, I))
6374 return false;
6375 break;
6376 }
6377 case Intrinsic::aarch64_neon_ld4r: {
6378 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6379 unsigned Opc = 0;
6380 if (Ty == LLT::fixed_vector(8, S8))
6381 Opc = AArch64::LD4Rv8b;
6382 else if (Ty == LLT::fixed_vector(16, S8))
6383 Opc = AArch64::LD4Rv16b;
6384 else if (Ty == LLT::fixed_vector(4, S16))
6385 Opc = AArch64::LD4Rv4h;
6386 else if (Ty == LLT::fixed_vector(8, S16))
6387 Opc = AArch64::LD4Rv8h;
6388 else if (Ty == LLT::fixed_vector(2, S32))
6389 Opc = AArch64::LD4Rv2s;
6390 else if (Ty == LLT::fixed_vector(4, S32))
6391 Opc = AArch64::LD4Rv4s;
6392 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6393 Opc = AArch64::LD4Rv2d;
6394 else if (Ty == S64 || Ty == P0)
6395 Opc = AArch64::LD4Rv1d;
6396 else
6397 llvm_unreachable("Unexpected type for ld4r!");
6398 selectVectorLoadIntrinsic(Opc, 4, I);
6399 break;
6400 }
6401 case Intrinsic::aarch64_neon_st1x2: {
6402 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6403 unsigned Opc;
6404 if (Ty == LLT::fixed_vector(8, S8))
6405 Opc = AArch64::ST1Twov8b;
6406 else if (Ty == LLT::fixed_vector(16, S8))
6407 Opc = AArch64::ST1Twov16b;
6408 else if (Ty == LLT::fixed_vector(4, S16))
6409 Opc = AArch64::ST1Twov4h;
6410 else if (Ty == LLT::fixed_vector(8, S16))
6411 Opc = AArch64::ST1Twov8h;
6412 else if (Ty == LLT::fixed_vector(2, S32))
6413 Opc = AArch64::ST1Twov2s;
6414 else if (Ty == LLT::fixed_vector(4, S32))
6415 Opc = AArch64::ST1Twov4s;
6416 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6417 Opc = AArch64::ST1Twov2d;
6418 else if (Ty == S64 || Ty == P0)
6419 Opc = AArch64::ST1Twov1d;
6420 else
6421 llvm_unreachable("Unexpected type for st1x2!");
6422 selectVectorStoreIntrinsic(I, 2, Opc);
6423 break;
6424 }
6425 case Intrinsic::aarch64_neon_st1x3: {
6426 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6427 unsigned Opc;
6428 if (Ty == LLT::fixed_vector(8, S8))
6429 Opc = AArch64::ST1Threev8b;
6430 else if (Ty == LLT::fixed_vector(16, S8))
6431 Opc = AArch64::ST1Threev16b;
6432 else if (Ty == LLT::fixed_vector(4, S16))
6433 Opc = AArch64::ST1Threev4h;
6434 else if (Ty == LLT::fixed_vector(8, S16))
6435 Opc = AArch64::ST1Threev8h;
6436 else if (Ty == LLT::fixed_vector(2, S32))
6437 Opc = AArch64::ST1Threev2s;
6438 else if (Ty == LLT::fixed_vector(4, S32))
6439 Opc = AArch64::ST1Threev4s;
6440 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6441 Opc = AArch64::ST1Threev2d;
6442 else if (Ty == S64 || Ty == P0)
6443 Opc = AArch64::ST1Threev1d;
6444 else
6445 llvm_unreachable("Unexpected type for st1x3!");
6446 selectVectorStoreIntrinsic(I, 3, Opc);
6447 break;
6448 }
6449 case Intrinsic::aarch64_neon_st1x4: {
6450 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6451 unsigned Opc;
6452 if (Ty == LLT::fixed_vector(8, S8))
6453 Opc = AArch64::ST1Fourv8b;
6454 else if (Ty == LLT::fixed_vector(16, S8))
6455 Opc = AArch64::ST1Fourv16b;
6456 else if (Ty == LLT::fixed_vector(4, S16))
6457 Opc = AArch64::ST1Fourv4h;
6458 else if (Ty == LLT::fixed_vector(8, S16))
6459 Opc = AArch64::ST1Fourv8h;
6460 else if (Ty == LLT::fixed_vector(2, S32))
6461 Opc = AArch64::ST1Fourv2s;
6462 else if (Ty == LLT::fixed_vector(4, S32))
6463 Opc = AArch64::ST1Fourv4s;
6464 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6465 Opc = AArch64::ST1Fourv2d;
6466 else if (Ty == S64 || Ty == P0)
6467 Opc = AArch64::ST1Fourv1d;
6468 else
6469 llvm_unreachable("Unexpected type for st1x4!");
6470 selectVectorStoreIntrinsic(I, 4, Opc);
6471 break;
6472 }
6473 case Intrinsic::aarch64_neon_st2: {
6474 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6475 unsigned Opc;
6476 if (Ty == LLT::fixed_vector(8, S8))
6477 Opc = AArch64::ST2Twov8b;
6478 else if (Ty == LLT::fixed_vector(16, S8))
6479 Opc = AArch64::ST2Twov16b;
6480 else if (Ty == LLT::fixed_vector(4, S16))
6481 Opc = AArch64::ST2Twov4h;
6482 else if (Ty == LLT::fixed_vector(8, S16))
6483 Opc = AArch64::ST2Twov8h;
6484 else if (Ty == LLT::fixed_vector(2, S32))
6485 Opc = AArch64::ST2Twov2s;
6486 else if (Ty == LLT::fixed_vector(4, S32))
6487 Opc = AArch64::ST2Twov4s;
6488 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6489 Opc = AArch64::ST2Twov2d;
6490 else if (Ty == S64 || Ty == P0)
6491 Opc = AArch64::ST1Twov1d;
6492 else
6493 llvm_unreachable("Unexpected type for st2!");
6494 selectVectorStoreIntrinsic(I, 2, Opc);
6495 break;
6496 }
6497 case Intrinsic::aarch64_neon_st3: {
6498 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6499 unsigned Opc;
6500 if (Ty == LLT::fixed_vector(8, S8))
6501 Opc = AArch64::ST3Threev8b;
6502 else if (Ty == LLT::fixed_vector(16, S8))
6503 Opc = AArch64::ST3Threev16b;
6504 else if (Ty == LLT::fixed_vector(4, S16))
6505 Opc = AArch64::ST3Threev4h;
6506 else if (Ty == LLT::fixed_vector(8, S16))
6507 Opc = AArch64::ST3Threev8h;
6508 else if (Ty == LLT::fixed_vector(2, S32))
6509 Opc = AArch64::ST3Threev2s;
6510 else if (Ty == LLT::fixed_vector(4, S32))
6511 Opc = AArch64::ST3Threev4s;
6512 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6513 Opc = AArch64::ST3Threev2d;
6514 else if (Ty == S64 || Ty == P0)
6515 Opc = AArch64::ST1Threev1d;
6516 else
6517 llvm_unreachable("Unexpected type for st3!");
6518 selectVectorStoreIntrinsic(I, 3, Opc);
6519 break;
6520 }
6521 case Intrinsic::aarch64_neon_st4: {
6522 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6523 unsigned Opc;
6524 if (Ty == LLT::fixed_vector(8, S8))
6525 Opc = AArch64::ST4Fourv8b;
6526 else if (Ty == LLT::fixed_vector(16, S8))
6527 Opc = AArch64::ST4Fourv16b;
6528 else if (Ty == LLT::fixed_vector(4, S16))
6529 Opc = AArch64::ST4Fourv4h;
6530 else if (Ty == LLT::fixed_vector(8, S16))
6531 Opc = AArch64::ST4Fourv8h;
6532 else if (Ty == LLT::fixed_vector(2, S32))
6533 Opc = AArch64::ST4Fourv2s;
6534 else if (Ty == LLT::fixed_vector(4, S32))
6535 Opc = AArch64::ST4Fourv4s;
6536 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6537 Opc = AArch64::ST4Fourv2d;
6538 else if (Ty == S64 || Ty == P0)
6539 Opc = AArch64::ST1Fourv1d;
6540 else
6541 llvm_unreachable("Unexpected type for st4!");
6542 selectVectorStoreIntrinsic(I, 4, Opc);
6543 break;
6544 }
6545 case Intrinsic::aarch64_neon_st2lane: {
6546 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6547 unsigned Opc;
6548 if (Ty == LLT::fixed_vector(8, S8) || Ty == LLT::fixed_vector(16, S8))
6549 Opc = AArch64::ST2i8;
6550 else if (Ty == LLT::fixed_vector(4, S16) || Ty == LLT::fixed_vector(8, S16))
6551 Opc = AArch64::ST2i16;
6552 else if (Ty == LLT::fixed_vector(2, S32) || Ty == LLT::fixed_vector(4, S32))
6553 Opc = AArch64::ST2i32;
6554 else if (Ty == LLT::fixed_vector(2, S64) ||
6555 Ty == LLT::fixed_vector(2, P0) || Ty == S64 || Ty == P0)
6556 Opc = AArch64::ST2i64;
6557 else
6558 llvm_unreachable("Unexpected type for st2lane!");
6559 if (!selectVectorStoreLaneIntrinsic(I, 2, Opc))
6560 return false;
6561 break;
6562 }
6563 case Intrinsic::aarch64_neon_st3lane: {
6564 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6565 unsigned Opc;
6566 if (Ty == LLT::fixed_vector(8, S8) || Ty == LLT::fixed_vector(16, S8))
6567 Opc = AArch64::ST3i8;
6568 else if (Ty == LLT::fixed_vector(4, S16) || Ty == LLT::fixed_vector(8, S16))
6569 Opc = AArch64::ST3i16;
6570 else if (Ty == LLT::fixed_vector(2, S32) || Ty == LLT::fixed_vector(4, S32))
6571 Opc = AArch64::ST3i32;
6572 else if (Ty == LLT::fixed_vector(2, S64) ||
6573 Ty == LLT::fixed_vector(2, P0) || Ty == S64 || Ty == P0)
6574 Opc = AArch64::ST3i64;
6575 else
6576 llvm_unreachable("Unexpected type for st3lane!");
6577 if (!selectVectorStoreLaneIntrinsic(I, 3, Opc))
6578 return false;
6579 break;
6580 }
6581 case Intrinsic::aarch64_neon_st4lane: {
6582 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6583 unsigned Opc;
6584 if (Ty == LLT::fixed_vector(8, S8) || Ty == LLT::fixed_vector(16, S8))
6585 Opc = AArch64::ST4i8;
6586 else if (Ty == LLT::fixed_vector(4, S16) || Ty == LLT::fixed_vector(8, S16))
6587 Opc = AArch64::ST4i16;
6588 else if (Ty == LLT::fixed_vector(2, S32) || Ty == LLT::fixed_vector(4, S32))
6589 Opc = AArch64::ST4i32;
6590 else if (Ty == LLT::fixed_vector(2, S64) ||
6591 Ty == LLT::fixed_vector(2, P0) || Ty == S64 || Ty == P0)
6592 Opc = AArch64::ST4i64;
6593 else
6594 llvm_unreachable("Unexpected type for st4lane!");
6595 if (!selectVectorStoreLaneIntrinsic(I, 4, Opc))
6596 return false;
6597 break;
6598 }
6599 case Intrinsic::aarch64_mops_memset_tag: {
6600 // Transform
6601 // %dst:gpr(p0) = \
6602 // G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aarch64.mops.memset.tag),
6603 // \ %dst:gpr(p0), %val:gpr(s64), %n:gpr(s64)
6604 // where %dst is updated, into
6605 // %Rd:GPR64common, %Rn:GPR64) = \
6606 // MOPSMemorySetTaggingPseudo \
6607 // %Rd:GPR64common, %Rn:GPR64, %Rm:GPR64
6608 // where Rd and Rn are tied.
6609 // It is expected that %val has been extended to s64 in legalization.
6610 // Note that the order of the size/value operands are swapped.
6611
6612 Register DstDef = I.getOperand(0).getReg();
6613 // I.getOperand(1) is the intrinsic function
6614 Register DstUse = I.getOperand(2).getReg();
6615 Register ValUse = I.getOperand(3).getReg();
6616 Register SizeUse = I.getOperand(4).getReg();
6617
6618 // MOPSMemorySetTaggingPseudo has two defs; the intrinsic call has only one.
6619 // Therefore an additional virtual register is required for the updated size
6620 // operand. This value is not accessible via the semantics of the intrinsic.
6622
6623 auto Memset = MIB.buildInstr(AArch64::MOPSMemorySetTaggingPseudo,
6624 {DstDef, SizeDef}, {DstUse, SizeUse, ValUse});
6625 Memset.cloneMemRefs(I);
6626 Memset.setOperandDead(5); // implicit-def $nzcv
6628 break;
6629 }
6630 case Intrinsic::ptrauth_resign_load_relative: {
6631 Register DstReg = I.getOperand(0).getReg();
6632 Register ValReg = I.getOperand(2).getReg();
6633 uint64_t AUTKey = I.getOperand(3).getImm();
6634 Register AUTDisc = I.getOperand(4).getReg();
6635 uint64_t PACKey = I.getOperand(5).getImm();
6636 Register PACDisc = I.getOperand(6).getReg();
6637 int64_t Addend = I.getOperand(7).getImm();
6638
6639 Register AUTAddrDisc = AUTDisc;
6640 uint16_t AUTConstDiscC = 0;
6641 std::tie(AUTConstDiscC, AUTAddrDisc) =
6643
6644 Register PACAddrDisc = PACDisc;
6645 uint16_t PACConstDiscC = 0;
6646 std::tie(PACConstDiscC, PACAddrDisc) =
6648
6649 MIB.buildCopy({AArch64::X16}, {ValReg});
6650
6651 MIB.buildInstr(AArch64::AUTRELLOADPAC)
6652 .addImm(AUTKey)
6653 .addImm(AUTConstDiscC)
6654 .addUse(AUTAddrDisc)
6655 .addImm(PACKey)
6656 .addImm(PACConstDiscC)
6657 .addUse(PACAddrDisc)
6658 .addImm(Addend)
6659 .setOperandDead(8) // implicit-def $x17
6660 .setOperandDead(9) // implicit-def $nzcv
6661 .constrainAllUses(TII, TRI, RBI);
6662 MIB.buildCopy({DstReg}, Register(AArch64::X16));
6663
6664 RBI.constrainGenericRegister(DstReg, AArch64::GPR64RegClass, MRI);
6665 I.eraseFromParent();
6666 return true;
6667 }
6668 }
6669
6670 I.eraseFromParent();
6671 return true;
6672}
6673
6674bool AArch64InstructionSelector::selectIntrinsic(MachineInstr &I,
6675 MachineRegisterInfo &MRI) {
6676 unsigned IntrinID = cast<GIntrinsic>(I).getIntrinsicID();
6677
6678 switch (IntrinID) {
6679 default:
6680 break;
6681 case Intrinsic::ptrauth_resign: {
6682 Register DstReg = I.getOperand(0).getReg();
6683 Register ValReg = I.getOperand(2).getReg();
6684 uint64_t AUTKey = I.getOperand(3).getImm();
6685 Register AUTDisc = I.getOperand(4).getReg();
6686 uint64_t PACKey = I.getOperand(5).getImm();
6687 Register PACDisc = I.getOperand(6).getReg();
6688
6689 Register AUTAddrDisc = AUTDisc;
6690 uint16_t AUTConstDiscC = 0;
6691 std::tie(AUTConstDiscC, AUTAddrDisc) =
6693
6694 Register PACAddrDisc = PACDisc;
6695 uint16_t PACConstDiscC = 0;
6696 std::tie(PACConstDiscC, PACAddrDisc) =
6698
6699 MIB.buildCopy({AArch64::X16}, {ValReg});
6700 MIB.buildInstr(AArch64::AUTPAC)
6701 .addImm(AUTKey)
6702 .addImm(AUTConstDiscC)
6703 .addUse(AUTAddrDisc)
6704 .addImm(PACKey)
6705 .addImm(PACConstDiscC)
6706 .addUse(PACAddrDisc)
6707 .setOperandDead(7) // implicit-def $x17
6708 .setOperandDead(8) // implicit-def $nzcv
6709 .constrainAllUses(TII, TRI, RBI);
6710 MIB.buildCopy({DstReg}, Register(AArch64::X16));
6711
6712 RBI.constrainGenericRegister(DstReg, AArch64::GPR64RegClass, MRI);
6713 I.eraseFromParent();
6714 return true;
6715 }
6716 case Intrinsic::ptrauth_auth_with_pc_and_resign: {
6717 Register DstReg = I.getOperand(0).getReg();
6718 Register ValReg = I.getOperand(2).getReg();
6719 uint64_t AUTKey = I.getOperand(3).getImm();
6720 Register AUTDisc = I.getOperand(4).getReg();
6721 Register AUTPC = I.getOperand(5).getReg();
6722 uint64_t PACKey = I.getOperand(6).getImm();
6723 Register PACDisc = I.getOperand(7).getReg();
6724
6725 assert((AUTKey == AArch64PACKey::IA || AUTKey == AArch64PACKey::IB) &&
6726 "auth_with_pc_and_resign only supports IA and IB keys");
6727
6728 uint16_t PACConstDiscC = 0;
6729 Register PACAddrDisc;
6730 std::tie(PACConstDiscC, PACAddrDisc) =
6732
6733 if (!PACAddrDisc.isValid())
6734 PACAddrDisc = AArch64::XZR;
6735
6736 MIB.buildCopy({AArch64::X17}, {ValReg});
6737 MIB.buildCopy({AArch64::X16}, {AUTDisc});
6738 MIB.buildCopy({AArch64::X15}, {AUTPC});
6739
6740 MIB.buildInstr(AArch64::AUTPCPAC)
6741 .addImm(AUTKey)
6742 .addImm(PACKey)
6743 .addImm(PACConstDiscC)
6744 .addUse(PACAddrDisc)
6745 .setOperandDead(5) // implicit-def $x15
6746 .setOperandDead(6) // implicit-def $x16
6747 .setOperandDead(7) // implicit-def $nzcv
6748 .constrainAllUses(TII, TRI, RBI);
6749
6750 MIB.buildCopy({DstReg}, Register(AArch64::X17));
6751 RBI.constrainGenericRegister(DstReg, AArch64::GPR64RegClass, MRI);
6752 I.eraseFromParent();
6753 return true;
6754 }
6755 case Intrinsic::ptrauth_auth: {
6756 Register DstReg = I.getOperand(0).getReg();
6757 Register ValReg = I.getOperand(2).getReg();
6758 uint64_t AUTKey = I.getOperand(3).getImm();
6759 Register AUTDisc = I.getOperand(4).getReg();
6760
6761 Register AUTAddrDisc = AUTDisc;
6762 uint16_t AUTConstDiscC = 0;
6763 std::tie(AUTConstDiscC, AUTAddrDisc) =
6765
6766 if (STI.isX16X17Safer()) {
6767 MIB.buildCopy({AArch64::X16}, {ValReg});
6768 MIB.buildInstr(AArch64::AUTx16x17)
6769 .addImm(AUTKey)
6770 .addImm(AUTConstDiscC)
6771 .addUse(AUTAddrDisc)
6772 .setOperandDead(4) // implicit-def $x17
6773 .setOperandDead(5) // implicit-def $nzcv
6774 .constrainAllUses(TII, TRI, RBI);
6775 MIB.buildCopy({DstReg}, Register(AArch64::X16));
6776 } else {
6777 Register ScratchReg =
6778 MRI.createVirtualRegister(&AArch64::GPR64commonRegClass);
6779 auto Auth = MIB.buildInstr(AArch64::AUTxMxN)
6780 .addDef(DstReg)
6781 .addDef(ScratchReg)
6782 .addUse(ValReg)
6783 .addImm(AUTKey)
6784 .addImm(AUTConstDiscC)
6785 .addUse(AUTAddrDisc);
6787 Auth.constrainAllUses(TII, TRI, RBI);
6788 }
6789
6790 RBI.constrainGenericRegister(DstReg, AArch64::GPR64RegClass, MRI);
6791 I.eraseFromParent();
6792 return true;
6793 }
6794 case Intrinsic::frameaddress:
6795 case Intrinsic::returnaddress: {
6796 MachineFunction &MF = *I.getParent()->getParent();
6797 MachineFrameInfo &MFI = MF.getFrameInfo();
6798
6799 unsigned Depth = I.getOperand(2).getImm();
6800 Register DstReg = I.getOperand(0).getReg();
6801 RBI.constrainGenericRegister(DstReg, AArch64::GPR64RegClass, MRI);
6802
6803 if (Depth == 0 && IntrinID == Intrinsic::returnaddress) {
6804 if (!MFReturnAddr) {
6805 // Insert the copy from LR/X30 into the entry block, before it can be
6806 // clobbered by anything.
6807 MFI.setReturnAddressIsTaken(true);
6808 MFReturnAddr = getFunctionLiveInPhysReg(
6809 MF, TII, AArch64::LR, AArch64::GPR64RegClass, I.getDebugLoc());
6810 }
6811
6812 if (STI.hasPAuth()) {
6813 MIB.buildInstr(AArch64::XPACI, {DstReg}, {MFReturnAddr});
6814 } else {
6815 MIB.buildCopy({Register(AArch64::LR)}, {MFReturnAddr});
6816 MIB.buildInstr(AArch64::XPACLRI);
6817 MIB.buildCopy({DstReg}, {Register(AArch64::LR)});
6818 }
6819
6820 I.eraseFromParent();
6821 return true;
6822 }
6823
6824 MFI.setFrameAddressIsTaken(true);
6825 Register FrameAddr(AArch64::FP);
6826 while (Depth--) {
6827 Register NextFrame = MRI.createVirtualRegister(&AArch64::GPR64spRegClass);
6828 auto Ldr =
6829 MIB.buildInstr(AArch64::LDRXui, {NextFrame}, {FrameAddr}).addImm(0);
6831 FrameAddr = NextFrame;
6832 }
6833
6834 if (IntrinID == Intrinsic::frameaddress)
6835 MIB.buildCopy({DstReg}, {FrameAddr});
6836 else {
6837 MFI.setReturnAddressIsTaken(true);
6838
6839 if (STI.hasPAuth()) {
6840 Register TmpReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
6841 MIB.buildInstr(AArch64::LDRXui, {TmpReg}, {FrameAddr}).addImm(1);
6842 MIB.buildInstr(AArch64::XPACI, {DstReg}, {TmpReg});
6843 } else {
6844 MIB.buildInstr(AArch64::LDRXui, {Register(AArch64::LR)}, {FrameAddr})
6845 .addImm(1);
6846 MIB.buildInstr(AArch64::XPACLRI);
6847 MIB.buildCopy({DstReg}, {Register(AArch64::LR)});
6848 }
6849 }
6850
6851 I.eraseFromParent();
6852 return true;
6853 }
6854 case Intrinsic::aarch64_neon_tbl2:
6855 SelectTable(I, MRI, 2, AArch64::TBLv8i8Two, AArch64::TBLv16i8Two, false);
6856 return true;
6857 case Intrinsic::aarch64_neon_tbl3:
6858 SelectTable(I, MRI, 3, AArch64::TBLv8i8Three, AArch64::TBLv16i8Three,
6859 false);
6860 return true;
6861 case Intrinsic::aarch64_neon_tbl4:
6862 SelectTable(I, MRI, 4, AArch64::TBLv8i8Four, AArch64::TBLv16i8Four, false);
6863 return true;
6864 case Intrinsic::aarch64_neon_tbx2:
6865 SelectTable(I, MRI, 2, AArch64::TBXv8i8Two, AArch64::TBXv16i8Two, true);
6866 return true;
6867 case Intrinsic::aarch64_neon_tbx3:
6868 SelectTable(I, MRI, 3, AArch64::TBXv8i8Three, AArch64::TBXv16i8Three, true);
6869 return true;
6870 case Intrinsic::aarch64_neon_tbx4:
6871 SelectTable(I, MRI, 4, AArch64::TBXv8i8Four, AArch64::TBXv16i8Four, true);
6872 return true;
6873 case Intrinsic::swift_async_context_addr:
6874 auto Sub = MIB.buildInstr(AArch64::SUBXri, {I.getOperand(0).getReg()},
6875 {Register(AArch64::FP)})
6876 .addImm(8)
6877 .addImm(0);
6879
6881 MF->getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(true);
6882 I.eraseFromParent();
6883 return true;
6884 }
6885 return false;
6886}
6887
6888// G_PTRAUTH_GLOBAL_VALUE lowering
6889//
6890// We have 3 lowering alternatives to choose from:
6891// - MOVaddrPAC: similar to MOVaddr, with added PAC.
6892// If the GV doesn't need a GOT load (i.e., is locally defined)
6893// materialize the pointer using adrp+add+pac. See LowerMOVaddrPAC.
6894//
6895// - LOADgotPAC: similar to LOADgot, with added PAC.
6896// If the GV needs a GOT load, materialize the pointer using the usual
6897// GOT adrp+ldr, +pac. Pointers in GOT are assumed to be not signed, the GOT
6898// section is assumed to be read-only (for example, via relro mechanism). See
6899// LowerMOVaddrPAC.
6900//
6901// - LOADauthptrstatic: similar to LOADgot, but use a
6902// special stub slot instead of a GOT slot.
6903// Load a signed pointer for symbol 'sym' from a stub slot named
6904// 'sym$auth_ptr$key$disc' filled by dynamic linker during relocation
6905// resolving. This usually lowers to adrp+ldr, but also emits an entry into
6906// .data with an
6907// @AUTH relocation. See LowerLOADauthptrstatic.
6908//
6909// All 3 are pseudos that are expand late to longer sequences: this lets us
6910// provide integrity guarantees on the to-be-signed intermediate values.
6911//
6912// LOADauthptrstatic is undesirable because it requires a large section filled
6913// with often similarly-signed pointers, making it a good harvesting target.
6914// Thus, it's only used for ptrauth references to extern_weak to avoid null
6915// checks.
6916
6917bool AArch64InstructionSelector::selectPtrAuthGlobalValue(
6918 MachineInstr &I, MachineRegisterInfo &MRI) const {
6919 Register DefReg = I.getOperand(0).getReg();
6920 Register Addr = I.getOperand(1).getReg();
6921 uint64_t Key = I.getOperand(2).getImm();
6922 Register AddrDisc = I.getOperand(3).getReg();
6923 uint64_t Disc = I.getOperand(4).getImm();
6924 int64_t Offset = 0;
6925
6927 report_fatal_error("key in ptrauth global out of range [0, " +
6928 Twine((int)AArch64PACKey::LAST) + "]");
6929
6930 // Blend only works if the integer discriminator is 16-bit wide.
6931 if (!isUInt<16>(Disc))
6933 "constant discriminator in ptrauth global out of range [0, 0xffff]");
6934
6935 // Choosing between 3 lowering alternatives is target-specific.
6936 if (!STI.isTargetELF() && !STI.isTargetMachO())
6937 report_fatal_error("ptrauth global lowering only supported on MachO/ELF");
6938
6939 if (!MRI.hasOneDef(Addr))
6940 return false;
6941
6942 // First match any offset we take from the real global.
6943 const MachineInstr *DefMI = &*MRI.def_instr_begin(Addr);
6944 if (DefMI->getOpcode() == TargetOpcode::G_PTR_ADD) {
6945 Register OffsetReg = DefMI->getOperand(2).getReg();
6946 if (!MRI.hasOneDef(OffsetReg))
6947 return false;
6948 const MachineInstr &OffsetMI = *MRI.def_instr_begin(OffsetReg);
6949 if (OffsetMI.getOpcode() != TargetOpcode::G_CONSTANT)
6950 return false;
6951
6952 Addr = DefMI->getOperand(1).getReg();
6953 if (!MRI.hasOneDef(Addr))
6954 return false;
6955
6956 DefMI = &*MRI.def_instr_begin(Addr);
6957 Offset = OffsetMI.getOperand(1).getCImm()->getSExtValue();
6958 }
6959
6960 // We should be left with a genuine unauthenticated GlobalValue.
6961 const GlobalValue *GV;
6962 if (DefMI->getOpcode() == TargetOpcode::G_GLOBAL_VALUE) {
6963 GV = DefMI->getOperand(1).getGlobal();
6965 } else if (DefMI->getOpcode() == AArch64::G_ADD_LOW) {
6966 GV = DefMI->getOperand(2).getGlobal();
6968 } else {
6969 return false;
6970 }
6971
6972 MachineIRBuilder MIB(I);
6973
6974 // Classify the reference to determine whether it needs a GOT load.
6975 unsigned OpFlags = STI.ClassifyGlobalReference(GV, TM);
6976 const bool NeedsGOTLoad = ((OpFlags & AArch64II::MO_GOT) != 0);
6977 assert(((OpFlags & (~AArch64II::MO_GOT)) == 0) &&
6978 "unsupported non-GOT op flags on ptrauth global reference");
6979 assert((!GV->hasExternalWeakLinkage() || NeedsGOTLoad) &&
6980 "unsupported non-GOT reference to weak ptrauth global");
6981
6982 std::optional<APInt> AddrDiscVal = getIConstantVRegVal(AddrDisc, MRI);
6983 bool HasAddrDisc = !AddrDiscVal || *AddrDiscVal != 0;
6984
6985 // Non-extern_weak:
6986 // - No GOT load needed -> MOVaddrPAC
6987 // - GOT load for non-extern_weak -> LOADgotPAC
6988 // Note that we disallow extern_weak refs to avoid null checks later.
6989 if (!GV->hasExternalWeakLinkage()) {
6990 MIB.buildInstr(NeedsGOTLoad ? AArch64::LOADgotPAC : AArch64::MOVaddrPAC)
6992 .addImm(Key)
6993 .addReg(HasAddrDisc ? AddrDisc : AArch64::XZR)
6994 .addImm(Disc)
6995 .constrainAllUses(TII, TRI, RBI);
6996 MIB.buildCopy(DefReg, Register(AArch64::X16));
6997 RBI.constrainGenericRegister(DefReg, AArch64::GPR64RegClass, MRI);
6998 I.eraseFromParent();
6999 return true;
7000 }
7001
7002 // extern_weak -> LOADauthptrstatic
7003
7004 // Offsets and extern_weak don't mix well: ptrauth aside, you'd get the
7005 // offset alone as a pointer if the symbol wasn't available, which would
7006 // probably break null checks in users. Ptrauth complicates things further:
7007 // error out.
7008 if (Offset != 0)
7010 "unsupported non-zero offset in weak ptrauth global reference");
7011
7012 if (HasAddrDisc)
7013 report_fatal_error("unsupported weak addr-div ptrauth global");
7014
7015 MIB.buildInstr(AArch64::LOADauthptrstatic, {DefReg}, {})
7016 .addGlobalAddress(GV, Offset)
7017 .addImm(Key)
7018 .addImm(Disc);
7019 RBI.constrainGenericRegister(DefReg, AArch64::GPR64RegClass, MRI);
7020
7021 I.eraseFromParent();
7022 return true;
7023}
7024
7025void AArch64InstructionSelector::SelectTable(MachineInstr &I,
7026 MachineRegisterInfo &MRI,
7027 unsigned NumVec, unsigned Opc1,
7028 unsigned Opc2, bool isExt) {
7029 Register DstReg = I.getOperand(0).getReg();
7030 unsigned Opc = MRI.getType(DstReg) == LLT::fixed_vector(8, 8) ? Opc1 : Opc2;
7031
7032 // Create the REG_SEQUENCE
7034 for (unsigned i = 0; i < NumVec; i++)
7035 Regs.push_back(I.getOperand(i + 2 + isExt).getReg());
7036 Register RegSeq = createQTuple(Regs, MIB);
7037
7038 Register IdxReg = I.getOperand(2 + NumVec + isExt).getReg();
7039 MachineInstrBuilder Instr;
7040 if (isExt) {
7041 Register Reg = I.getOperand(2).getReg();
7042 Instr = MIB.buildInstr(Opc, {DstReg}, {Reg, RegSeq, IdxReg});
7043 } else
7044 Instr = MIB.buildInstr(Opc, {DstReg}, {RegSeq, IdxReg});
7046 I.eraseFromParent();
7047}
7048
7049InstructionSelector::ComplexRendererFns
7050AArch64InstructionSelector::selectShiftA_32(const MachineOperand &Root) const {
7051 auto MaybeImmed = getImmedFromMO(Root);
7052 if (MaybeImmed == std::nullopt || *MaybeImmed > 31)
7053 return std::nullopt;
7054 uint64_t Enc = (32 - *MaybeImmed) & 0x1f;
7055 return {{[=](MachineInstrBuilder &MIB) { MIB.addImm(Enc); }}};
7056}
7057
7058InstructionSelector::ComplexRendererFns
7059AArch64InstructionSelector::selectShiftB_32(const MachineOperand &Root) const {
7060 auto MaybeImmed = getImmedFromMO(Root);
7061 if (MaybeImmed == std::nullopt || *MaybeImmed > 31)
7062 return std::nullopt;
7063 uint64_t Enc = 31 - *MaybeImmed;
7064 return {{[=](MachineInstrBuilder &MIB) { MIB.addImm(Enc); }}};
7065}
7066
7067InstructionSelector::ComplexRendererFns
7068AArch64InstructionSelector::selectShiftA_64(const MachineOperand &Root) const {
7069 auto MaybeImmed = getImmedFromMO(Root);
7070 if (MaybeImmed == std::nullopt || *MaybeImmed > 63)
7071 return std::nullopt;
7072 uint64_t Enc = (64 - *MaybeImmed) & 0x3f;
7073 return {{[=](MachineInstrBuilder &MIB) { MIB.addImm(Enc); }}};
7074}
7075
7076InstructionSelector::ComplexRendererFns
7077AArch64InstructionSelector::selectShiftB_64(const MachineOperand &Root) const {
7078 auto MaybeImmed = getImmedFromMO(Root);
7079 if (MaybeImmed == std::nullopt || *MaybeImmed > 63)
7080 return std::nullopt;
7081 uint64_t Enc = 63 - *MaybeImmed;
7082 return {{[=](MachineInstrBuilder &MIB) { MIB.addImm(Enc); }}};
7083}
7084
7085template <unsigned ShiftWidth>
7086InstructionSelector::ComplexRendererFns
7087AArch64InstructionSelector::selectShiftMask(MachineOperand &Root) const {
7088 if (!Root.isReg())
7089 return std::nullopt;
7090
7091 MachineRegisterInfo &MRI =
7092 Root.getParent()->getParent()->getParent()->getRegInfo();
7093
7094 Register ShAmtReg = Root.getReg();
7095
7096 // Peek through zext for i32 shifts only. For i64 shifts the zext case
7097 // is already handled by existing patterns in the Shift multiclass.
7098 if (ShiftWidth == 32) {
7099 Register ZExtSrcReg;
7100 if (mi_match(ShAmtReg, MRI, m_GZExt(m_Reg(ZExtSrcReg))))
7101 ShAmtReg = ZExtSrcReg;
7102 }
7103
7104 // Remove AND if the mask covers at least the low log2(ShiftWidth) bits.
7105 APInt AndMask;
7106 Register AndSrcReg;
7107 if (mi_match(ShAmtReg, MRI, m_GAnd(m_Reg(AndSrcReg), m_ICst(AndMask))) &&
7108 MRI.getType(ShAmtReg).getSizeInBits() == ShiftWidth) {
7109 if (AndMask.countr_one() >= Log2_32(ShiftWidth))
7110 ShAmtReg = AndSrcReg;
7111 }
7112
7113 // If shifting by X+/-N where N == 0 mod ShiftWidth, then just shift by X
7114 // to avoid the ADD/SUB. The low log2(ShiftWidth) bits are unchanged, so the
7115 // shift can use X directly; the original ADD/SUB stays for any other users.
7116 Register AddSrcReg;
7117 int64_t AddImm;
7118 if ((mi_match(ShAmtReg, MRI,
7119 m_GAdd(m_Reg(AddSrcReg), m_ICstOrSplat(AddImm))) ||
7120 mi_match(ShAmtReg, MRI,
7121 m_GSub(m_Reg(AddSrcReg), m_ICstOrSplat(AddImm)))) &&
7122 (AddImm % ShiftWidth == 0)) {
7123 ShAmtReg = AddSrcReg;
7124 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(ShAmtReg); }}};
7125 }
7126
7127 // If shifting by N-X where N == 0 mod ShiftWidth, then just shift by -X
7128 // to generate a NEG instead of a SUB from a constant.
7129 Register SubSrcReg;
7130 int64_t SubImm;
7131 if (MRI.hasOneUse(ShAmtReg) &&
7132 mi_match(ShAmtReg, MRI, m_GSub(m_ICst(SubImm), m_Reg(SubSrcReg))) &&
7133 SubImm != 0 && (SubImm % ShiftWidth == 0)) {
7134 return {{[=](MachineInstrBuilder &MIB) {
7135 MachineInstr *I = MIB.getInstr();
7136 MachineRegisterInfo &MRI2 = I->getMF()->getRegInfo();
7137 const TargetRegisterClass &RC =
7138 ShiftWidth == 32 ? AArch64::GPR32RegClass : AArch64::GPR64RegClass;
7139 unsigned SubOpc = ShiftWidth == 32 ? AArch64::SUBWrr : AArch64::SUBXrr;
7140 Register ZeroReg = ShiftWidth == 32 ? AArch64::WZR : AArch64::XZR;
7141 Register NegReg = MRI2.createVirtualRegister(&RC);
7142 auto NegMI = BuildMI(*I->getParent(), *I, I->getDebugLoc(),
7143 TII.get(SubOpc), NegReg)
7144 .addReg(ZeroReg)
7145 .addReg(SubSrcReg);
7147 MIB.addReg(NegReg);
7148 }}};
7149 }
7150
7151 // If shifting by N-X where N == -1 mod ShiftWidth, then just shift by ~X
7152 // to generate a NOT (MVN) instead of a SUB from a constant.
7153 Register NotSrcReg;
7154 int64_t NotImm;
7155 if (MRI.hasOneUse(ShAmtReg) &&
7156 mi_match(ShAmtReg, MRI, m_GSub(m_ICst(NotImm), m_Reg(NotSrcReg))) &&
7157 (NotImm % ShiftWidth == ShiftWidth - 1)) {
7158 return {{[=](MachineInstrBuilder &MIB) {
7159 MachineInstr *I = MIB.getInstr();
7160 MachineRegisterInfo &MRI2 = I->getMF()->getRegInfo();
7161 const TargetRegisterClass &RC =
7162 ShiftWidth == 32 ? AArch64::GPR32RegClass : AArch64::GPR64RegClass;
7163 unsigned NotOpc = ShiftWidth == 32 ? AArch64::ORNWrr : AArch64::ORNXrr;
7164 Register ZeroReg = ShiftWidth == 32 ? AArch64::WZR : AArch64::XZR;
7165 Register NotReg = MRI2.createVirtualRegister(&RC);
7166 auto NotMI = BuildMI(*I->getParent(), *I, I->getDebugLoc(),
7167 TII.get(NotOpc), NotReg)
7168 .addReg(ZeroReg)
7169 .addReg(NotSrcReg);
7171 MIB.addReg(NotReg);
7172 }}};
7173 }
7174
7175 // Only succeed if we changed the shift amount; otherwise let other
7176 // patterns (e.g. zext GPR32 -> SUBREG_TO_REG) match instead.
7177 if (ShAmtReg == Root.getReg())
7178 return std::nullopt;
7179
7180 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(ShAmtReg); }}};
7181}
7182
7183/// Helper to select an immediate value that can be represented as a 12-bit
7184/// value shifted left by either 0 or 12. If it is possible to do so, return
7185/// the immediate and shift value. If not, return std::nullopt.
7186///
7187/// Used by selectArithImmed and selectNegArithImmed.
7188InstructionSelector::ComplexRendererFns
7189AArch64InstructionSelector::select12BitValueWithLeftShift(
7190 uint64_t Immed) const {
7191 unsigned ShiftAmt;
7192 if (Immed >> 12 == 0) {
7193 ShiftAmt = 0;
7194 } else if ((Immed & 0xfff) == 0 && Immed >> 24 == 0) {
7195 ShiftAmt = 12;
7196 Immed = Immed >> 12;
7197 } else
7198 return std::nullopt;
7199
7200 unsigned ShVal = AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftAmt);
7201 return {{
7202 [=](MachineInstrBuilder &MIB) { MIB.addImm(Immed); },
7203 [=](MachineInstrBuilder &MIB) { MIB.addImm(ShVal); },
7204 }};
7205}
7206
7207/// SelectArithImmed - Select an immediate value that can be represented as
7208/// a 12-bit value shifted left by either 0 or 12. If so, return true with
7209/// Val set to the 12-bit value and Shift set to the shifter operand.
7210InstructionSelector::ComplexRendererFns
7211AArch64InstructionSelector::selectArithImmed(MachineOperand &Root) const {
7212 // This function is called from the addsub_shifted_imm ComplexPattern,
7213 // which lists [imm] as the list of opcode it's interested in, however
7214 // we still need to check whether the operand is actually an immediate
7215 // here because the ComplexPattern opcode list is only used in
7216 // root-level opcode matching.
7217 auto MaybeImmed = getImmedFromMO(Root);
7218 if (MaybeImmed == std::nullopt)
7219 return std::nullopt;
7220 return select12BitValueWithLeftShift(*MaybeImmed);
7221}
7222
7223/// SelectNegArithImmed - As above, but negates the value before trying to
7224/// select it.
7225InstructionSelector::ComplexRendererFns
7226AArch64InstructionSelector::selectNegArithImmed(MachineOperand &Root) const {
7227 // We need a register here, because we need to know if we have a 64 or 32
7228 // bit immediate.
7229 if (!Root.isReg())
7230 return std::nullopt;
7231 auto MaybeImmed = getImmedFromMO(Root);
7232 if (MaybeImmed == std::nullopt)
7233 return std::nullopt;
7234 uint64_t Immed = *MaybeImmed;
7235
7236 // This negation is almost always valid, but "cmp wN, #0" and "cmn wN, #0"
7237 // have the opposite effect on the C flag, so this pattern mustn't match under
7238 // those circumstances.
7239 if (Immed == 0)
7240 return std::nullopt;
7241
7242 // Check if we're dealing with a 32-bit type on the root or a 64-bit type on
7243 // the root.
7244 MachineRegisterInfo &MRI = Root.getParent()->getMF()->getRegInfo();
7245 if (MRI.getType(Root.getReg()).getSizeInBits() == 32)
7246 Immed = ~((uint32_t)Immed) + 1;
7247 else
7248 Immed = ~Immed + 1ULL;
7249
7250 if (Immed & 0xFFFFFFFFFF000000ULL)
7251 return std::nullopt;
7252
7253 Immed &= 0xFFFFFFULL;
7254 return select12BitValueWithLeftShift(Immed);
7255}
7256
7257/// Checks if we are sure that folding MI into load/store addressing mode is
7258/// beneficial or not.
7259///
7260/// Returns:
7261/// - true if folding MI would be beneficial.
7262/// - false if folding MI would be bad.
7263/// - std::nullopt if it is not sure whether folding MI is beneficial.
7264///
7265/// \p MI can be the offset operand of G_PTR_ADD, e.g. G_SHL in the example:
7266///
7267/// %13:gpr(s64) = G_CONSTANT i64 1
7268/// %8:gpr(s64) = G_SHL %6, %13(s64)
7269/// %9:gpr(p0) = G_PTR_ADD %0, %8(s64)
7270/// %12:gpr(s32) = G_LOAD %9(p0) :: (load (s16))
7271std::optional<bool> AArch64InstructionSelector::isWorthFoldingIntoAddrMode(
7272 const MachineInstr &MI, const MachineRegisterInfo &MRI) const {
7273 if (MI.getOpcode() == AArch64::G_SHL) {
7274 // Address operands with shifts are free, except for running on subtargets
7275 // with AddrLSLSlow14.
7276 if (const auto ValAndVeg = getIConstantVRegValWithLookThrough(
7277 MI.getOperand(2).getReg(), MRI)) {
7278 const APInt ShiftVal = ValAndVeg->Value;
7279
7280 // Don't fold if we know this will be slow.
7281 return !(STI.hasAddrLSLSlow14() && (ShiftVal == 1 || ShiftVal == 4));
7282 }
7283 }
7284 return std::nullopt;
7285}
7286
7287/// Return true if it is worth folding MI into an extended register. That is,
7288/// if it's safe to pull it into the addressing mode of a load or store as a
7289/// shift.
7290/// \p IsAddrOperand whether the def of MI is used as an address operand
7291/// (e.g. feeding into an LDR/STR).
7292bool AArch64InstructionSelector::isWorthFoldingIntoExtendedReg(
7293 const MachineInstr &MI, const MachineRegisterInfo &MRI,
7294 bool IsAddrOperand) const {
7295
7296 // Always fold if there is one use, or if we're optimizing for size.
7297 Register DefReg = MI.getOperand(0).getReg();
7298 if (MRI.hasOneNonDBGUse(DefReg) ||
7299 MI.getParent()->getParent()->getFunction().hasOptSize())
7300 return true;
7301
7302 if (IsAddrOperand) {
7303 // If we are already sure that folding MI is good or bad, return the result.
7304 if (const auto Worth = isWorthFoldingIntoAddrMode(MI, MRI))
7305 return *Worth;
7306
7307 // Fold G_PTR_ADD if its offset operand can be folded
7308 if (MI.getOpcode() == AArch64::G_PTR_ADD) {
7309 MachineInstr *OffsetInst =
7310 getDefIgnoringCopies(MI.getOperand(2).getReg(), MRI);
7311
7312 // Note, we already know G_PTR_ADD is used by at least two instructions.
7313 // If we are also sure about whether folding is beneficial or not,
7314 // return the result.
7315 if (const auto Worth = isWorthFoldingIntoAddrMode(*OffsetInst, MRI))
7316 return *Worth;
7317 }
7318 }
7319
7320 // FIXME: Consider checking HasALULSLFast as appropriate.
7321
7322 // We have a fastpath, so folding a shift in and potentially computing it
7323 // many times may be beneficial. Check if this is only used in memory ops.
7324 // If it is, then we should fold.
7325 return all_of(MRI.use_nodbg_instructions(DefReg),
7326 [](MachineInstr &Use) { return Use.mayLoadOrStore(); });
7327}
7328
7329InstructionSelector::ComplexRendererFns
7330AArch64InstructionSelector::selectExtendedSHL(
7331 MachineOperand &Root, MachineOperand &Base, MachineOperand &Offset,
7332 unsigned SizeInBytes, bool WantsExt) const {
7333 assert(Base.isReg() && "Expected base to be a register operand");
7334 assert(Offset.isReg() && "Expected offset to be a register operand");
7335
7336 MachineRegisterInfo &MRI = Root.getParent()->getMF()->getRegInfo();
7337 MachineInstr *OffsetInst = MRI.getVRegDef(Offset.getReg());
7338
7339 unsigned OffsetOpc = OffsetInst->getOpcode();
7340 bool LookedThroughZExt = false;
7341 if (OffsetOpc != TargetOpcode::G_SHL && OffsetOpc != TargetOpcode::G_MUL) {
7342 // Try to look through a ZEXT.
7343 if (OffsetOpc != TargetOpcode::G_ZEXT || !WantsExt)
7344 return std::nullopt;
7345
7346 OffsetInst = MRI.getVRegDef(OffsetInst->getOperand(1).getReg());
7347 OffsetOpc = OffsetInst->getOpcode();
7348 LookedThroughZExt = true;
7349
7350 if (OffsetOpc != TargetOpcode::G_SHL && OffsetOpc != TargetOpcode::G_MUL)
7351 return std::nullopt;
7352 }
7353 // Make sure that the memory op is a valid size.
7354 int64_t LegalShiftVal = Log2_32(SizeInBytes);
7355 if (LegalShiftVal == 0)
7356 return std::nullopt;
7357 if (!isWorthFoldingIntoExtendedReg(*OffsetInst, MRI, true))
7358 return std::nullopt;
7359
7360 // Now, try to find the specific G_CONSTANT. Start by assuming that the
7361 // register we will offset is the LHS, and the register containing the
7362 // constant is the RHS.
7363 Register OffsetReg = OffsetInst->getOperand(1).getReg();
7364 Register ConstantReg = OffsetInst->getOperand(2).getReg();
7365 auto ValAndVReg = getIConstantVRegValWithLookThrough(ConstantReg, MRI);
7366 if (!ValAndVReg) {
7367 // We didn't get a constant on the RHS. If the opcode is a shift, then
7368 // we're done.
7369 if (OffsetOpc == TargetOpcode::G_SHL)
7370 return std::nullopt;
7371
7372 // If we have a G_MUL, we can use either register. Try looking at the RHS.
7373 std::swap(OffsetReg, ConstantReg);
7374 ValAndVReg = getIConstantVRegValWithLookThrough(ConstantReg, MRI);
7375 if (!ValAndVReg)
7376 return std::nullopt;
7377 }
7378
7379 // The value must fit into 3 bits, and must be positive. Make sure that is
7380 // true.
7381 int64_t ImmVal = ValAndVReg->Value.getSExtValue();
7382
7383 // Since we're going to pull this into a shift, the constant value must be
7384 // a power of 2. If we got a multiply, then we need to check this.
7385 if (OffsetOpc == TargetOpcode::G_MUL) {
7386 if (!llvm::has_single_bit<uint32_t>(ImmVal))
7387 return std::nullopt;
7388
7389 // Got a power of 2. So, the amount we'll shift is the log base-2 of that.
7390 ImmVal = Log2_32(ImmVal);
7391 }
7392
7393 if ((ImmVal & 0x7) != ImmVal)
7394 return std::nullopt;
7395
7396 // We are only allowed to shift by LegalShiftVal. This shift value is built
7397 // into the instruction, so we can't just use whatever we want.
7398 if (ImmVal != LegalShiftVal)
7399 return std::nullopt;
7400
7401 unsigned SignExtend = 0;
7402 if (WantsExt) {
7403 // Check if the offset is defined by an extend, unless we looked through a
7404 // G_ZEXT earlier.
7405 if (!LookedThroughZExt) {
7406 MachineInstr *ExtInst = getDefIgnoringCopies(OffsetReg, MRI);
7407 auto Ext = getExtendTypeForInst(*ExtInst, MRI, true);
7409 return std::nullopt;
7410
7411 SignExtend = AArch64_AM::isSignExtendShiftType(Ext) ? 1 : 0;
7412 // We only support SXTW for signed extension here.
7413 if (SignExtend && Ext != AArch64_AM::SXTW)
7414 return std::nullopt;
7415 OffsetReg = ExtInst->getOperand(1).getReg();
7416 }
7417
7418 // Need a 32-bit wide register here.
7419 MachineIRBuilder MIB(*MRI.getVRegDef(Root.getReg()));
7420 OffsetReg = moveScalarRegClass(OffsetReg, AArch64::GPR32RegClass, MIB);
7421 }
7422
7423 // We can use the LHS of the GEP as the base, and the LHS of the shift as an
7424 // offset. Signify that we are shifting by setting the shift flag to 1.
7425 return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(Base.getReg()); },
7426 [=](MachineInstrBuilder &MIB) { MIB.addUse(OffsetReg); },
7427 [=](MachineInstrBuilder &MIB) {
7428 // Need to add both immediates here to make sure that they are both
7429 // added to the instruction.
7430 MIB.addImm(SignExtend);
7431 MIB.addImm(1);
7432 }}};
7433}
7434
7435/// This is used for computing addresses like this:
7436///
7437/// ldr x1, [x2, x3, lsl #3]
7438///
7439/// Where x2 is the base register, and x3 is an offset register. The shift-left
7440/// is a constant value specific to this load instruction. That is, we'll never
7441/// see anything other than a 3 here (which corresponds to the size of the
7442/// element being loaded.)
7443InstructionSelector::ComplexRendererFns
7444AArch64InstructionSelector::selectAddrModeShiftedExtendXReg(
7445 MachineOperand &Root, unsigned SizeInBytes) const {
7446 if (!Root.isReg())
7447 return std::nullopt;
7448 MachineRegisterInfo &MRI = Root.getParent()->getMF()->getRegInfo();
7449
7450 // We want to find something like this:
7451 //
7452 // val = G_CONSTANT LegalShiftVal
7453 // shift = G_SHL off_reg val
7454 // ptr = G_PTR_ADD base_reg shift
7455 // x = G_LOAD ptr
7456 //
7457 // And fold it into this addressing mode:
7458 //
7459 // ldr x, [base_reg, off_reg, lsl #LegalShiftVal]
7460
7461 // Check if we can find the G_PTR_ADD.
7462 MachineInstr *PtrAdd =
7463 getOpcodeDef(TargetOpcode::G_PTR_ADD, Root.getReg(), MRI);
7464 if (!PtrAdd || !isWorthFoldingIntoExtendedReg(*PtrAdd, MRI, true))
7465 return std::nullopt;
7466
7467 // Now, try to match an opcode which will match our specific offset.
7468 // We want a G_SHL or a G_MUL.
7469 MachineInstr *OffsetInst =
7471 return selectExtendedSHL(Root, PtrAdd->getOperand(1),
7472 OffsetInst->getOperand(0), SizeInBytes,
7473 /*WantsExt=*/false);
7474}
7475
7476/// This is used for computing addresses like this:
7477///
7478/// ldr x1, [x2, x3]
7479///
7480/// Where x2 is the base register, and x3 is an offset register.
7481///
7482/// When possible (or profitable) to fold a G_PTR_ADD into the address
7483/// calculation, this will do so. Otherwise, it will return std::nullopt.
7484InstructionSelector::ComplexRendererFns
7485AArch64InstructionSelector::selectAddrModeRegisterOffset(
7486 MachineOperand &Root) const {
7487 MachineRegisterInfo &MRI = Root.getParent()->getMF()->getRegInfo();
7488
7489 // We need a GEP.
7491 if (!mi_match(Root.getReg(), MRI, m_GPtrAdd(m_Reg(Base), m_Reg(Offset))))
7492 return std::nullopt;
7493
7494 // If this is used more than once, let's not bother folding.
7495 // TODO: Check if they are memory ops. If they are, then we can still fold
7496 // without having to recompute anything.
7497 if (!MRI.hasOneNonDBGUse(Root.getReg()))
7498 return std::nullopt;
7499
7500 // Base is the GEP's LHS, offset is its RHS.
7501 return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(Base); },
7502 [=](MachineInstrBuilder &MIB) { MIB.addUse(Offset); },
7503 [=](MachineInstrBuilder &MIB) {
7504 // Need to add both immediates here to make sure that they are both
7505 // added to the instruction.
7506 MIB.addImm(0);
7507 MIB.addImm(0);
7508 }}};
7509}
7510
7511/// This is intended to be equivalent to selectAddrModeXRO in
7512/// AArch64ISelDAGtoDAG. It's used for selecting X register offset loads.
7513InstructionSelector::ComplexRendererFns
7514AArch64InstructionSelector::selectAddrModeXRO(MachineOperand &Root,
7515 unsigned SizeInBytes) const {
7516 MachineRegisterInfo &MRI = Root.getParent()->getMF()->getRegInfo();
7517 if (!Root.isReg())
7518 return std::nullopt;
7519 MachineInstr *PtrAdd =
7520 getOpcodeDef(TargetOpcode::G_PTR_ADD, Root.getReg(), MRI);
7521 if (!PtrAdd)
7522 return std::nullopt;
7523
7524 // Check for an immediates which cannot be encoded in the [base + imm]
7525 // addressing mode, and can't be encoded in an add/sub. If this happens, we'll
7526 // end up with code like:
7527 //
7528 // mov x0, wide
7529 // add x1 base, x0
7530 // ldr x2, [x1, x0]
7531 //
7532 // In this situation, we can use the [base, xreg] addressing mode to save an
7533 // add/sub:
7534 //
7535 // mov x0, wide
7536 // ldr x2, [base, x0]
7537 auto ValAndVReg =
7539 if (ValAndVReg) {
7540 unsigned Scale = Log2_32(SizeInBytes);
7541 int64_t ImmOff = ValAndVReg->Value.getSExtValue();
7542
7543 // Skip immediates that can be selected in the load/store addressing
7544 // mode.
7545 if (ImmOff % SizeInBytes == 0 && ImmOff >= 0 &&
7546 ImmOff < (0x1000 << Scale))
7547 return std::nullopt;
7548
7549 // Helper lambda to decide whether or not it is preferable to emit an add.
7550 auto isPreferredADD = [](int64_t ImmOff) {
7551 // Constants in [0x0, 0xfff] can be encoded in an add.
7552 if ((ImmOff & 0xfffffffffffff000LL) == 0x0LL)
7553 return true;
7554
7555 // Can it be encoded in an add lsl #12?
7556 if ((ImmOff & 0xffffffffff000fffLL) != 0x0LL)
7557 return false;
7558
7559 // It can be encoded in an add lsl #12, but we may not want to. If it is
7560 // possible to select this as a single movz, then prefer that. A single
7561 // movz is faster than an add with a shift.
7562 return (ImmOff & 0xffffffffff00ffffLL) != 0x0LL &&
7563 (ImmOff & 0xffffffffffff0fffLL) != 0x0LL;
7564 };
7565
7566 // If the immediate can be encoded in a single add/sub, then bail out.
7567 if (isPreferredADD(ImmOff) || isPreferredADD(-ImmOff))
7568 return std::nullopt;
7569 }
7570
7571 // Try to fold shifts into the addressing mode.
7572 auto AddrModeFns = selectAddrModeShiftedExtendXReg(Root, SizeInBytes);
7573 if (AddrModeFns)
7574 return AddrModeFns;
7575
7576 // If that doesn't work, see if it's possible to fold in registers from
7577 // a GEP.
7578 return selectAddrModeRegisterOffset(Root);
7579}
7580
7581/// This is used for computing addresses like this:
7582///
7583/// ldr x0, [xBase, wOffset, sxtw #LegalShiftVal]
7584///
7585/// Where we have a 64-bit base register, a 32-bit offset register, and an
7586/// extend (which may or may not be signed).
7587InstructionSelector::ComplexRendererFns
7588AArch64InstructionSelector::selectAddrModeWRO(MachineOperand &Root,
7589 unsigned SizeInBytes) const {
7590 MachineRegisterInfo &MRI = Root.getParent()->getMF()->getRegInfo();
7591
7592 MachineInstr *PtrAdd =
7593 getOpcodeDef(TargetOpcode::G_PTR_ADD, Root.getReg(), MRI);
7594 if (!PtrAdd || !isWorthFoldingIntoExtendedReg(*PtrAdd, MRI, true))
7595 return std::nullopt;
7596
7597 MachineOperand &LHS = PtrAdd->getOperand(1);
7598 MachineOperand &RHS = PtrAdd->getOperand(2);
7599 MachineInstr *OffsetInst = getDefIgnoringCopies(RHS.getReg(), MRI);
7600
7601 // The first case is the same as selectAddrModeXRO, except we need an extend.
7602 // In this case, we try to find a shift and extend, and fold them into the
7603 // addressing mode.
7604 //
7605 // E.g.
7606 //
7607 // off_reg = G_Z/S/ANYEXT ext_reg
7608 // val = G_CONSTANT LegalShiftVal
7609 // shift = G_SHL off_reg val
7610 // ptr = G_PTR_ADD base_reg shift
7611 // x = G_LOAD ptr
7612 //
7613 // In this case we can get a load like this:
7614 //
7615 // ldr x0, [base_reg, ext_reg, sxtw #LegalShiftVal]
7616 auto ExtendedShl = selectExtendedSHL(Root, LHS, OffsetInst->getOperand(0),
7617 SizeInBytes, /*WantsExt=*/true);
7618 if (ExtendedShl)
7619 return ExtendedShl;
7620
7621 // There was no shift. We can try and fold a G_Z/S/ANYEXT in alone though.
7622 //
7623 // e.g.
7624 // ldr something, [base_reg, ext_reg, sxtw]
7625 if (!isWorthFoldingIntoExtendedReg(*OffsetInst, MRI, true))
7626 return std::nullopt;
7627
7628 // Check if this is an extend. We'll get an extend type if it is.
7630 getExtendTypeForInst(*OffsetInst, MRI, /*IsLoadStore=*/true);
7632 return std::nullopt;
7633
7634 // Need a 32-bit wide register.
7635 MachineIRBuilder MIB(*PtrAdd);
7636 Register ExtReg = moveScalarRegClass(OffsetInst->getOperand(1).getReg(),
7637 AArch64::GPR32RegClass, MIB);
7638 unsigned SignExtend = Ext == AArch64_AM::SXTW;
7639
7640 // Base is LHS, offset is ExtReg.
7641 return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(LHS.getReg()); },
7642 [=](MachineInstrBuilder &MIB) { MIB.addUse(ExtReg); },
7643 [=](MachineInstrBuilder &MIB) {
7644 MIB.addImm(SignExtend);
7645 MIB.addImm(0);
7646 }}};
7647}
7648
7649/// Select a "register plus unscaled signed 9-bit immediate" address. This
7650/// should only match when there is an offset that is not valid for a scaled
7651/// immediate addressing mode. The "Size" argument is the size in bytes of the
7652/// memory reference, which is needed here to know what is valid for a scaled
7653/// immediate.
7654InstructionSelector::ComplexRendererFns
7655AArch64InstructionSelector::selectAddrModeUnscaled(MachineOperand &Root,
7656 unsigned Size) const {
7657 MachineRegisterInfo &MRI =
7658 Root.getParent()->getParent()->getParent()->getRegInfo();
7659
7660 if (!Root.isReg())
7661 return std::nullopt;
7662
7663 if (!isBaseWithConstantOffset(Root, MRI))
7664 return std::nullopt;
7665
7666 MachineInstr *RootDef = MRI.getVRegDef(Root.getReg());
7667
7668 MachineOperand &OffImm = RootDef->getOperand(2);
7669 if (!OffImm.isReg())
7670 return std::nullopt;
7671 MachineInstr *RHS = MRI.getVRegDef(OffImm.getReg());
7672 if (RHS->getOpcode() != TargetOpcode::G_CONSTANT)
7673 return std::nullopt;
7674 int64_t RHSC;
7675 MachineOperand &RHSOp1 = RHS->getOperand(1);
7676 if (!RHSOp1.isCImm() || RHSOp1.getCImm()->getBitWidth() > 64)
7677 return std::nullopt;
7678 RHSC = RHSOp1.getCImm()->getSExtValue();
7679
7680 if (RHSC >= -256 && RHSC < 256) {
7681 MachineOperand &Base = RootDef->getOperand(1);
7682 return {{
7683 [=](MachineInstrBuilder &MIB) { MIB.add(Base); },
7684 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); },
7685 }};
7686 }
7687 return std::nullopt;
7688}
7689
7690InstructionSelector::ComplexRendererFns
7691AArch64InstructionSelector::tryFoldAddLowIntoImm(MachineInstr &RootDef,
7692 unsigned Size,
7693 MachineRegisterInfo &MRI) const {
7694 if (RootDef.getOpcode() != AArch64::G_ADD_LOW)
7695 return std::nullopt;
7696 MachineInstr &Adrp = *MRI.getVRegDef(RootDef.getOperand(1).getReg());
7697 if (Adrp.getOpcode() != AArch64::ADRP)
7698 return std::nullopt;
7699
7700 // TODO: add heuristics like isWorthFoldingADDlow() from SelectionDAG.
7701 auto Offset = Adrp.getOperand(1).getOffset();
7702 if (Offset % Size != 0)
7703 return std::nullopt;
7704
7705 auto GV = Adrp.getOperand(1).getGlobal();
7706 if (GV->isThreadLocal())
7707 return std::nullopt;
7708
7709 auto &MF = *RootDef.getParent()->getParent();
7710 if (GV->getPointerAlignment(MF.getDataLayout()) < Size)
7711 return std::nullopt;
7712
7713 unsigned OpFlags = STI.ClassifyGlobalReference(GV, MF.getTarget());
7714 MachineIRBuilder MIRBuilder(RootDef);
7715 Register AdrpReg = Adrp.getOperand(0).getReg();
7716 return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(AdrpReg); },
7717 [=](MachineInstrBuilder &MIB) {
7718 MIB.addGlobalAddress(GV, Offset,
7719 OpFlags | AArch64II::MO_PAGEOFF |
7721 }}};
7722}
7723
7724/// Select a "register plus scaled unsigned 12-bit immediate" address. The
7725/// "Size" argument is the size in bytes of the memory reference, which
7726/// determines the scale.
7727InstructionSelector::ComplexRendererFns
7728AArch64InstructionSelector::selectAddrModeIndexed(MachineOperand &Root,
7729 unsigned Size) const {
7730 MachineFunction &MF = *Root.getParent()->getParent()->getParent();
7731 MachineRegisterInfo &MRI = MF.getRegInfo();
7732
7733 if (!Root.isReg())
7734 return std::nullopt;
7735
7736 MachineInstr *RootDef = MRI.getVRegDef(Root.getReg());
7737 if (RootDef->getOpcode() == TargetOpcode::G_FRAME_INDEX) {
7738 return {{
7739 [=](MachineInstrBuilder &MIB) { MIB.add(RootDef->getOperand(1)); },
7740 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },
7741 }};
7742 }
7743
7745 // Check if we can fold in the ADD of small code model ADRP + ADD address.
7746 // HACK: ld64 on Darwin doesn't support relocations on PRFM, so we can't fold
7747 // globals into the offset.
7748 MachineInstr *RootParent = Root.getParent();
7749 if (CM == CodeModel::Small &&
7750 !(RootParent->getOpcode() == AArch64::G_AARCH64_PREFETCH &&
7751 STI.isTargetDarwin())) {
7752 auto OpFns = tryFoldAddLowIntoImm(*RootDef, Size, MRI);
7753 if (OpFns)
7754 return OpFns;
7755 }
7756
7757 if (isBaseWithConstantOffset(Root, MRI)) {
7758 MachineOperand &LHS = RootDef->getOperand(1);
7759 MachineOperand &RHS = RootDef->getOperand(2);
7760 MachineInstr *LHSDef = MRI.getVRegDef(LHS.getReg());
7761 MachineInstr *RHSDef = MRI.getVRegDef(RHS.getReg());
7762
7763 int64_t RHSC = (int64_t)RHSDef->getOperand(1).getCImm()->getZExtValue();
7764 unsigned Scale = Log2_32(Size);
7765 if ((RHSC & (Size - 1)) == 0 && RHSC >= 0 && RHSC < (0x1000 << Scale)) {
7766 if (LHSDef->getOpcode() == TargetOpcode::G_FRAME_INDEX)
7767 return {{
7768 [=](MachineInstrBuilder &MIB) { MIB.add(LHSDef->getOperand(1)); },
7769 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC >> Scale); },
7770 }};
7771
7772 return {{
7773 [=](MachineInstrBuilder &MIB) { MIB.add(LHS); },
7774 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC >> Scale); },
7775 }};
7776 }
7777 }
7778
7779 // Before falling back to our general case, check if the unscaled
7780 // instructions can handle this. If so, that's preferable.
7781 if (selectAddrModeUnscaled(Root, Size))
7782 return std::nullopt;
7783
7784 return {{
7785 [=](MachineInstrBuilder &MIB) { MIB.add(Root); },
7786 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },
7787 }};
7788}
7789
7790/// Given a shift instruction, return the correct shift type for that
7791/// instruction.
7793 switch (MI.getOpcode()) {
7794 default:
7796 case TargetOpcode::G_SHL:
7797 return AArch64_AM::LSL;
7798 case TargetOpcode::G_LSHR:
7799 return AArch64_AM::LSR;
7800 case TargetOpcode::G_ASHR:
7801 return AArch64_AM::ASR;
7802 case TargetOpcode::G_ROTR:
7803 return AArch64_AM::ROR;
7804 }
7805}
7806
7807/// Select a "shifted register" operand. If the value is not shifted, set the
7808/// shift operand to a default value of "lsl 0".
7809InstructionSelector::ComplexRendererFns
7810AArch64InstructionSelector::selectShiftedRegister(MachineOperand &Root,
7811 bool AllowROR) const {
7812 if (!Root.isReg())
7813 return std::nullopt;
7814 MachineRegisterInfo &MRI =
7815 Root.getParent()->getParent()->getParent()->getRegInfo();
7816
7817 // Check if the operand is defined by an instruction which corresponds to
7818 // a ShiftExtendType. E.g. a G_SHL, G_LSHR, etc.
7819 MachineInstr *ShiftInst = MRI.getVRegDef(Root.getReg());
7821 if (ShType == AArch64_AM::InvalidShiftExtend)
7822 return std::nullopt;
7823 if (ShType == AArch64_AM::ROR && !AllowROR)
7824 return std::nullopt;
7825 if (!isWorthFoldingIntoExtendedReg(*ShiftInst, MRI, false))
7826 return std::nullopt;
7827
7828 // Need an immediate on the RHS.
7829 MachineOperand &ShiftRHS = ShiftInst->getOperand(2);
7830 auto Immed = getImmedFromMO(ShiftRHS);
7831 if (!Immed)
7832 return std::nullopt;
7833
7834 // We have something that we can fold. Fold in the shift's LHS and RHS into
7835 // the instruction.
7836 MachineOperand &ShiftLHS = ShiftInst->getOperand(1);
7837 Register ShiftReg = ShiftLHS.getReg();
7838
7839 unsigned NumBits = MRI.getType(ShiftReg).getSizeInBits();
7840 unsigned Val = *Immed & (NumBits - 1);
7841 unsigned ShiftVal = AArch64_AM::getShifterImm(ShType, Val);
7842
7843 return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(ShiftReg); },
7844 [=](MachineInstrBuilder &MIB) { MIB.addImm(ShiftVal); }}};
7845}
7846
7847AArch64_AM::ShiftExtendType AArch64InstructionSelector::getExtendTypeForInst(
7848 MachineInstr &MI, MachineRegisterInfo &MRI, bool IsLoadStore) const {
7849 unsigned Opc = MI.getOpcode();
7850
7851 // Handle explicit extend instructions first.
7852 if (Opc == TargetOpcode::G_SEXT || Opc == TargetOpcode::G_SEXT_INREG) {
7853 unsigned Size;
7854 if (Opc == TargetOpcode::G_SEXT)
7855 Size = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
7856 else
7857 Size = MI.getOperand(2).getImm();
7858 assert(Size != 64 && "Extend from 64 bits?");
7859 switch (Size) {
7860 case 8:
7861 return IsLoadStore ? AArch64_AM::InvalidShiftExtend : AArch64_AM::SXTB;
7862 case 16:
7863 return IsLoadStore ? AArch64_AM::InvalidShiftExtend : AArch64_AM::SXTH;
7864 case 32:
7865 return AArch64_AM::SXTW;
7866 default:
7868 }
7869 }
7870
7871 if (Opc == TargetOpcode::G_ZEXT || Opc == TargetOpcode::G_ANYEXT) {
7872 unsigned Size = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
7873 assert(Size != 64 && "Extend from 64 bits?");
7874 switch (Size) {
7875 case 8:
7876 return IsLoadStore ? AArch64_AM::InvalidShiftExtend : AArch64_AM::UXTB;
7877 case 16:
7878 return IsLoadStore ? AArch64_AM::InvalidShiftExtend : AArch64_AM::UXTH;
7879 case 32:
7880 return AArch64_AM::UXTW;
7881 default:
7883 }
7884 }
7885
7886 // Don't have an explicit extend. Try to handle a G_AND with a constant mask
7887 // on the RHS.
7888 if (Opc != TargetOpcode::G_AND)
7890
7891 std::optional<uint64_t> MaybeAndMask = getImmedFromMO(MI.getOperand(2));
7892 if (!MaybeAndMask)
7894 uint64_t AndMask = *MaybeAndMask;
7895 switch (AndMask) {
7896 default:
7898 case 0xFF:
7899 return !IsLoadStore ? AArch64_AM::UXTB : AArch64_AM::InvalidShiftExtend;
7900 case 0xFFFF:
7901 return !IsLoadStore ? AArch64_AM::UXTH : AArch64_AM::InvalidShiftExtend;
7902 case 0xFFFFFFFF:
7903 return AArch64_AM::UXTW;
7904 }
7905}
7906
7907Register AArch64InstructionSelector::moveScalarRegClass(
7908 Register Reg, const TargetRegisterClass &RC, MachineIRBuilder &MIB) const {
7909 MachineRegisterInfo &MRI = *MIB.getMRI();
7910 auto Ty = MRI.getType(Reg);
7911 assert(!Ty.isVector() && "Expected scalars only!");
7912 if (Ty.getSizeInBits() == TRI.getRegSizeInBits(RC))
7913 return Reg;
7914
7915 // Create a copy and immediately select it.
7916 // FIXME: We should have an emitCopy function?
7917 auto Copy = MIB.buildCopy({&RC}, {Reg});
7918 selectCopy(*Copy, TII, MRI, TRI, RBI);
7919 return Copy.getReg(0);
7920}
7921
7922/// Select an "extended register" operand. This operand folds in an extend
7923/// followed by an optional left shift.
7924InstructionSelector::ComplexRendererFns
7925AArch64InstructionSelector::selectArithExtendedRegister(
7926 MachineOperand &Root) const {
7927 if (!Root.isReg())
7928 return std::nullopt;
7929 MachineRegisterInfo &MRI =
7930 Root.getParent()->getParent()->getParent()->getRegInfo();
7931
7932 uint64_t ShiftVal = 0;
7933 Register ExtReg;
7935 MachineInstr *RootDef = getDefIgnoringCopies(Root.getReg(), MRI);
7936 if (!RootDef)
7937 return std::nullopt;
7938
7939 if (!isWorthFoldingIntoExtendedReg(*RootDef, MRI, false))
7940 return std::nullopt;
7941
7942 // Check if we can fold a shift and an extend.
7943 if (RootDef->getOpcode() == TargetOpcode::G_SHL) {
7944 // Look for a constant on the RHS of the shift.
7945 MachineOperand &RHS = RootDef->getOperand(2);
7946 std::optional<uint64_t> MaybeShiftVal = getImmedFromMO(RHS);
7947 if (!MaybeShiftVal)
7948 return std::nullopt;
7949 ShiftVal = *MaybeShiftVal;
7950 if (ShiftVal > 4)
7951 return std::nullopt;
7952 // Look for a valid extend instruction on the LHS of the shift.
7953 MachineOperand &LHS = RootDef->getOperand(1);
7954 MachineInstr *ExtDef = getDefIgnoringCopies(LHS.getReg(), MRI);
7955 if (!ExtDef)
7956 return std::nullopt;
7957 Ext = getExtendTypeForInst(*ExtDef, MRI);
7959 return std::nullopt;
7960 ExtReg = ExtDef->getOperand(1).getReg();
7961 } else {
7962 // Didn't get a shift. Try just folding an extend.
7963 Ext = getExtendTypeForInst(*RootDef, MRI);
7965 return std::nullopt;
7966 ExtReg = RootDef->getOperand(1).getReg();
7967
7968 // If we have a 32 bit instruction which zeroes out the high half of a
7969 // register, we get an implicit zero extend for free. Check if we have one.
7970 // FIXME: We actually emit the extend right now even though we don't have
7971 // to.
7972 if (Ext == AArch64_AM::UXTW && MRI.getType(ExtReg).getSizeInBits() == 32) {
7973 MachineInstr *ExtInst = MRI.getVRegDef(ExtReg);
7974 if (isDef32(*ExtInst))
7975 return std::nullopt;
7976 }
7977 }
7978
7979 // We require a GPR32 here. Narrow the ExtReg if needed using a subregister
7980 // copy.
7981 MachineIRBuilder MIB(*RootDef);
7982 ExtReg = moveScalarRegClass(ExtReg, AArch64::GPR32RegClass, MIB);
7983
7984 return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(ExtReg); },
7985 [=](MachineInstrBuilder &MIB) {
7986 MIB.addImm(getArithExtendImm(Ext, ShiftVal));
7987 }}};
7988}
7989
7990InstructionSelector::ComplexRendererFns
7991AArch64InstructionSelector::selectExtractHigh(MachineOperand &Root) const {
7992 if (!Root.isReg())
7993 return std::nullopt;
7994 MachineRegisterInfo &MRI =
7995 Root.getParent()->getParent()->getParent()->getRegInfo();
7996
7997 auto Extract = getDefSrcRegIgnoringCopies(Root.getReg(), MRI);
7998 while (Extract && Extract->MI->getOpcode() == TargetOpcode::G_BITCAST &&
7999 STI.isLittleEndian())
8000 Extract =
8001 getDefSrcRegIgnoringCopies(Extract->MI->getOperand(1).getReg(), MRI);
8002 if (!Extract)
8003 return std::nullopt;
8004
8005 if (auto *Unmerge = dyn_cast<GUnmerge>(Extract->MI)) {
8006 if (Unmerge->getNumDefs() == 2 &&
8007 Extract->Reg == Unmerge->getOperand(1).getReg()) {
8008 Register ExtReg = Unmerge->getSourceReg();
8009 return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(ExtReg); }}};
8010 }
8011 }
8012 if (auto *ExtElt = dyn_cast<GExtractVectorElement>(Extract->MI)) {
8013 LLT SrcTy = MRI.getType(ExtElt->getVectorReg());
8014 auto LaneIdx =
8015 getIConstantVRegValWithLookThrough(ExtElt->getIndexReg(), MRI);
8016 if (LaneIdx && SrcTy == LLT::fixed_vector(2, 64) &&
8017 LaneIdx->Value.getSExtValue() == 1) {
8018 Register ExtReg = ExtElt->getVectorReg();
8019 return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(ExtReg); }}};
8020 }
8021 }
8022 if (auto *Subvec = dyn_cast<GExtractSubvector>(Extract->MI)) {
8023 LLT SrcTy = MRI.getType(Subvec->getSrcVec());
8024 auto LaneIdx = Subvec->getIndexImm();
8025 if (LaneIdx == SrcTy.getNumElements() / 2) {
8026 Register ExtReg = Subvec->getSrcVec();
8027 return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(ExtReg); }}};
8028 }
8029 }
8030
8031 return std::nullopt;
8032}
8033
8034InstructionSelector::ComplexRendererFns
8035AArch64InstructionSelector::selectCVTFixedPointBase(const MachineOperand &Root,
8036 unsigned DstElemWidth,
8037 bool isReciprocal) const {
8038 if (!Root.isReg())
8039 return std::nullopt;
8040 const MachineRegisterInfo &MRI =
8041 Root.getParent()->getParent()->getParent()->getRegInfo();
8042
8043 Register Reg = Root.getReg();
8044 MachineInstr *Dup = getDefIgnoringCopies(Reg, MRI);
8045
8046 if (Dup && Dup->getOpcode() == TargetOpcode::G_SPLAT_VECTOR)
8047 Reg = Dup->getOperand(1).getReg();
8048
8049 std::optional<ValueAndVReg> CstVal =
8051
8052 if (!CstVal)
8053 return std::nullopt;
8054
8055 unsigned CstElemWidth = MRI.getType(Reg).getScalarSizeInBits();
8056 APFloat FVal(0.0);
8057 switch (CstElemWidth) {
8058 case 16:
8059 FVal = APFloat(APFloat::IEEEhalf(), CstVal->Value.trunc(CstElemWidth));
8060 break;
8061 case 32:
8062 FVal = APFloat(APFloat::IEEEsingle(), CstVal->Value);
8063 break;
8064 case 64:
8065 FVal = APFloat(APFloat::IEEEdouble(), CstVal->Value);
8066 break;
8067 default:
8068 return std::nullopt;
8069 };
8070 if (unsigned FBits =
8071 CheckFixedPointOperandConstant(FVal, DstElemWidth, isReciprocal))
8072 return {{[=](MachineInstrBuilder &MIB) { MIB.addImm(FBits); }}};
8073
8074 return std::nullopt;
8075}
8076
8077unsigned AArch64InstructionSelector::getFixedPointWidthFromOperand(
8078 const MachineOperand &Root) const {
8079 return Root.getParent()
8080 ->getMF()
8081 ->getRegInfo()
8082 .getType(Root.getReg())
8084}
8085
8086template <unsigned Width>
8087InstructionSelector::ComplexRendererFns
8088AArch64InstructionSelector::selectCVTFixedPoint(MachineOperand &Root) const {
8089 return selectCVTFixedPointBase(Root, Width, /*isReciprocal*/ false);
8090}
8091
8092template <unsigned Width>
8093InstructionSelector::ComplexRendererFns
8094AArch64InstructionSelector::selectCVTFixedPosRecipOperand(
8095 MachineOperand &Root) const {
8096 return selectCVTFixedPointBase(Root, Width, /*isReciprocal*/ true);
8097}
8098
8099InstructionSelector::ComplexRendererFns
8100AArch64InstructionSelector::selectCVTFixedPointVec(MachineOperand &Root) const {
8101 return selectCVTFixedPointBase(Root, getFixedPointWidthFromOperand(Root),
8102 /*isReciprocal*/ false);
8103}
8104
8105InstructionSelector::ComplexRendererFns
8106AArch64InstructionSelector::selectCVTFixedPosRecipOperandVec(
8107 MachineOperand &Root) const {
8108 return selectCVTFixedPointBase(Root, getFixedPointWidthFromOperand(Root),
8109 /*isReciprocal*/ true);
8110}
8111
8112void AArch64InstructionSelector::renderFixedPointScalarXForm(
8113 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
8114 assert(OpIdx == 3 && MI.getOperand(OpIdx).isImm() &&
8115 "Expected vecshift immediate operand");
8116 MIB.addImm(MI.getOperand(OpIdx).getImm());
8117}
8118
8119void AArch64InstructionSelector::renderFixedPointImm(MachineInstrBuilder &MIB,
8120 const MachineOperand &Root,
8121 unsigned Width,
8122 bool isReciprocal) const {
8123 // FIXME: This is only needed to satisfy the type checking in tablegen, and
8124 // should be able to reuse the Renderers already calculated by
8125 // selectCVTFixedPointBase.
8126 InstructionSelector::ComplexRendererFns Renderer =
8127 selectCVTFixedPointBase(Root, Width, isReciprocal);
8128 assert((Renderer && Renderer->size() == 1) &&
8129 "Expected selectCVTFixedPointBase to provide a function\n");
8130 (Renderer->front())(MIB);
8131}
8132
8133void AArch64InstructionSelector::renderFixedPointXForm(MachineInstrBuilder &MIB,
8134 const MachineInstr &MI,
8135 int OpIdx) const {
8136 const MachineOperand &Root = MI.getOperand(OpIdx);
8137 renderFixedPointImm(MIB, Root, getFixedPointWidthFromOperand(Root),
8138 /*isReciprocal*/ false);
8139}
8140
8141void AArch64InstructionSelector::renderFixedPointRecipXForm(
8142 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
8143 const MachineOperand &Root = MI.getOperand(OpIdx);
8144 renderFixedPointImm(MIB, Root, getFixedPointWidthFromOperand(Root),
8145 /*isReciprocal*/ true);
8146}
8147
8148void AArch64InstructionSelector::renderTruncImm(MachineInstrBuilder &MIB,
8149 const MachineInstr &MI,
8150 int OpIdx) const {
8151 const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
8152 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
8153 "Expected G_CONSTANT");
8154 std::optional<int64_t> CstVal =
8155 getIConstantVRegSExtVal(MI.getOperand(0).getReg(), MRI);
8156 assert(CstVal && "Expected constant value");
8157 MIB.addImm(*CstVal);
8158}
8159
8160void AArch64InstructionSelector::renderLogicalImm32(
8161 MachineInstrBuilder &MIB, const MachineInstr &I, int OpIdx) const {
8162 assert(I.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
8163 "Expected G_CONSTANT");
8164 uint64_t CstVal = I.getOperand(1).getCImm()->getZExtValue();
8166 MIB.addImm(Enc);
8167}
8168
8169void AArch64InstructionSelector::renderLogicalImm64(
8170 MachineInstrBuilder &MIB, const MachineInstr &I, int OpIdx) const {
8171 assert(I.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
8172 "Expected G_CONSTANT");
8173 uint64_t CstVal = I.getOperand(1).getCImm()->getZExtValue();
8175 MIB.addImm(Enc);
8176}
8177
8178void AArch64InstructionSelector::renderUbsanTrap(MachineInstrBuilder &MIB,
8179 const MachineInstr &MI,
8180 int OpIdx) const {
8181 assert(MI.getOpcode() == TargetOpcode::G_UBSANTRAP && OpIdx == 0 &&
8182 "Expected G_UBSANTRAP");
8183 MIB.addImm(MI.getOperand(0).getImm() | ('U' << 8));
8184}
8185
8186void AArch64InstructionSelector::renderFPImm16(MachineInstrBuilder &MIB,
8187 const MachineInstr &MI,
8188 int OpIdx) const {
8189 assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 &&
8190 "Expected G_FCONSTANT");
8191 MIB.addImm(
8192 AArch64_AM::getFP16Imm(MI.getOperand(1).getFPImm()->getValueAPF()));
8193}
8194
8195void AArch64InstructionSelector::renderFPImm32(MachineInstrBuilder &MIB,
8196 const MachineInstr &MI,
8197 int OpIdx) const {
8198 assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 &&
8199 "Expected G_FCONSTANT");
8200 MIB.addImm(
8201 AArch64_AM::getFP32Imm(MI.getOperand(1).getFPImm()->getValueAPF()));
8202}
8203
8204void AArch64InstructionSelector::renderFPImm64(MachineInstrBuilder &MIB,
8205 const MachineInstr &MI,
8206 int OpIdx) const {
8207 assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 &&
8208 "Expected G_FCONSTANT");
8209 MIB.addImm(
8210 AArch64_AM::getFP64Imm(MI.getOperand(1).getFPImm()->getValueAPF()));
8211}
8212
8213void AArch64InstructionSelector::renderFPImm32SIMDModImmType4(
8214 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
8215 assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 &&
8216 "Expected G_FCONSTANT");
8218 .getFPImm()
8219 ->getValueAPF()
8220 .bitcastToAPInt()
8221 .getZExtValue()));
8222}
8223
8224bool AArch64InstructionSelector::isLoadStoreOfNumBytes(
8225 const MachineInstr &MI, unsigned NumBytes) const {
8226 if (!MI.mayLoadOrStore())
8227 return false;
8228 assert(MI.hasOneMemOperand() &&
8229 "Expected load/store to have only one mem op!");
8230 return (*MI.memoperands_begin())->getSize() == NumBytes;
8231}
8232
8233bool AArch64InstructionSelector::isDef32(const MachineInstr &MI) const {
8234 const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
8235 if (MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() != 32)
8236 return false;
8237
8238 // Only return true if we know the operation will zero-out the high half of
8239 // the 64-bit register. Truncates can be subregister copies, which don't
8240 // zero out the high bits. Copies and other copy-like instructions can be
8241 // fed by truncates, or could be lowered as subregister copies.
8242 switch (MI.getOpcode()) {
8243 default:
8244 return true;
8245 case TargetOpcode::COPY:
8246 case TargetOpcode::G_BITCAST:
8247 case TargetOpcode::G_TRUNC:
8248 case TargetOpcode::G_PHI:
8249 return false;
8250 }
8251}
8252
8253
8254// Perform fixups on the given PHI instruction's operands to force them all
8255// to be the same as the destination regbank.
8257 const AArch64RegisterBankInfo &RBI) {
8258 assert(MI.getOpcode() == TargetOpcode::G_PHI && "Expected a G_PHI");
8259 Register DstReg = MI.getOperand(0).getReg();
8260 const RegisterBank *DstRB = MRI.getRegBankOrNull(DstReg);
8261 assert(DstRB && "Expected PHI dst to have regbank assigned");
8262 MachineIRBuilder MIB(MI);
8263
8264 // Go through each operand and ensure it has the same regbank.
8265 for (MachineOperand &MO : llvm::drop_begin(MI.operands())) {
8266 if (!MO.isReg())
8267 continue;
8268 Register OpReg = MO.getReg();
8269 const RegisterBank *RB = MRI.getRegBankOrNull(OpReg);
8270 if (RB != DstRB) {
8271 // Insert a cross-bank copy.
8272 auto *OpDef = MRI.getVRegDef(OpReg);
8273 const LLT &Ty = MRI.getType(OpReg);
8274 MachineBasicBlock &OpDefBB = *OpDef->getParent();
8275
8276 // Any instruction we insert must appear after all PHIs in the block
8277 // for the block to be valid MIR.
8278 MachineBasicBlock::iterator InsertPt = std::next(OpDef->getIterator());
8279 if (InsertPt != OpDefBB.end() && InsertPt->isPHI())
8280 InsertPt = OpDefBB.getFirstNonPHI();
8281 MIB.setInsertPt(*OpDef->getParent(), InsertPt);
8282 auto Copy = MIB.buildCopy(Ty, OpReg);
8283 MRI.setRegBank(Copy.getReg(0), *DstRB);
8284 MO.setReg(Copy.getReg(0));
8285 }
8286 }
8287}
8288
8289void AArch64InstructionSelector::processPHIs(MachineFunction &MF) {
8290 // We're looking for PHIs, build a list so we don't invalidate iterators.
8291 MachineRegisterInfo &MRI = MF.getRegInfo();
8293 for (auto &BB : MF) {
8294 for (auto &MI : BB) {
8295 if (MI.getOpcode() == TargetOpcode::G_PHI)
8296 Phis.emplace_back(&MI);
8297 }
8298 }
8299
8300 for (auto *MI : Phis) {
8301 // We need to do some work here if the operand types are < 16 bit and they
8302 // are split across fpr/gpr banks. Since all types <32b on gpr
8303 // end up being assigned gpr32 regclasses, we can end up with PHIs here
8304 // which try to select between a gpr32 and an fpr16. Ideally RBS shouldn't
8305 // be selecting heterogenous regbanks for operands if possible, but we
8306 // still need to be able to deal with it here.
8307 //
8308 // To fix this, if we have a gpr-bank operand < 32b in size and at least
8309 // one other operand is on the fpr bank, then we add cross-bank copies
8310 // to homogenize the operand banks. For simplicity the bank that we choose
8311 // to settle on is whatever bank the def operand has. For example:
8312 //
8313 // %endbb:
8314 // %dst:gpr(s16) = G_PHI %in1:gpr(s16), %bb1, %in2:fpr(s16), %bb2
8315 // =>
8316 // %bb2:
8317 // ...
8318 // %in2_copy:gpr(s16) = COPY %in2:fpr(s16)
8319 // ...
8320 // %endbb:
8321 // %dst:gpr(s16) = G_PHI %in1:gpr(s16), %bb1, %in2_copy:gpr(s16), %bb2
8322 bool HasGPROp = false, HasFPROp = false;
8323 for (const MachineOperand &MO : llvm::drop_begin(MI->operands())) {
8324 if (!MO.isReg())
8325 continue;
8326 const LLT &Ty = MRI.getType(MO.getReg());
8327 if (!Ty.isValid() || !Ty.isScalar())
8328 break;
8329 if (Ty.getSizeInBits() >= 32)
8330 break;
8331 const RegisterBank *RB = MRI.getRegBankOrNull(MO.getReg());
8332 // If for some reason we don't have a regbank yet. Don't try anything.
8333 if (!RB)
8334 break;
8335
8336 if (RB->getID() == AArch64::GPRRegBankID)
8337 HasGPROp = true;
8338 else
8339 HasFPROp = true;
8340 }
8341 // We have heterogenous regbanks, need to fixup.
8342 if (HasGPROp && HasFPROp)
8343 fixupPHIOpBanks(*MI, MRI, RBI);
8344 }
8345}
8346
8347namespace llvm {
8348InstructionSelector *
8351 const AArch64RegisterBankInfo &RBI) {
8352 return new AArch64InstructionSelector(TM, Subtarget, RBI);
8353}
8354}
#define Success
MachineInstrBuilder MachineInstrBuilder & DefMI
static std::tuple< SDValue, SDValue > extractPtrauthBlendDiscriminators(SDValue Disc, SelectionDAG *DAG)
static bool isPreferredADD(int64_t ImmOff)
static SDValue emitConditionalComparison(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue CCOp, AArch64CC::CondCode Predicate, AArch64CC::CondCode OutCC, const SDLoc &DL, SelectionDAG &DAG)
can be transformed to: not (and (not (and (setCC (cmp C)) (setCD (cmp D)))) (and (not (setCA (cmp A))...
static bool isCMN(SDValue Op, ISD::CondCode CC, SelectionDAG &DAG)
static SDValue emitConjunctionRec(SelectionDAG &DAG, SDValue Val, AArch64CC::CondCode &OutCC, bool Negate, SDValue CCOp, AArch64CC::CondCode Predicate)
Emit conjunction or disjunction tree with the CMP/FCMP followed by a chain of CCMP/CFCMP ops.
static void changeFPCCToANDAArch64CC(ISD::CondCode CC, AArch64CC::CondCode &CondCode, AArch64CC::CondCode &CondCode2)
Convert a DAG fp condition code to an AArch64 CC.
const AArch64Subtarget & Subtarget
static bool canEmitConjunction(SelectionDAG &DAG, const SDValue Val, bool &CanNegate, bool &MustBeFirst, bool &PreferFirst, bool WillNegate, unsigned Depth=0)
Returns true if Val is a tree of AND/OR/SETCC operations that can be expressed as a conjunction.
const TargetLowering & TLI
SDValue Pred
static SDValue emitConjunction(SelectionDAG &DAG, SDValue Val, AArch64CC::CondCode &OutCC)
Emit expression as a conjunction (a series of CCMP/CFCMP ops).
#define GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
static Register getTestBitReg(Register Reg, uint64_t &Bit, bool &Invert, MachineRegisterInfo &MRI)
Return a register which can be used as a bit to test in a TB(N)Z.
static unsigned getMinSizeForRegBank(const RegisterBank &RB)
Returns the minimum size the given register bank can hold.
static unsigned selectLoadStoreUIOp(unsigned GenericOpc, unsigned RegBankID, unsigned OpSize)
Select the AArch64 opcode for the G_LOAD or G_STORE operation GenericOpc, appropriate for the (value)...
static const TargetRegisterClass * getMinClassForRegBank(const RegisterBank &RB, TypeSize SizeInBits, bool GetAllRegSet=false)
Given a register bank, and size in bits, return the smallest register class that can represent that c...
static std::optional< APInt > getVectorShiftImm(Register Reg, MachineRegisterInfo &MRI)
Returns the element immediate value of a vector shift operand if found.
static unsigned selectBinaryOp(unsigned GenericOpc, unsigned RegBankID, unsigned OpSize)
Select the AArch64 opcode for the basic binary operation GenericOpc, appropriate for the register ban...
static bool getSubRegForClass(const TargetRegisterClass *RC, const TargetRegisterInfo &TRI, unsigned &SubReg)
Returns the correct subregister to use for a given register class.
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
static bool copySubReg(MachineInstr &I, MachineRegisterInfo &MRI, const RegisterBankInfo &RBI, Register SrcReg, const TargetRegisterClass *To, unsigned SubReg)
Helper function for selectCopy.
static AArch64CC::CondCode changeICMPPredToAArch64CC(CmpInst::Predicate P, Register RHS={}, MachineRegisterInfo *MRI=nullptr)
static std::optional< uint64_t > getVectorSHLImm(LLT SrcTy, Register Reg, MachineRegisterInfo &MRI)
Matches and returns the shift immediate value for a SHL instruction given a shift operand.
static Register createDTuple(ArrayRef< Register > Regs, MachineIRBuilder &MIB)
Create a tuple of D-registers using the registers in Regs.
static void fixupPHIOpBanks(MachineInstr &MI, MachineRegisterInfo &MRI, const AArch64RegisterBankInfo &RBI)
static AArch64_AM::ShiftExtendType getShiftTypeForInst(MachineInstr &MI)
Given a shift instruction, return the correct shift type for that instruction.
static bool getLaneCopyOpcode(unsigned &CopyOpc, unsigned &ExtractSubReg, const unsigned EltSize)
static Register createQTuple(ArrayRef< Register > Regs, MachineIRBuilder &MIB)
Create a tuple of Q-registers using the registers in Regs.
static std::optional< uint64_t > getImmedFromMO(const MachineOperand &Root)
static std::pair< unsigned, unsigned > getInsertVecEltOpInfo(const RegisterBank &RB, unsigned EltSize)
Return an <Opcode, SubregIndex> pair to do an vector elt insert of a given size and RB.
static Register createTuple(ArrayRef< Register > Regs, const unsigned RegClassIDs[], const unsigned SubRegs[], MachineIRBuilder &MIB)
Create a REG_SEQUENCE instruction using the registers in Regs.
static void changeFPCCToORAArch64CC(CmpInst::Predicate CC, AArch64CC::CondCode &CondCode, AArch64CC::CondCode &CondCode2)
changeFPCCToORAArch64CC - Convert an IR fp condition code to an AArch64 CC.
unsigned RegSize
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file declares the targeting of the RegisterBankInfo class for AArch64.
uint64_t uint64_t
uint64_t Imm
constexpr LLT S16
constexpr LLT S32
constexpr LLT S64
constexpr LLT S8
static bool isStore(int Opcode)
static bool selectMergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
static bool selectUnmergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
MachineBasicBlock & MBB
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file contains constants used for implementing Dwarf debug support.
Provides analysis for querying information about KnownBits during GISel passes.
#define DEBUG_TYPE
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
static void emitLoadFromConstantPool(Register DstReg, const Constant *ConstVal, MachineIRBuilder &MIRBuilder)
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
Definition Lint.cpp:540
#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 MachineConstantPool class which is an abstract constant pool to keep track of ...
This file declares the MachineIRBuilder class.
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define T
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
#define P(N)
static MachineBasicBlock * emitSelect(MachineInstr &MI, MachineBasicBlock *BB, const TargetInstrInfo *TII, const PPCSubtarget &Subtarget)
Emit SELECT instruction, using ISEL if available, otherwise use branch-based control flow.
if(PassOpts->AAPipeline)
static StringRef getName(Value *V)
RISCVCC::CondCode CC
MachineRegisterInfo & MRI
MachineInstr *& Lo
#define LLVM_DEBUG(...)
Definition Debug.h:119
static constexpr int Concat[]
Value * RHS
Value * LHS
This class provides the information for the target register banks.
std::optional< uint16_t > getPtrAuthBlockAddressDiscriminatorIfEnabled(const Function &ParentFn) const
Compute the integer discriminator for a given BlockAddress constant, if blockaddress signing is enabl...
const AArch64TargetLowering * getTargetLowering() const override
unsigned ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const
ClassifyGlobalReference - Find the target operand flags that describe how a global value should be re...
bool isX16X17Safer() const
Returns whether the operating system makes it safer to store sensitive values in x16 and x17 as oppos...
bool isCallingConvWin64(CallingConv::ID CC, bool IsVarArg) const
APInt bitcastToAPInt() const
Definition APFloat.h:1475
Class for arbitrary precision integers.
Definition APInt.h:78
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1560
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
Definition APInt.cpp:648
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
Definition APInt.h:235
unsigned countr_one() const
Count the number of trailing one bits.
Definition APInt.h:1676
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
bool isEquality() const
Determine if this is an equals/not equals predicate.
Definition InstrTypes.h:978
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
Definition InstrTypes.h:743
@ ICMP_SLT
signed less than
Definition InstrTypes.h:769
@ ICMP_SLE
signed less or equal
Definition InstrTypes.h:770
@ FCMP_OLT
0 1 0 0 True if ordered and less than
Definition InstrTypes.h:746
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
Definition InstrTypes.h:755
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
Definition InstrTypes.h:744
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
Definition InstrTypes.h:745
@ ICMP_UGE
unsigned greater or equal
Definition InstrTypes.h:764
@ ICMP_UGT
unsigned greater than
Definition InstrTypes.h:763
@ ICMP_SGT
signed greater than
Definition InstrTypes.h:767
@ FCMP_ULT
1 1 0 0 True if unordered or less than
Definition InstrTypes.h:754
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
Definition InstrTypes.h:748
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
Definition InstrTypes.h:751
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:765
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
Definition InstrTypes.h:752
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
Definition InstrTypes.h:747
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
Definition InstrTypes.h:749
@ ICMP_NE
not equal
Definition InstrTypes.h:762
@ ICMP_SGE
signed greater or equal
Definition InstrTypes.h:768
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
Definition InstrTypes.h:756
@ ICMP_ULE
unsigned less or equal
Definition InstrTypes.h:766
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
Definition InstrTypes.h:753
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Definition InstrTypes.h:750
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Definition InstrTypes.h:890
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
Definition InstrTypes.h:852
bool isIntPredicate() const
Definition InstrTypes.h:846
bool isUnsigned() const
Definition InstrTypes.h:999
static LLVM_ABI Constant * getSplat(unsigned NumElts, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
const APFloat & getValue() const
Definition Constants.h:464
const APFloat & getValueAPF() const
Definition Constants.h:463
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Definition Constants.h:174
unsigned getBitWidth() const
getBitWidth - Return the scalar bitwidth of this constant.
Definition Constants.h:162
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition Constants.h:168
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
Definition Constant.h:44
TypeSize getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type.
Definition DataLayout.h:579
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:273
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:352
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
Definition Function.h:230
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:731
virtual void setupMF(MachineFunction &mf, GISelValueTracking *vt, CodeGenCoverage *covinfo=nullptr, ProfileSummaryInfo *psi=nullptr, BlockFrequencyInfo *bfi=nullptr)
Setup per-MF executor state.
Represents indexed stores.
Register getPointerReg() const
Get the source register of the pointer value.
MachineMemOperand & getMMO() const
Get the MachineMemOperand on this instruction.
LocationSize getMemSize() const
Returns the size in bytes of the memory access.
LocationSize getMemSizeInBits() const
Returns the size in bits of the memory access.
Represents a G_SELECT.
Register getCondReg() const
Register getFalseReg() const
Register getTrueReg() const
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
bool hasExternalWeakLinkage() const
bool isEquality() const
Return true if this predicate is either EQ or NE.
constexpr bool isScalableVector() const
Returns true if the LLT is a scalable vector.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
LLT multiplyElements(int Factor) const
Produce a vector type that is Factor times bigger, preserving the element type.
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
LLT getScalarType() const
constexpr bool isPointerVector() const
constexpr bool isInteger() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
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 bool isPointer() const
constexpr unsigned getAddressSpace() 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.
static LLT integer(unsigned SizeInBits)
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
TypeSize getValue() const
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
void setFrameAddressIsTaken(bool T)
void setReturnAddressIsTaken(bool s)
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.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Helper class to build MachineInstr.
void setInsertPt(MachineBasicBlock &MBB, MachineBasicBlock::iterator II)
Set the insertion point before the specified position.
void setInstr(MachineInstr &MI)
Set the insertion point to before MI.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
void setInstrAndDebugLoc(MachineInstr &MI)
Set the insertion point to before MI, and set the debug loc to MI's loc.
const MachineBasicBlock & getMBB() const
Getter for the basic block we currently build.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineIRBuilderState & getState()
Getter for the State.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
const DataLayout & getDataLayout() const
void setState(const MachineIRBuilderState &NewState)
Setter for the State.
MachineInstrBuilder buildPtrToInt(const DstOp &Dst, const SrcOp &Src)
Build and insert a G_PTRTOINT instruction.
Register getReg(unsigned Idx) const
Get the register for the operand index.
void constrainAllUses(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) const
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addBlockAddress(const BlockAddress *BA, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addJumpTableIndex(unsigned Idx, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
bool isDebugInstr() const
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
void setImplicitPhysRegDefsDead()
Mark the implicit physreg defs named by the instruction description as dead.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
LLVM_ABI void addMemOperand(MachineFunction &MF, MachineMemOperand *MO)
Add a MachineMemOperand to the machine instruction.
LLT getMemoryType() const
Return the memory type of the memory reference.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
AtomicOrdering getSuccessOrdering() const
Return the atomic ordering requirements for this memory operation.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
const ConstantInt * getCImm() const
bool isCImm() const
isCImm - Test if this is a MO_CImmediate operand.
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
static MachineOperand CreatePredicate(unsigned Pred)
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateGA(const GlobalValue *GV, int64_t Offset, unsigned TargetFlags=0)
static MachineOperand CreateBA(const BlockAddress *BA, int64_t Offset, unsigned TargetFlags=0)
const ConstantFP * getFPImm() const
unsigned getPredicate() const
int64_t getOffset() const
Return the offset from the symbol in this operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
const RegClassOrRegBank & getRegClassOrRegBank(Register Reg) const
Return the register bank or register class of Reg.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
def_instr_iterator def_instr_begin(Register RegNo) const
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
bool hasOneUse(Register RegNo) const
hasOneUse - Return true if there is exactly one instruction using the specified register.
const RegisterBank * getRegBankOrNull(Register Reg) const
Return the register bank of Reg, or null if Reg has not been assigned a register bank or has been ass...
LLVM_ABI void setRegBank(Register Reg, const RegisterBank &RegBank)
Set the register bank to RegBank for Reg.
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
LLVM_ABI void setType(Register VReg, LLT Ty)
Set the low-level type of VReg to Ty.
const MachineFunction & getMF() const
bool hasOneDef(Register RegNo) const
Return true if there is exactly one operand defining the specified register.
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
Analysis providing profile information.
Holds all the information related to register banks.
static const TargetRegisterClass * constrainGenericRegister(Register Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI)
Constrain the (possibly generic) virtual register Reg to RC.
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isValid() const
Definition Register.h:112
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
TargetInstrInfo - Interface to description of machine instruction set.
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize=false) const
Returns true if the specified FP immediate can be materialized without a load from the constant pool.
bool isPositionIndependent() const
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
TargetOptions Options
CodeModel::Model getCodeModel() const
Returns the code model.
unsigned TLSSize
Bit size of immediate TLS offsets (0 == use the default).
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual const TargetLowering * getTargetLowering() const
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:352
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
Definition TypeSize.h:355
Value * getOperand(unsigned i) const
Definition User.h:207
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
Definition Value.cpp:985
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:169
self_iterator getIterator()
Definition ilist_node.h:123
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static CondCode getInvertedCondCode(CondCode Code)
static unsigned getNZCVToSatisfyCondCode(CondCode Code)
Given a condition code, return NZCV flags that would satisfy that condition.
void changeFCMPPredToAArch64CC(const CmpInst::Predicate P, AArch64CC::CondCode &CondCode, AArch64CC::CondCode &CondCode2)
Find the AArch64 condition codes necessary to represent P for a scalar floating point comparison.
@ MO_NC
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow.
@ MO_G1
MO_G1 - A symbol operand with this flag (granule 1) represents the bits 16-31 of a 64-bit address,...
@ MO_PAGEOFF
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page.
@ MO_GOT
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
@ MO_G0
MO_G0 - A symbol operand with this flag (granule 0) represents the bits 0-15 of a 64-bit address,...
@ MO_PAGE
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
@ MO_HI12
MO_HI12 - This flag indicates that a symbol operand represents the bits 13-24 of a 64-bit address,...
@ MO_TLS
MO_TLS - Indicates that the operand being accessed is some kind of thread-local symbol.
@ MO_G2
MO_G2 - A symbol operand with this flag (granule 2) represents the bits 32-47 of a 64-bit address,...
@ MO_G3
MO_G3 - A symbol operand with this flag (granule 3) represents the high 16-bits of a 64-bit address,...
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
static int getFP32Imm(const APInt &Imm)
getFP32Imm - Return an 8-bit floating-point version of the 32-bit floating-point value.
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
static int getFP64Imm(const APInt &Imm)
getFP64Imm - Return an 8-bit floating-point version of the 64-bit floating-point value.
static int getFP16Imm(const APInt &Imm)
getFP16Imm - Return an 8-bit floating-point version of the 16-bit floating-point value.
static uint8_t encodeAdvSIMDModImmType4(uint64_t Imm)
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
static bool isSignExtendShiftType(AArch64_AM::ShiftExtendType Type)
isSignExtendShiftType - Returns true if Type is sign extending.
bool expandVectorMOVImm(APInt Imm, SmallVectorImpl< ImmInsnModel > &Insn, const AArch64Subtarget &ST)
TLSModel::Model getELFTLSModel(const GlobalValue *GV, const AArch64TargetMachine &TM, bool HasELFSignedGOT)
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
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.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
operand_type_match m_Reg()
SpecificConstantMatch m_SpecificICst(const APInt &RequestedValue)
Matches a constant equal to RequestedValue.
UnaryOp_match< SrcTy, TargetOpcode::G_ZEXT > m_GZExt(const SrcTy &Src)
ConstantMatch< APInt > m_ICst(APInt &Cst)
BinaryOp_match< LHS, RHS, TargetOpcode::G_ADD, true > m_GAdd(const LHS &L, const RHS &R)
auto m_PosZeroFP()
Matches a floating-point positive zero.
BinaryOp_match< LHS, RHS, TargetOpcode::G_OR, true > m_GOr(const LHS &L, const RHS &R)
BinaryOp_match< SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB > m_Neg(const SrcTy &&Src)
Matches a register negated by a G_SUB.
ICstOrSplatMatch< APInt > m_ICstOrSplat(APInt &Cst)
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
BinaryOp_match< LHS, RHS, TargetOpcode::G_SUB > m_GSub(const LHS &L, const RHS &R)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
BinaryOp_match< LHS, RHS, TargetOpcode::G_PTR_ADD, false > m_GPtrAdd(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_SHL, false > m_GShl(const LHS &L, const RHS &R)
Or< Preds... > m_any_of(Preds &&... preds)
BinaryOp_match< LHS, RHS, TargetOpcode::G_AND, true > m_GAnd(const LHS &L, const RHS &R)
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
Predicate getPredicate(unsigned Condition, unsigned Hint)
Return predicate consisting of specified condition and hint bits.
constexpr double e
NodeAddr< InstrNode * > Instr
Definition RDFGraph.h:389
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI Register getFunctionLiveInPhysReg(MachineFunction &MF, const TargetInstrInfo &TII, MCRegister PhysReg, const TargetRegisterClass &RC, const DebugLoc &DL, LLT RegTy=LLT())
Return a virtual register corresponding to the incoming argument register PhysReg.
Definition Utils.cpp:896
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
@ Offset
Definition DWP.cpp:577
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:1755
LLVM_ABI Register constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, MachineOperand &RegMO)
Constrain the Register operand OpIdx, so that it is now constrained to the TargetRegisterClass passed...
Definition Utils.cpp:64
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:679
PointerUnion< const TargetRegisterClass *, const RegisterBank * > RegClassOrRegBank
Convenient type to represent either a register class or a register bank.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
Definition Utils.cpp:301
unsigned CheckFixedPointOperandConstant(APFloat &FVal, unsigned RegWidth, bool isReciprocal)
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool isStrongerThanMonotonic(AtomicOrdering AO)
LLVM_ABI void constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
Definition Utils.cpp:163
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel.
unsigned getBLRCallOpcode(const MachineFunction &MF)
Return opcode to be used for indirect calls.
@ O1
Optimize quickly without destroying debuggability.
@ O0
Disable as many optimizations as possible.
LLVM_ABI MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
Definition Utils.cpp:520
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
LLVM_ABI std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
Definition Utils.cpp:321
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
Definition MathExtras.h:274
InstructionSelector * createAArch64InstructionSelector(const AArch64TargetMachine &, const AArch64Subtarget &, const AArch64RegisterBankInfo &)
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
Definition STLExtras.h:2042
constexpr bool has_single_bit(T Value) noexcept
Definition bit.h:149
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:1762
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
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:446
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
AtomicOrdering
Atomic ordering for LLVM's memory model.
@ Sub
Subtraction of integers.
@ Add
Sum of integers.
DWARFExpression::Operation Op
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:440
LLVM_ABI std::optional< DefinitionAndSourceRegister > getDefSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, and underlying value Register folding away any copies.
Definition Utils.cpp:495
LLVM_ABI std::optional< Register > getVectorSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI)
Definition Utils.cpp:1605
LLVM_ABI Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the source register for Reg, folding away any trivial copies.
Definition Utils.cpp:527
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
Definition ValueTypes.h:55
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.