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 = RBI.getSizeInBits(DstReg, MRI, TRI);
889 TypeSize SrcRegSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
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 << RBI.getSizeInBits(DstReg, MRI, TRI) << '\n');
912 return false;
913 }
914
915 if (I.getOpcode() == TargetOpcode::G_BITCAST &&
916 RBI.getSizeInBits(DstReg, MRI, TRI) == 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.
1563 auto Pred = (CmpInst::Predicate)FCmp.getOperand(1).getPredicate();
1564 emitFPCompare(FCmp.getOperand(2).getReg(), FCmp.getOperand(3).getReg(), MIB,
1565 Pred);
1566 AArch64CC::CondCode CC1, CC2;
1567 changeFCMPPredToAArch64CC(Pred, 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.
1637 if (ICmpInst::isEquality(Pred)) {
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,
2428 return nullptr;
2429 auto *Cmp = getOpcodeDef(TargetOpcode::G_ICMP, ZExt, MRI);
2430 if (!Cmp ||
2431 MRI.getType(Cmp->getOperand(2).getReg()).getSizeInBits() != 64)
2432 return nullptr;
2433 return Cmp;
2434 };
2435 // Try to match
2436 // z + (cmp pred, x, y)
2437 MachineInstr *Cmp = MatchCmp(AddRHS);
2438 if (!Cmp) {
2439 // (cmp pred, x, y) + z
2440 std::swap(AddLHS, AddRHS);
2441 Cmp = MatchCmp(AddRHS);
2442 if (!Cmp)
2443 return false;
2444 }
2445 auto &PredOp = Cmp->getOperand(1);
2447 emitIntegerCompare(/*LHS=*/Cmp->getOperand(2),
2448 /*RHS=*/Cmp->getOperand(3), PredOp, MIB);
2449 auto Pred = static_cast<CmpInst::Predicate>(PredOp.getPredicate());
2451 CmpInst::getInversePredicate(Pred), Cmp->getOperand(3).getReg(), &MRI);
2452 emitCSINC(/*Dst=*/AddDst, /*Src =*/AddLHS, /*Src2=*/AddLHS, InvCC, MIB);
2453 I.eraseFromParent();
2454 return true;
2455 }
2456 case TargetOpcode::G_OR: {
2457 // Look for operations that take the lower `Width=Size-ShiftImm` bits of
2458 // `ShiftSrc` and insert them into the upper `Width` bits of `MaskSrc` via
2459 // shifting and masking that we can replace with a BFI (encoded as a BFM).
2460 Register Dst = I.getOperand(0).getReg();
2461 LLT Ty = MRI.getType(Dst);
2462
2463 if (!Ty.isScalar())
2464 return false;
2465
2466 unsigned Size = Ty.getSizeInBits();
2467 if (Size != 32 && Size != 64)
2468 return false;
2469
2470 Register ShiftSrc;
2471 int64_t ShiftImm;
2472 Register MaskSrc;
2473 int64_t MaskImm;
2474 if (!mi_match(
2475 Dst, MRI,
2476 m_GOr(m_OneNonDBGUse(m_GShl(m_Reg(ShiftSrc), m_ICst(ShiftImm))),
2477 m_OneNonDBGUse(m_GAnd(m_Reg(MaskSrc), m_ICst(MaskImm))))))
2478 return false;
2479
2480 if (ShiftImm > Size || ((1ULL << ShiftImm) - 1ULL) != uint64_t(MaskImm))
2481 return false;
2482
2483 int64_t Immr = Size - ShiftImm;
2484 int64_t Imms = Size - ShiftImm - 1;
2485 unsigned Opc = Size == 32 ? AArch64::BFMWri : AArch64::BFMXri;
2486 emitInstr(Opc, {Dst}, {MaskSrc, ShiftSrc, Immr, Imms}, MIB);
2487 I.eraseFromParent();
2488 return true;
2489 }
2490 case TargetOpcode::G_FENCE: {
2491 if (I.getOperand(1).getImm() == 0)
2492 BuildMI(MBB, I, MIMetadata(I), TII.get(TargetOpcode::MEMBARRIER));
2493 else
2494 BuildMI(MBB, I, MIMetadata(I), TII.get(AArch64::DMB))
2495 .addImm(I.getOperand(0).getImm() == 4 ? 0x9 : 0xb);
2496 I.eraseFromParent();
2497 return true;
2498 }
2499 case TargetOpcode::G_BRINDIRECT: {
2500 const Function &Fn = MF.getFunction();
2501 if (std::optional<uint16_t> BADisc =
2503 auto MI = MIB.buildInstr(AArch64::BRA, {}, {I.getOperand(0).getReg()});
2505 MI.addImm(*BADisc);
2506 MI.addReg(/*AddrDisc=*/AArch64::XZR);
2507 I.eraseFromParent();
2509 return true;
2510 }
2511 // Use table-based selection.
2512 return false;
2513 }
2514
2515 default:
2516 return false;
2517 }
2518}
2519
2520bool AArch64InstructionSelector::select(MachineInstr &I) {
2521 assert(I.getParent() && "Instruction should be in a basic block!");
2522 assert(I.getParent()->getParent() && "Instruction should be in a function!");
2523
2524 MachineBasicBlock &MBB = *I.getParent();
2525 MachineFunction &MF = *MBB.getParent();
2526 MachineRegisterInfo &MRI = MF.getRegInfo();
2527
2528 const AArch64Subtarget *Subtarget = &MF.getSubtarget<AArch64Subtarget>();
2529 if (Subtarget->requiresStrictAlign()) {
2530 // We don't support this feature yet.
2531 LLVM_DEBUG(dbgs() << "AArch64 GISel does not support strict-align yet\n");
2532 return false;
2533 }
2534
2536
2537 unsigned Opcode = I.getOpcode();
2538 // G_PHI requires same handling as PHI
2539 if (!I.isPreISelOpcode() || Opcode == TargetOpcode::G_PHI) {
2540 // Certain non-generic instructions also need some special handling.
2541
2542 if (Opcode == TargetOpcode::LOAD_STACK_GUARD) {
2544 return true;
2545 }
2546
2547 if (Opcode == TargetOpcode::PHI || Opcode == TargetOpcode::G_PHI) {
2548 const Register DefReg = I.getOperand(0).getReg();
2549 const LLT DefTy = MRI.getType(DefReg);
2550
2551 const RegClassOrRegBank &RegClassOrBank =
2552 MRI.getRegClassOrRegBank(DefReg);
2553
2554 const TargetRegisterClass *DefRC =
2556 if (!DefRC) {
2557 if (!DefTy.isValid()) {
2558 LLVM_DEBUG(dbgs() << "PHI operand has no type, not a gvreg?\n");
2559 return false;
2560 }
2561 const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
2562 DefRC = getRegClassForTypeOnBank(DefTy, RB);
2563 if (!DefRC) {
2564 LLVM_DEBUG(dbgs() << "PHI operand has unexpected size/bank\n");
2565 return false;
2566 }
2567 }
2568
2569 I.setDesc(TII.get(TargetOpcode::PHI));
2570
2571 return RBI.constrainGenericRegister(DefReg, *DefRC, MRI);
2572 }
2573
2574 if (I.isCopy())
2575 return selectCopy(I, TII, MRI, TRI, RBI);
2576
2577 return true;
2578 }
2579
2580
2581 if (I.getNumOperands() != I.getNumExplicitOperands()) {
2582 LLVM_DEBUG(
2583 dbgs() << "Generic instruction has unexpected implicit operands\n");
2584 return false;
2585 }
2586
2587 // Try to do some lowering before we start instruction selecting. These
2588 // lowerings are purely transformations on the input G_MIR and so selection
2589 // must continue after any modification of the instruction.
2590 if (preISelLower(I)) {
2591 Opcode = I.getOpcode(); // The opcode may have been modified, refresh it.
2592 }
2593
2594 // There may be patterns where the importer can't deal with them optimally,
2595 // but does select it to a suboptimal sequence so our custom C++ selection
2596 // code later never has a chance to work on it. Therefore, we have an early
2597 // selection attempt here to give priority to certain selection routines
2598 // over the imported ones.
2599 if (earlySelect(I))
2600 return true;
2601
2602 if (selectImpl(I, *CoverageInfo))
2603 return true;
2604
2605 LLT Ty =
2606 I.getOperand(0).isReg() ? MRI.getType(I.getOperand(0).getReg()) : LLT{};
2607
2608 switch (Opcode) {
2609 case TargetOpcode::G_SBFX:
2610 case TargetOpcode::G_UBFX: {
2611 static const unsigned OpcTable[2][2] = {
2612 {AArch64::UBFMWri, AArch64::UBFMXri},
2613 {AArch64::SBFMWri, AArch64::SBFMXri}};
2614 bool IsSigned = Opcode == TargetOpcode::G_SBFX;
2615 unsigned Size = Ty.getSizeInBits();
2616 unsigned Opc = OpcTable[IsSigned][Size == 64];
2617 auto Cst1 =
2618 getIConstantVRegValWithLookThrough(I.getOperand(2).getReg(), MRI);
2619 assert(Cst1 && "Should have gotten a constant for src 1?");
2620 auto Cst2 =
2621 getIConstantVRegValWithLookThrough(I.getOperand(3).getReg(), MRI);
2622 assert(Cst2 && "Should have gotten a constant for src 2?");
2623 auto LSB = Cst1->Value.getZExtValue();
2624 auto Width = Cst2->Value.getZExtValue();
2625 auto BitfieldInst =
2626 MIB.buildInstr(Opc, {I.getOperand(0)}, {I.getOperand(1)})
2627 .addImm(LSB)
2628 .addImm(LSB + Width - 1);
2629 I.eraseFromParent();
2630 constrainSelectedInstRegOperands(*BitfieldInst, TII, TRI, RBI);
2631 return true;
2632 }
2633 case TargetOpcode::G_BRCOND:
2634 return selectCompareBranch(I, MF, MRI);
2635
2636 case TargetOpcode::G_BRJT:
2637 return selectBrJT(I, MRI);
2638
2639 case AArch64::G_ADD_LOW: {
2640 // This op may have been separated from it's ADRP companion by the localizer
2641 // or some other code motion pass. Given that many CPUs will try to
2642 // macro fuse these operations anyway, select this into a MOVaddr pseudo
2643 // which will later be expanded into an ADRP+ADD pair after scheduling.
2644 MachineInstr *BaseMI = MRI.getVRegDef(I.getOperand(1).getReg());
2645 if (BaseMI->getOpcode() != AArch64::ADRP) {
2646 I.setDesc(TII.get(AArch64::ADDXri));
2647 I.addOperand(MachineOperand::CreateImm(0));
2649 return true;
2650 }
2652 "Expected small code model");
2653 auto Op1 = BaseMI->getOperand(1);
2654 auto Op2 = I.getOperand(2);
2655 auto MovAddr = MIB.buildInstr(AArch64::MOVaddr, {I.getOperand(0)}, {})
2656 .addGlobalAddress(Op1.getGlobal(), Op1.getOffset(),
2657 Op1.getTargetFlags())
2658 .addGlobalAddress(Op2.getGlobal(), Op2.getOffset(),
2659 Op2.getTargetFlags());
2660 I.eraseFromParent();
2661 constrainSelectedInstRegOperands(*MovAddr, TII, TRI, RBI);
2662 return true;
2663 }
2664
2665 case TargetOpcode::G_FCONSTANT: {
2666 const Register DefReg = I.getOperand(0).getReg();
2667 const LLT DefTy = MRI.getType(DefReg);
2668 const unsigned DefSize = DefTy.getSizeInBits();
2669 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
2670
2671 const TargetRegisterClass &FPRRC = *getRegClassForTypeOnBank(DefTy, RB);
2672 assert(
2673 (DefSize == 16 || DefSize == 32 || DefSize == 64 || DefSize == 128) &&
2674 "Unexpected destination size for G_FCONSTANT?");
2675
2676 // Try to emit as a vector movi.
2677 const ConstantFP *FPImm = I.getOperand(1).getFPImm();
2678 APInt Imm = DefSize >= 64
2679 ? FPImm->getValue().bitcastToAPInt()
2680 : APInt::getSplat(64, FPImm->getValue().bitcastToAPInt());
2681 if (auto *Mov = emitConstantMOVVector(
2682 DefSize >= 64 ? DstOp(DefReg) : DstOp(&AArch64::FPR64RegClass), Imm,
2683 MRI)) {
2684 if (DefSize < 64) {
2685 MIB.buildInstr(TargetOpcode::COPY, {DefReg}, {})
2686 .addReg(Mov->getOperand(0).getReg(), {},
2687 DefSize == 16 ? AArch64::hsub : AArch64::ssub);
2688 RBI.constrainGenericRegister(DefReg, FPRRC, MRI);
2689 }
2690 I.eraseFromParent();
2691 return true;
2692 }
2693
2694 // If TLI says that this fpimm is legal then prefer a copy from GPR movimm,
2695 // otherwise we'll expand to a constant pool load
2696 bool OptForSize = shouldOptForSize(&MF);
2697 const auto &TLI = MF.getSubtarget().getTargetLowering();
2698 if ((DefSize == 32 || DefSize == 64) &&
2699 TLI->isFPImmLegal(I.getOperand(1).getFPImm()->getValueAPF(),
2700 EVT::getFloatingPointVT(DefSize), OptForSize)) {
2701 // Emit a copy to emit a normal movimm.
2702 const Register DefGPRReg = MRI.createVirtualRegister(
2703 DefSize == 64 ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass);
2704 MachineOperand &RegOp = I.getOperand(0);
2705 RegOp.setReg(DefGPRReg);
2706 MIB.setInsertPt(MIB.getMBB(), std::next(I.getIterator()));
2707 MIB.buildCopy({DefReg}, {DefGPRReg});
2708
2709 if (!RBI.constrainGenericRegister(DefReg, FPRRC, MRI)) {
2710 LLVM_DEBUG(dbgs() << "Failed to constrain G_FCONSTANT def operand\n");
2711 return false;
2712 }
2713
2714 MachineOperand &ImmOp = I.getOperand(1);
2715 ImmOp.ChangeToImmediate(
2717
2718 const unsigned MovOpc =
2719 DefSize == 64 ? AArch64::MOVi64imm : AArch64::MOVi32imm;
2720 I.setDesc(TII.get(MovOpc));
2722 return true;
2723 }
2724
2725 // Expand to a constant pool.
2726 auto *LoadMI = emitLoadFromConstantPool(FPImm, MIB);
2727 if (!LoadMI) {
2728 LLVM_DEBUG(dbgs() << "Failed to load double constant pool entry\n");
2729 return false;
2730 }
2731 MIB.buildCopy({DefReg}, {LoadMI->getOperand(0).getReg()});
2732 I.eraseFromParent();
2733 return RBI.constrainGenericRegister(DefReg, FPRRC, MRI);
2734 }
2735 case TargetOpcode::G_EXTRACT: {
2736 Register DstReg = I.getOperand(0).getReg();
2737 Register SrcReg = I.getOperand(1).getReg();
2738 LLT SrcTy = MRI.getType(SrcReg);
2739 LLT DstTy = MRI.getType(DstReg);
2740 (void)DstTy;
2741 unsigned SrcSize = SrcTy.getSizeInBits();
2742
2743 if (SrcTy.getSizeInBits() > 64) {
2744 // This should be an extract of an s128, which is like a vector extract.
2745 if (SrcTy.getSizeInBits() != 128)
2746 return false;
2747 // Only support extracting 64 bits from an s128 at the moment.
2748 if (DstTy.getSizeInBits() != 64)
2749 return false;
2750
2751 unsigned Offset = I.getOperand(2).getImm();
2752 if (Offset % 64 != 0)
2753 return false;
2754
2755 // Check we have the right regbank always.
2756 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
2757 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
2758 assert(SrcRB.getID() == DstRB.getID() && "Wrong extract regbank!");
2759
2760 if (SrcRB.getID() == AArch64::GPRRegBankID) {
2761 auto NewI =
2762 MIB.buildInstr(TargetOpcode::COPY, {DstReg}, {})
2763 .addUse(SrcReg, {},
2764 Offset == 0 ? AArch64::sube64 : AArch64::subo64);
2765 constrainOperandRegClass(MF, TRI, MRI, TII, RBI, *NewI,
2766 AArch64::GPR64RegClass, NewI->getOperand(0));
2767 I.eraseFromParent();
2768 return true;
2769 }
2770
2771 // Emit the same code as a vector extract.
2772 // Offset must be a multiple of 64.
2773 unsigned LaneIdx = Offset / 64;
2774 MachineInstr *Extract = emitExtractVectorElt(
2775 DstReg, DstRB, LLT::scalar(64), SrcReg, LaneIdx, MIB);
2776 if (!Extract)
2777 return false;
2778 I.eraseFromParent();
2779 return true;
2780 }
2781
2782 I.setDesc(TII.get(SrcSize == 64 ? AArch64::UBFMXri : AArch64::UBFMWri));
2783 MachineInstrBuilder(MF, I).addImm(I.getOperand(2).getImm() +
2784 Ty.getSizeInBits() - 1);
2785
2786 if (SrcSize < 64) {
2787 assert(SrcSize == 32 && DstTy.getSizeInBits() == 16 &&
2788 "unexpected G_EXTRACT types");
2790 return true;
2791 }
2792
2794 MIB.setInsertPt(MIB.getMBB(), std::next(I.getIterator()));
2795 MIB.buildInstr(TargetOpcode::COPY, {I.getOperand(0).getReg()}, {})
2796 .addReg(DstReg, {}, AArch64::sub_32);
2797 RBI.constrainGenericRegister(I.getOperand(0).getReg(),
2798 AArch64::GPR32RegClass, MRI);
2799 I.getOperand(0).setReg(DstReg);
2800
2802 return true;
2803 }
2804
2805 case TargetOpcode::G_INSERT: {
2806 LLT SrcTy = MRI.getType(I.getOperand(2).getReg());
2807 LLT DstTy = MRI.getType(I.getOperand(0).getReg());
2808 unsigned DstSize = DstTy.getSizeInBits();
2809 // Larger inserts are vectors, same-size ones should be something else by
2810 // now (split up or turned into COPYs).
2811 if (Ty.getSizeInBits() > 64 || SrcTy.getSizeInBits() > 32)
2812 return false;
2813
2814 I.setDesc(TII.get(DstSize == 64 ? AArch64::BFMXri : AArch64::BFMWri));
2815 unsigned LSB = I.getOperand(3).getImm();
2816 unsigned Width = MRI.getType(I.getOperand(2).getReg()).getSizeInBits();
2817 I.getOperand(3).setImm((DstSize - LSB) % DstSize);
2818 MachineInstrBuilder(MF, I).addImm(Width - 1);
2819
2820 if (DstSize < 64) {
2821 assert(DstSize == 32 && SrcTy.getSizeInBits() == 16 &&
2822 "unexpected G_INSERT types");
2824 return true;
2825 }
2826
2828 BuildMI(MBB, I.getIterator(), I.getDebugLoc(),
2829 TII.get(AArch64::SUBREG_TO_REG))
2830 .addDef(SrcReg)
2831 .addUse(I.getOperand(2).getReg())
2832 .addImm(AArch64::sub_32);
2833 RBI.constrainGenericRegister(I.getOperand(2).getReg(),
2834 AArch64::GPR32RegClass, MRI);
2835 I.getOperand(2).setReg(SrcReg);
2836
2838 return true;
2839 }
2840 case TargetOpcode::G_FRAME_INDEX: {
2841 // allocas and G_FRAME_INDEX are only supported in addrspace(0).
2842 if (Ty != LLT::pointer(0, 64)) {
2843 LLVM_DEBUG(dbgs() << "G_FRAME_INDEX pointer has type: " << Ty
2844 << ", expected: " << LLT::pointer(0, 64) << '\n');
2845 return false;
2846 }
2847 I.setDesc(TII.get(AArch64::ADDXri));
2848
2849 // MOs for a #0 shifted immediate.
2850 I.addOperand(MachineOperand::CreateImm(0));
2851 I.addOperand(MachineOperand::CreateImm(0));
2852
2854 return true;
2855 }
2856
2857 case TargetOpcode::G_GLOBAL_VALUE: {
2858 const GlobalValue *GV = nullptr;
2859 unsigned OpFlags;
2860 if (I.getOperand(1).isSymbol()) {
2861 OpFlags = I.getOperand(1).getTargetFlags();
2862 // Currently only used by "RtLibUseGOT".
2863 assert(OpFlags == AArch64II::MO_GOT);
2864 } else {
2865 GV = I.getOperand(1).getGlobal();
2866 if (GV->isThreadLocal())
2867 return selectTLSGlobalValue(I, MRI);
2868
2869 OpFlags = STI.ClassifyGlobalReference(GV, TM);
2870 }
2871
2872 if (OpFlags & AArch64II::MO_GOT) {
2873 bool IsGOTSigned = MF.getInfo<AArch64FunctionInfo>()->hasELFSignedGOT();
2874 I.setDesc(TII.get(IsGOTSigned ? AArch64::LOADgotAUTH : AArch64::LOADgot));
2875 I.getOperand(1).setTargetFlags(OpFlags);
2876 I.addImplicitDefUseOperands(MF);
2877 I.setImplicitPhysRegDefsDead();
2878 } else if (TM.getCodeModel() == CodeModel::Large &&
2879 !TM.isPositionIndependent()) {
2880 // Materialize the global using movz/movk instructions.
2881 materializeLargeCMVal(I, GV, OpFlags);
2882 I.eraseFromParent();
2883 return true;
2884 } else if (TM.getCodeModel() == CodeModel::Tiny) {
2885 I.setDesc(TII.get(AArch64::ADR));
2886 I.getOperand(1).setTargetFlags(OpFlags);
2887 } else {
2888 I.setDesc(TII.get(AArch64::MOVaddr));
2889 I.getOperand(1).setTargetFlags(OpFlags | AArch64II::MO_PAGE);
2890 MachineInstrBuilder MIB(MF, I);
2891 MIB.addGlobalAddress(GV, I.getOperand(1).getOffset(),
2893 }
2895 return true;
2896 }
2897
2898 case TargetOpcode::G_PTRAUTH_GLOBAL_VALUE:
2899 return selectPtrAuthGlobalValue(I, MRI);
2900
2901 case TargetOpcode::G_ZEXTLOAD:
2902 case TargetOpcode::G_LOAD:
2903 case TargetOpcode::G_STORE: {
2904 GLoadStore &LdSt = cast<GLoadStore>(I);
2905 bool IsZExtLoad = I.getOpcode() == TargetOpcode::G_ZEXTLOAD;
2906 LLT PtrTy = MRI.getType(LdSt.getPointerReg());
2907
2908 // Can only handle AddressSpace 0, 64-bit pointers.
2909 if (PtrTy != LLT::pointer(0, 64)) {
2910 return false;
2911 }
2912
2913 uint64_t MemSizeInBytes = LdSt.getMemSize().getValue();
2914 unsigned MemSizeInBits = LdSt.getMemSizeInBits().getValue();
2915 AtomicOrdering Order = LdSt.getMMO().getSuccessOrdering();
2916
2917 // Need special instructions for atomics that affect ordering.
2918 if (isStrongerThanMonotonic(Order)) {
2919 assert(!isa<GZExtLoad>(LdSt));
2920 assert(MemSizeInBytes <= 8 &&
2921 "128-bit atomics should already be custom-legalized");
2922
2923 if (isa<GLoad>(LdSt)) {
2924 static constexpr unsigned LDAPROpcodes[] = {
2925 AArch64::LDAPRB, AArch64::LDAPRH, AArch64::LDAPRW, AArch64::LDAPRX};
2926 static constexpr unsigned LDAROpcodes[] = {
2927 AArch64::LDARB, AArch64::LDARH, AArch64::LDARW, AArch64::LDARX};
2928 ArrayRef<unsigned> Opcodes =
2929 STI.hasRCPC() && Order != AtomicOrdering::SequentiallyConsistent
2930 ? LDAPROpcodes
2931 : LDAROpcodes;
2932 I.setDesc(TII.get(Opcodes[Log2_32(MemSizeInBytes)]));
2933 } else {
2934 static constexpr unsigned Opcodes[] = {AArch64::STLRB, AArch64::STLRH,
2935 AArch64::STLRW, AArch64::STLRX};
2936 Register ValReg = LdSt.getReg(0);
2937 if (MRI.getType(ValReg).getSizeInBits() == 64 && MemSizeInBits != 64) {
2938 // Emit a subreg copy of 32 bits.
2939 Register NewVal = MRI.createVirtualRegister(&AArch64::GPR32RegClass);
2940 MIB.buildInstr(TargetOpcode::COPY, {NewVal}, {})
2941 .addReg(I.getOperand(0).getReg(), {}, AArch64::sub_32);
2942 I.getOperand(0).setReg(NewVal);
2943 }
2944 I.setDesc(TII.get(Opcodes[Log2_32(MemSizeInBytes)]));
2945 }
2947 return true;
2948 }
2949
2950#ifndef NDEBUG
2951 const Register PtrReg = LdSt.getPointerReg();
2952 const RegisterBank &PtrRB = *RBI.getRegBank(PtrReg, MRI, TRI);
2953 // Check that the pointer register is valid.
2954 assert(PtrRB.getID() == AArch64::GPRRegBankID &&
2955 "Load/Store pointer operand isn't a GPR");
2956 assert(MRI.getType(PtrReg).isPointer() &&
2957 "Load/Store pointer operand isn't a pointer");
2958#endif
2959
2960 const Register ValReg = LdSt.getReg(0);
2961 const RegisterBank &RB = *RBI.getRegBank(ValReg, MRI, TRI);
2962 LLT ValTy = MRI.getType(ValReg);
2963
2964 // The code below doesn't support truncating stores, so we need to split it
2965 // again.
2966 if (isa<GStore>(LdSt) && ValTy.getSizeInBits() > MemSizeInBits &&
2967 RB.getID() == AArch64::FPRRegBankID) {
2968 unsigned SubReg;
2969 LLT MemTy = LdSt.getMMO().getMemoryType();
2970 auto *RC = getRegClassForTypeOnBank(MemTy, RB);
2971 if (!getSubRegForClass(RC, TRI, SubReg))
2972 return false;
2973
2974 // Generate a subreg copy.
2975 auto Copy = MIB.buildInstr(TargetOpcode::COPY, {MemTy}, {})
2976 .addReg(ValReg, {}, SubReg)
2977 .getReg(0);
2978 RBI.constrainGenericRegister(Copy, *RC, MRI);
2979 LdSt.getOperand(0).setReg(Copy);
2980 } else if (isa<GLoad>(LdSt) && ValTy.getSizeInBits() > MemSizeInBits) {
2981 // If this is an any-extending load from the FPR bank, split it into a regular
2982 // load + extend.
2983 if (RB.getID() == AArch64::FPRRegBankID) {
2984 unsigned SubReg;
2985 LLT MemTy = LdSt.getMMO().getMemoryType();
2986 auto *RC = getRegClassForTypeOnBank(MemTy, RB);
2987 if (!getSubRegForClass(RC, TRI, SubReg))
2988 return false;
2989 Register OldDst = LdSt.getReg(0);
2990 Register NewDst =
2992 LdSt.getOperand(0).setReg(NewDst);
2993 MRI.setRegBank(NewDst, RB);
2994 // Generate a SUBREG_TO_REG to extend it.
2995 MIB.setInsertPt(MIB.getMBB(), std::next(LdSt.getIterator()));
2996 MIB.buildInstr(AArch64::SUBREG_TO_REG, {OldDst}, {})
2997 .addUse(NewDst)
2998 .addImm(SubReg);
2999 auto SubRegRC = getRegClassForTypeOnBank(MRI.getType(OldDst), RB);
3000 RBI.constrainGenericRegister(OldDst, *SubRegRC, MRI);
3001 MIB.setInstr(LdSt);
3002 ValTy = MemTy; // This is no longer an extending load.
3003 }
3004 }
3005
3006 // Helper lambda for partially selecting I. Either returns the original
3007 // instruction with an updated opcode, or a new instruction.
3008 auto SelectLoadStoreAddressingMode = [&]() -> MachineInstr * {
3009 bool IsStore = isa<GStore>(I);
3010 const unsigned NewOpc =
3011 selectLoadStoreUIOp(I.getOpcode(), RB.getID(), MemSizeInBits);
3012 if (NewOpc == I.getOpcode())
3013 return nullptr;
3014 // Check if we can fold anything into the addressing mode.
3015 auto AddrModeFns =
3016 selectAddrModeIndexed(I.getOperand(1), MemSizeInBytes);
3017 if (!AddrModeFns) {
3018 // Can't fold anything. Use the original instruction.
3019 I.setDesc(TII.get(NewOpc));
3020 I.addOperand(MachineOperand::CreateImm(0));
3021 return &I;
3022 }
3023
3024 // Folded something. Create a new instruction and return it.
3025 auto NewInst = MIB.buildInstr(NewOpc, {}, {}, I.getFlags());
3026 Register CurValReg = I.getOperand(0).getReg();
3027 IsStore ? NewInst.addUse(CurValReg) : NewInst.addDef(CurValReg);
3028 NewInst.cloneMemRefs(I);
3029 for (auto &Fn : *AddrModeFns)
3030 Fn(NewInst);
3031 I.eraseFromParent();
3032 return &*NewInst;
3033 };
3034
3035 MachineInstr *LoadStore = SelectLoadStoreAddressingMode();
3036 if (!LoadStore)
3037 return false;
3038
3039 // If we're storing a 0, use WZR/XZR.
3040 if (Opcode == TargetOpcode::G_STORE) {
3042 LoadStore->getOperand(0).getReg(), MRI);
3043 if (CVal && CVal->Value == 0) {
3044 switch (LoadStore->getOpcode()) {
3045 case AArch64::STRWui:
3046 case AArch64::STRHHui:
3047 case AArch64::STRBBui:
3048 LoadStore->getOperand(0).setReg(AArch64::WZR);
3049 break;
3050 case AArch64::STRXui:
3051 LoadStore->getOperand(0).setReg(AArch64::XZR);
3052 break;
3053 }
3054 }
3055 }
3056
3057 if (IsZExtLoad || (Opcode == TargetOpcode::G_LOAD &&
3058 ValTy == LLT::scalar(64) && MemSizeInBits == 32)) {
3059 // The any/zextload from a smaller type to i32 should be handled by the
3060 // importer.
3061 if (MRI.getType(LoadStore->getOperand(0).getReg()).getSizeInBits() != 64)
3062 return false;
3063 // If we have an extending load then change the load's type to be a
3064 // narrower reg and zero_extend with SUBREG_TO_REG.
3065 Register LdReg = MRI.createVirtualRegister(&AArch64::GPR32RegClass);
3066 Register DstReg = LoadStore->getOperand(0).getReg();
3067 LoadStore->getOperand(0).setReg(LdReg);
3068
3069 MIB.setInsertPt(MIB.getMBB(), std::next(LoadStore->getIterator()));
3070 MIB.buildInstr(AArch64::SUBREG_TO_REG, {DstReg}, {})
3071 .addUse(LdReg)
3072 .addImm(AArch64::sub_32);
3073 constrainSelectedInstRegOperands(*LoadStore, TII, TRI, RBI);
3074 return RBI.constrainGenericRegister(DstReg, AArch64::GPR64allRegClass,
3075 MRI);
3076 }
3077 constrainSelectedInstRegOperands(*LoadStore, TII, TRI, RBI);
3078 return true;
3079 }
3080
3081 case TargetOpcode::G_INDEXED_ZEXTLOAD:
3082 case TargetOpcode::G_INDEXED_SEXTLOAD:
3083 return selectIndexedExtLoad(I, MRI);
3084 case TargetOpcode::G_INDEXED_LOAD:
3085 return selectIndexedLoad(I, MRI);
3086 case TargetOpcode::G_INDEXED_STORE:
3087 return selectIndexedStore(cast<GIndexedStore>(I), MRI);
3088
3089 case TargetOpcode::G_LSHR:
3090 case TargetOpcode::G_ASHR:
3091 if (MRI.getType(I.getOperand(0).getReg()).isVector())
3092 return selectVectorAshrLshr(I, MRI);
3093 [[fallthrough]];
3094 case TargetOpcode::G_SHL: {
3095 if (Opcode == TargetOpcode::G_SHL &&
3096 MRI.getType(I.getOperand(0).getReg()).isVector())
3097 return selectVectorSHL(I, MRI);
3098
3099 // These shifts were legalized to have 64 bit shift amounts because we
3100 // want to take advantage of the selection patterns that assume the
3101 // immediates are s64s, however, selectBinaryOp will assume both operands
3102 // will have the same bit size.
3103 {
3104 Register SrcReg = I.getOperand(1).getReg();
3105 Register ShiftReg = I.getOperand(2).getReg();
3106 const LLT ShiftTy = MRI.getType(ShiftReg);
3107 const LLT SrcTy = MRI.getType(SrcReg);
3108 if (!SrcTy.isVector() && SrcTy.getSizeInBits() == 32 &&
3109 ShiftTy.getSizeInBits() == 64) {
3110 assert(!ShiftTy.isVector() && "unexpected vector shift ty");
3111 // Insert a subregister copy to implement a 64->32 trunc
3112 auto Trunc = MIB.buildInstr(TargetOpcode::COPY, {SrcTy}, {})
3113 .addReg(ShiftReg, {}, AArch64::sub_32);
3114 MRI.setRegBank(Trunc.getReg(0), RBI.getRegBank(AArch64::GPRRegBankID));
3115 I.getOperand(2).setReg(Trunc.getReg(0));
3116 }
3117 }
3118
3119 const unsigned OpSize = Ty.getSizeInBits();
3120 const Register DefReg = I.getOperand(0).getReg();
3121 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
3122
3123 const unsigned NewOpc = selectBinaryOp(I.getOpcode(), RB.getID(), OpSize);
3124 if (NewOpc == I.getOpcode())
3125 return false;
3126
3127 I.setDesc(TII.get(NewOpc));
3128 // FIXME: Should the type be always reset in setDesc?
3129
3130 // Now that we selected an opcode, we need to constrain the register
3131 // operands to use appropriate classes.
3133 return true;
3134 }
3135 case TargetOpcode::G_PTR_ADD: {
3136 emitADD(I.getOperand(0).getReg(), I.getOperand(1), I.getOperand(2), MIB);
3137 I.eraseFromParent();
3138 return true;
3139 }
3140
3141 case TargetOpcode::G_SADDE:
3142 case TargetOpcode::G_UADDE:
3143 case TargetOpcode::G_SSUBE:
3144 case TargetOpcode::G_USUBE:
3145 case TargetOpcode::G_SADDO:
3146 case TargetOpcode::G_UADDO:
3147 case TargetOpcode::G_SSUBO:
3148 case TargetOpcode::G_USUBO:
3149 return selectOverflowOp(I, MRI);
3150
3151 case TargetOpcode::G_PTRMASK: {
3152 Register MaskReg = I.getOperand(2).getReg();
3153 std::optional<int64_t> MaskVal = getIConstantVRegSExtVal(MaskReg, MRI);
3154 // TODO: Implement arbitrary cases
3155 if (!MaskVal || !isShiftedMask_64(*MaskVal))
3156 return false;
3157
3158 uint64_t Mask = *MaskVal;
3159 I.setDesc(TII.get(AArch64::ANDXri));
3160 I.getOperand(2).ChangeToImmediate(
3162
3164 return true;
3165 }
3166 case TargetOpcode::G_PTRTOINT:
3167 case TargetOpcode::G_TRUNC: {
3168 const LLT DstTy = MRI.getType(I.getOperand(0).getReg());
3169 const LLT SrcTy = MRI.getType(I.getOperand(1).getReg());
3170
3171 const Register DstReg = I.getOperand(0).getReg();
3172 const Register SrcReg = I.getOperand(1).getReg();
3173
3174 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
3175 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
3176
3177 if (DstRB.getID() != SrcRB.getID()) {
3178 LLVM_DEBUG(
3179 dbgs() << "G_TRUNC/G_PTRTOINT input/output on different banks\n");
3180 return false;
3181 }
3182
3183 if (DstRB.getID() == AArch64::GPRRegBankID) {
3184 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(DstTy, DstRB);
3185 if (!DstRC)
3186 return false;
3187
3188 const TargetRegisterClass *SrcRC = getRegClassForTypeOnBank(SrcTy, SrcRB);
3189 if (!SrcRC)
3190 return false;
3191
3192 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
3193 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
3194 LLVM_DEBUG(dbgs() << "Failed to constrain G_TRUNC/G_PTRTOINT\n");
3195 return false;
3196 }
3197
3198 if (DstRC == SrcRC) {
3199 // Nothing to be done
3200 } else if (Opcode == TargetOpcode::G_TRUNC && DstTy == LLT::scalar(32) &&
3201 SrcTy == LLT::scalar(64)) {
3202 llvm_unreachable("TableGen can import this case");
3203 return false;
3204 } else if (DstRC == &AArch64::GPR32RegClass &&
3205 SrcRC == &AArch64::GPR64RegClass) {
3206 I.getOperand(1).setSubReg(AArch64::sub_32);
3207 } else {
3208 LLVM_DEBUG(
3209 dbgs() << "Unhandled mismatched classes in G_TRUNC/G_PTRTOINT\n");
3210 return false;
3211 }
3212
3213 I.setDesc(TII.get(TargetOpcode::COPY));
3214 return true;
3215 } else if (DstRB.getID() == AArch64::FPRRegBankID) {
3216 if (DstTy == LLT::fixed_vector(4, 16) &&
3217 SrcTy == LLT::fixed_vector(4, 32)) {
3218 I.setDesc(TII.get(AArch64::XTNv4i16));
3220 return true;
3221 }
3222
3223 if (!SrcTy.isVector() && SrcTy.getSizeInBits() == 128) {
3224 MachineInstr *Extract = emitExtractVectorElt(
3225 DstReg, DstRB, LLT::scalar(DstTy.getSizeInBits()), SrcReg, 0, MIB);
3226 if (!Extract)
3227 return false;
3228 I.eraseFromParent();
3229 return true;
3230 }
3231
3232 // We might have a vector G_PTRTOINT, in which case just emit a COPY.
3233 if (Opcode == TargetOpcode::G_PTRTOINT) {
3234 assert(DstTy.isVector() && "Expected an FPR ptrtoint to be a vector");
3235 I.setDesc(TII.get(TargetOpcode::COPY));
3236 return selectCopy(I, TII, MRI, TRI, RBI);
3237 }
3238 }
3239
3240 return false;
3241 }
3242
3243 case TargetOpcode::G_ANYEXT: {
3244 if (selectUSMovFromExtend(I, MRI))
3245 return true;
3246
3247 const Register DstReg = I.getOperand(0).getReg();
3248 const Register SrcReg = I.getOperand(1).getReg();
3249
3250 const RegisterBank &RBDst = *RBI.getRegBank(DstReg, MRI, TRI);
3251 if (RBDst.getID() != AArch64::GPRRegBankID) {
3252 LLVM_DEBUG(dbgs() << "G_ANYEXT on bank: " << RBDst
3253 << ", expected: GPR\n");
3254 return false;
3255 }
3256
3257 const RegisterBank &RBSrc = *RBI.getRegBank(SrcReg, MRI, TRI);
3258 if (RBSrc.getID() != AArch64::GPRRegBankID) {
3259 LLVM_DEBUG(dbgs() << "G_ANYEXT on bank: " << RBSrc
3260 << ", expected: GPR\n");
3261 return false;
3262 }
3263
3264 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
3265
3266 if (DstSize == 0) {
3267 LLVM_DEBUG(dbgs() << "G_ANYEXT operand has no size, not a gvreg?\n");
3268 return false;
3269 }
3270
3271 if (DstSize != 64 && DstSize > 32) {
3272 LLVM_DEBUG(dbgs() << "G_ANYEXT to size: " << DstSize
3273 << ", expected: 32 or 64\n");
3274 return false;
3275 }
3276 // At this point G_ANYEXT is just like a plain COPY, but we need
3277 // to explicitly form the 64-bit value if any.
3278 if (DstSize > 32) {
3279 Register ExtSrc = MRI.createVirtualRegister(&AArch64::GPR64allRegClass);
3280 BuildMI(MBB, I, I.getDebugLoc(), TII.get(AArch64::SUBREG_TO_REG))
3281 .addDef(ExtSrc)
3282 .addUse(SrcReg)
3283 .addImm(AArch64::sub_32);
3284 I.getOperand(1).setReg(ExtSrc);
3285 }
3286 return selectCopy(I, TII, MRI, TRI, RBI);
3287 }
3288
3289 case TargetOpcode::G_ZEXT:
3290 case TargetOpcode::G_SEXT_INREG:
3291 case TargetOpcode::G_SEXT: {
3292 if (selectUSMovFromExtend(I, MRI))
3293 return true;
3294
3295 unsigned Opcode = I.getOpcode();
3296 const bool IsSigned = Opcode != TargetOpcode::G_ZEXT;
3297 const Register DefReg = I.getOperand(0).getReg();
3298 Register SrcReg = I.getOperand(1).getReg();
3299 const LLT DstTy = MRI.getType(DefReg);
3300 const LLT SrcTy = MRI.getType(SrcReg);
3301 unsigned DstSize = DstTy.getSizeInBits();
3302 unsigned SrcSize = SrcTy.getSizeInBits();
3303
3304 // SEXT_INREG has the same src reg size as dst, the size of the value to be
3305 // extended is encoded in the imm.
3306 if (Opcode == TargetOpcode::G_SEXT_INREG)
3307 SrcSize = I.getOperand(2).getImm();
3308
3309 if (DstTy.isVector())
3310 return false; // Should be handled by imported patterns.
3311
3312 assert((*RBI.getRegBank(DefReg, MRI, TRI)).getID() ==
3313 AArch64::GPRRegBankID &&
3314 "Unexpected ext regbank");
3315
3316 MachineInstr *ExtI;
3317
3318 // First check if we're extending the result of a load which has a dest type
3319 // smaller than 32 bits, then this zext is redundant. GPR32 is the smallest
3320 // GPR register on AArch64 and all loads which are smaller automatically
3321 // zero-extend the upper bits. E.g.
3322 // %v(s8) = G_LOAD %p, :: (load 1)
3323 // %v2(s32) = G_ZEXT %v(s8)
3324 if (!IsSigned) {
3325 auto *LoadMI = getOpcodeDef(TargetOpcode::G_LOAD, SrcReg, MRI);
3326 bool IsGPR =
3327 RBI.getRegBank(SrcReg, MRI, TRI)->getID() == AArch64::GPRRegBankID;
3328 if (LoadMI && IsGPR) {
3329 const MachineMemOperand *MemOp = *LoadMI->memoperands_begin();
3330 unsigned BytesLoaded = MemOp->getSize().getValue();
3331 if (BytesLoaded < 4 && SrcTy.getSizeInBytes() == BytesLoaded)
3332 return selectCopy(I, TII, MRI, TRI, RBI);
3333 }
3334
3335 // For the 32-bit -> 64-bit case, we can emit a mov (ORRWrs)
3336 // + SUBREG_TO_REG.
3337 if (IsGPR && SrcSize == 32 && DstSize == 64) {
3338 Register SubregToRegSrc =
3339 MRI.createVirtualRegister(&AArch64::GPR32RegClass);
3340 const Register ZReg = AArch64::WZR;
3341 MIB.buildInstr(AArch64::ORRWrs, {SubregToRegSrc}, {ZReg, SrcReg})
3342 .addImm(0);
3343
3344 MIB.buildInstr(AArch64::SUBREG_TO_REG, {DefReg}, {})
3345 .addUse(SubregToRegSrc)
3346 .addImm(AArch64::sub_32);
3347
3348 if (!RBI.constrainGenericRegister(DefReg, AArch64::GPR64RegClass,
3349 MRI)) {
3350 LLVM_DEBUG(dbgs() << "Failed to constrain G_ZEXT destination\n");
3351 return false;
3352 }
3353
3354 if (!RBI.constrainGenericRegister(SrcReg, AArch64::GPR32RegClass,
3355 MRI)) {
3356 LLVM_DEBUG(dbgs() << "Failed to constrain G_ZEXT source\n");
3357 return false;
3358 }
3359
3360 I.eraseFromParent();
3361 return true;
3362 }
3363 }
3364
3365 if (DstSize == 64) {
3366 if (Opcode != TargetOpcode::G_SEXT_INREG) {
3367 // FIXME: Can we avoid manually doing this?
3368 if (!RBI.constrainGenericRegister(SrcReg, AArch64::GPR32RegClass,
3369 MRI)) {
3370 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(Opcode)
3371 << " operand\n");
3372 return false;
3373 }
3374 SrcReg = MIB.buildInstr(AArch64::SUBREG_TO_REG,
3375 {&AArch64::GPR64RegClass}, {})
3376 .addUse(SrcReg)
3377 .addImm(AArch64::sub_32)
3378 .getReg(0);
3379 }
3380
3381 ExtI = MIB.buildInstr(IsSigned ? AArch64::SBFMXri : AArch64::UBFMXri,
3382 {DefReg}, {SrcReg})
3383 .addImm(0)
3384 .addImm(SrcSize - 1);
3385 } else if (DstSize <= 32) {
3386 ExtI = MIB.buildInstr(IsSigned ? AArch64::SBFMWri : AArch64::UBFMWri,
3387 {DefReg}, {SrcReg})
3388 .addImm(0)
3389 .addImm(SrcSize - 1);
3390 } else {
3391 return false;
3392 }
3393
3395 I.eraseFromParent();
3396 return true;
3397 }
3398
3399 case TargetOpcode::G_FREEZE:
3400 return selectCopy(I, TII, MRI, TRI, RBI);
3401
3402 case TargetOpcode::G_INTTOPTR:
3403 // The importer is currently unable to import pointer types since they
3404 // didn't exist in SelectionDAG.
3405 return selectCopy(I, TII, MRI, TRI, RBI);
3406
3407 case TargetOpcode::G_BITCAST:
3408 // Imported SelectionDAG rules can handle every bitcast except those that
3409 // bitcast from a type to the same type. Ideally, these shouldn't occur
3410 // but we might not run an optimizer that deletes them. The other exception
3411 // is bitcasts involving pointer types, as SelectionDAG has no knowledge
3412 // of them.
3413 return selectCopy(I, TII, MRI, TRI, RBI);
3414
3415 case TargetOpcode::G_SELECT: {
3416 auto &Sel = cast<GSelect>(I);
3417 const Register CondReg = Sel.getCondReg();
3418 const Register TReg = Sel.getTrueReg();
3419 const Register FReg = Sel.getFalseReg();
3420
3421 if (tryOptSelect(Sel))
3422 return true;
3423
3424 // Make sure to use an unused vreg instead of wzr, so that the peephole
3425 // optimizations will be able to optimize these.
3426 Register DeadVReg = MRI.createVirtualRegister(&AArch64::GPR32RegClass);
3427 auto TstMI = MIB.buildInstr(AArch64::ANDSWri, {DeadVReg}, {CondReg})
3428 .addImm(AArch64_AM::encodeLogicalImmediate(1, 32));
3430 if (!emitSelect(Sel.getReg(0), TReg, FReg, AArch64CC::NE, MIB))
3431 return false;
3432 Sel.eraseFromParent();
3433 return true;
3434 }
3435 case TargetOpcode::G_ICMP: {
3436 if (Ty.isVector())
3437 return false;
3438
3439 if (Ty != LLT::scalar(32)) {
3440 LLVM_DEBUG(dbgs() << "G_ICMP result has type: " << Ty
3441 << ", expected: " << LLT::scalar(32) << '\n');
3442 return false;
3443 }
3444
3445 auto &PredOp = I.getOperand(1);
3446 emitIntegerCompare(I.getOperand(2), I.getOperand(3), PredOp, MIB);
3447 auto Pred = static_cast<CmpInst::Predicate>(PredOp.getPredicate());
3449 CmpInst::getInversePredicate(Pred), I.getOperand(3).getReg(), &MRI);
3450 emitCSINC(/*Dst=*/I.getOperand(0).getReg(), /*Src1=*/AArch64::WZR,
3451 /*Src2=*/AArch64::WZR, InvCC, MIB);
3452 I.eraseFromParent();
3453 return true;
3454 }
3455
3456 case TargetOpcode::G_FCMP: {
3457 CmpInst::Predicate Pred =
3458 static_cast<CmpInst::Predicate>(I.getOperand(1).getPredicate());
3459 if (!emitFPCompare(I.getOperand(2).getReg(), I.getOperand(3).getReg(), MIB,
3460 Pred) ||
3461 !emitCSetForFCmp(I.getOperand(0).getReg(), Pred, MIB))
3462 return false;
3463 I.eraseFromParent();
3464 return true;
3465 }
3466 case TargetOpcode::G_VASTART:
3467 return STI.isTargetDarwin() ? selectVaStartDarwin(I, MF, MRI)
3468 : selectVaStartAAPCS(I, MF, MRI);
3469 case TargetOpcode::G_INTRINSIC:
3470 return selectIntrinsic(I, MRI);
3471 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
3472 return selectIntrinsicWithSideEffects(I, MRI);
3473 case TargetOpcode::G_IMPLICIT_DEF: {
3474 I.setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
3475 const LLT DstTy = MRI.getType(I.getOperand(0).getReg());
3476 const Register DstReg = I.getOperand(0).getReg();
3477 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
3478 const TargetRegisterClass *DstRC = getRegClassForTypeOnBank(DstTy, DstRB);
3479 RBI.constrainGenericRegister(DstReg, *DstRC, MRI);
3480 return true;
3481 }
3482 case TargetOpcode::G_BLOCK_ADDR: {
3483 Function *BAFn = I.getOperand(1).getBlockAddress()->getFunction();
3484 if (std::optional<uint16_t> BADisc =
3486 MIB.buildInstr(AArch64::MOVaddrPAC)
3487 .addBlockAddress(I.getOperand(1).getBlockAddress())
3489 .addReg(/*AddrDisc=*/AArch64::XZR)
3490 .addImm(*BADisc)
3491 .constrainAllUses(TII, TRI, RBI);
3492 MIB.buildCopy(I.getOperand(0).getReg(), Register(AArch64::X16));
3493 RBI.constrainGenericRegister(I.getOperand(0).getReg(),
3494 AArch64::GPR64RegClass, MRI);
3495 I.eraseFromParent();
3496 return true;
3497 }
3499 materializeLargeCMVal(I, I.getOperand(1).getBlockAddress(), 0);
3500 I.eraseFromParent();
3501 return true;
3502 } else {
3503 I.setDesc(TII.get(AArch64::MOVaddrBA));
3504 auto MovMI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(AArch64::MOVaddrBA),
3505 I.getOperand(0).getReg())
3506 .addBlockAddress(I.getOperand(1).getBlockAddress(),
3507 /* Offset */ 0, AArch64II::MO_PAGE)
3509 I.getOperand(1).getBlockAddress(), /* Offset */ 0,
3511 I.eraseFromParent();
3513 return true;
3514 }
3515 }
3516 case TargetOpcode::G_BUILD_VECTOR:
3517 return selectBuildVector(I, MRI);
3518 case TargetOpcode::G_MERGE_VALUES:
3519 return selectMergeValues(I, MRI);
3520 case TargetOpcode::G_UNMERGE_VALUES:
3521 return selectUnmergeValues(I, MRI);
3522 case TargetOpcode::G_SHUFFLE_VECTOR:
3523 return selectShuffleVector(I, MRI);
3524 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
3525 return selectExtractElt(I, MRI);
3526 case TargetOpcode::G_CONCAT_VECTORS:
3527 return selectConcatVectors(I, MRI);
3528 case TargetOpcode::G_JUMP_TABLE:
3529 return selectJumpTable(I, MRI);
3530 case TargetOpcode::G_MEMCPY:
3531 case TargetOpcode::G_MEMCPY_INLINE:
3532 case TargetOpcode::G_MEMMOVE:
3533 case TargetOpcode::G_MEMSET:
3534 case TargetOpcode::G_MEMSET_INLINE:
3535 assert(STI.hasMOPS() && "Shouldn't get here without +mops feature");
3536 return selectMOPS(I, MRI);
3537 }
3538
3539 return false;
3540}
3541
3542bool AArch64InstructionSelector::selectAndRestoreState(MachineInstr &I) {
3543 MachineIRBuilderState OldMIBState = MIB.getState();
3544 bool Success = select(I);
3545 MIB.setState(OldMIBState);
3546 return Success;
3547}
3548
3549bool AArch64InstructionSelector::selectMOPS(MachineInstr &GI,
3550 MachineRegisterInfo &MRI) {
3551 unsigned Mopcode;
3552 switch (GI.getOpcode()) {
3553 case TargetOpcode::G_MEMCPY:
3554 case TargetOpcode::G_MEMCPY_INLINE:
3555 Mopcode = AArch64::MOPSMemoryCopyPseudo;
3556 break;
3557 case TargetOpcode::G_MEMMOVE:
3558 Mopcode = AArch64::MOPSMemoryMovePseudo;
3559 break;
3560 case TargetOpcode::G_MEMSET:
3561 case TargetOpcode::G_MEMSET_INLINE:
3562 // For tagged memset see llvm.aarch64.mops.memset.tag
3563 Mopcode = AArch64::MOPSMemorySetPseudo;
3564 break;
3565 }
3566
3567 auto &DstPtr = GI.getOperand(0);
3568 auto &SrcOrVal = GI.getOperand(1);
3569 auto &Size = GI.getOperand(2);
3570
3571 // Create copies of the registers that can be clobbered.
3572 const Register DstPtrCopy = MRI.cloneVirtualRegister(DstPtr.getReg());
3573 const Register SrcValCopy = MRI.cloneVirtualRegister(SrcOrVal.getReg());
3574 const Register SizeCopy = MRI.cloneVirtualRegister(Size.getReg());
3575
3576 const bool IsSet = Mopcode == AArch64::MOPSMemorySetPseudo;
3577 const auto &SrcValRegClass =
3578 IsSet ? AArch64::GPR64RegClass : AArch64::GPR64commonRegClass;
3579
3580 // Constrain to specific registers
3581 RBI.constrainGenericRegister(DstPtrCopy, AArch64::GPR64commonRegClass, MRI);
3582 RBI.constrainGenericRegister(SrcValCopy, SrcValRegClass, MRI);
3583 RBI.constrainGenericRegister(SizeCopy, AArch64::GPR64RegClass, MRI);
3584
3585 MIB.buildCopy(DstPtrCopy, DstPtr);
3586 MIB.buildCopy(SrcValCopy, SrcOrVal);
3587 MIB.buildCopy(SizeCopy, Size);
3588
3589 // New instruction uses the copied registers because it must update them.
3590 // The defs are not used since they don't exist in G_MEM*. They are still
3591 // tied.
3592 // Note: order of operands is different from G_MEMSET, G_MEMCPY, G_MEMMOVE
3593 Register DefDstPtr = MRI.createVirtualRegister(&AArch64::GPR64commonRegClass);
3594 Register DefSize = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3595 if (IsSet) {
3596 MIB.buildInstr(Mopcode, {DefDstPtr, DefSize},
3597 {DstPtrCopy, SizeCopy, SrcValCopy})
3598 .setOperandDead(5); // implicit-def $nzcv
3599 } else {
3600 Register DefSrcPtr = MRI.createVirtualRegister(&SrcValRegClass);
3601 MIB.buildInstr(Mopcode, {DefDstPtr, DefSrcPtr, DefSize},
3602 {DstPtrCopy, SrcValCopy, SizeCopy})
3603 .setOperandDead(6); // implicit-def $nzcv
3604 }
3605
3606 GI.eraseFromParent();
3607 return true;
3608}
3609
3610bool AArch64InstructionSelector::selectBrJT(MachineInstr &I,
3611 MachineRegisterInfo &MRI) {
3612 assert(I.getOpcode() == TargetOpcode::G_BRJT && "Expected G_BRJT");
3613 Register JTAddr = I.getOperand(0).getReg();
3614 unsigned JTI = I.getOperand(1).getIndex();
3615 Register Index = I.getOperand(2).getReg();
3616
3617 MF->getInfo<AArch64FunctionInfo>()->setJumpTableEntryInfo(JTI, 4, nullptr);
3618
3619 // With aarch64-jump-table-hardening, we only expand the jump table dispatch
3620 // sequence later, to guarantee the integrity of the intermediate values.
3621 if (MF->getFunction().hasFnAttribute("aarch64-jump-table-hardening")) {
3623 if (STI.isTargetMachO()) {
3624 if (CM != CodeModel::Small && CM != CodeModel::Large)
3625 report_fatal_error("Unsupported code-model for hardened jump-table");
3626 } else {
3627 // Note that COFF support would likely also need JUMP_TABLE_DEBUG_INFO.
3628 assert(STI.isTargetELF() &&
3629 "jump table hardening only supported on MachO/ELF");
3630 if (CM != CodeModel::Small)
3631 report_fatal_error("Unsupported code-model for hardened jump-table");
3632 }
3633
3634 MIB.buildCopy({AArch64::X16}, I.getOperand(2).getReg());
3635 MIB.buildInstr(AArch64::BR_JumpTable)
3636 .addJumpTableIndex(I.getOperand(1).getIndex());
3637 I.eraseFromParent();
3638 return true;
3639 }
3640
3641 Register TargetReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3642 Register ScratchReg = MRI.createVirtualRegister(&AArch64::GPR64spRegClass);
3643
3644 auto JumpTableInst = MIB.buildInstr(AArch64::JumpTableDest32,
3645 {TargetReg, ScratchReg}, {JTAddr, Index})
3646 .addJumpTableIndex(JTI);
3647 // Save the jump table info.
3648 MIB.buildInstr(TargetOpcode::JUMP_TABLE_DEBUG_INFO, {},
3649 {static_cast<int64_t>(JTI)});
3650 // Build the indirect branch.
3651 MIB.buildInstr(AArch64::BR, {}, {TargetReg});
3652 I.eraseFromParent();
3653 constrainSelectedInstRegOperands(*JumpTableInst, TII, TRI, RBI);
3654 return true;
3655}
3656
3657bool AArch64InstructionSelector::selectJumpTable(MachineInstr &I,
3658 MachineRegisterInfo &MRI) {
3659 assert(I.getOpcode() == TargetOpcode::G_JUMP_TABLE && "Expected jump table");
3660 assert(I.getOperand(1).isJTI() && "Jump table op should have a JTI!");
3661
3662 Register DstReg = I.getOperand(0).getReg();
3663 unsigned JTI = I.getOperand(1).getIndex();
3664 // We generate a MOVaddrJT which will get expanded to an ADRP + ADD later.
3665 auto MovMI =
3666 MIB.buildInstr(AArch64::MOVaddrJT, {DstReg}, {})
3667 .addJumpTableIndex(JTI, AArch64II::MO_PAGE)
3669 I.eraseFromParent();
3671 return true;
3672}
3673
3674bool AArch64InstructionSelector::selectTLSLocalExecELF(
3675 const GlobalValue *GV, MachineInstr &I, MachineRegisterInfo &MRI) {
3676 auto ConstrainRegOps = [&](MachineInstrBuilder MIB) {
3678 };
3680 ConstrainRegOps(MIB.buildInstr(AArch64::MOVbaseTLS, {ThreadBase}, {}));
3681
3682 switch (MF->getTarget().Options.TLSSize) {
3683 default:
3684 llvm_unreachable("Unexpected TLS size");
3685 case 12: {
3686 // add x0, x0, :tprel_lo12:a
3687 ConstrainRegOps(
3688 MIB.buildInstr(AArch64::ADDXri, {I.getOperand(0).getReg()},
3689 {ThreadBase})
3691 .addImm(0));
3692 break;
3693 }
3694 case 24: {
3695 // add x0, x0, :tprel_hi12:a
3696 // add x0, x0, :tprel_lo12_nc:a
3697 Register Addr = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3698 ConstrainRegOps(
3699 MIB.buildInstr(AArch64::ADDXri, {Addr}, {ThreadBase})
3701 .addImm(0));
3702 ConstrainRegOps(
3703 MIB.buildInstr(AArch64::ADDXri, {I.getOperand(0).getReg()}, {Addr})
3704 .addGlobalAddress(GV, 0,
3707 .addImm(0));
3708 break;
3709 }
3710 case 32: {
3711 // movz x0, #:tprel_g1:a
3712 // movk x0, #:tprel_g0_nc:a
3713 // add x0, x1, x0
3714 Register Addr = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3715 ConstrainRegOps(
3716 MIB.buildInstr(AArch64::MOVZXi, {Addr}, {})
3718 .addImm(16));
3719 Register Addr2 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3720 ConstrainRegOps(MIB.buildInstr(AArch64::MOVKXi, {Addr2}, {Addr})
3721 .addGlobalAddress(GV, 0,
3724 .addImm(0));
3725 ConstrainRegOps(MIB.buildInstr(AArch64::ADDXrr, {I.getOperand(0).getReg()},
3726 {ThreadBase, Addr2}));
3727 break;
3728 }
3729 case 48: {
3730 // movz x0, #:tprel_g2:a
3731 // movk x0, #:tprel_g1_nc:a
3732 // movk x0, #:tprel_g0_nc:a
3733 // add x0, x1, x0
3734 Register Addr = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3735 ConstrainRegOps(
3736 MIB.buildInstr(AArch64::MOVZXi, {Addr}, {})
3738 .addImm(32));
3739 Register Addr2 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3740 ConstrainRegOps(MIB.buildInstr(AArch64::MOVKXi, {Addr2}, {Addr})
3741 .addGlobalAddress(GV, 0,
3744 .addImm(16));
3745 Register Addr3 = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
3746 ConstrainRegOps(MIB.buildInstr(AArch64::MOVKXi, {Addr3}, {Addr2})
3747 .addGlobalAddress(GV, 0,
3750 .addImm(0));
3751 ConstrainRegOps(MIB.buildInstr(AArch64::ADDXrr, {I.getOperand(0).getReg()},
3752 {ThreadBase, Addr3}));
3753 break;
3754 }
3755 }
3756 I.eraseFromParent();
3757 return true;
3758}
3759
3760// TLS lowering below mirrors the corresponding DAGISel implementation.
3761// See LowerELFTLSModel() for details.
3762bool AArch64InstructionSelector::selectTLSGlobalValueELF(
3763 MachineInstr &I, MachineRegisterInfo &MRI) {
3764 const GlobalValue *GV = I.getOperand(1).getGlobal();
3765 auto *FuncInfo = MF->getInfo<AArch64FunctionInfo>();
3767 AArch64::getELFTLSModel(GV, TM, FuncInfo->hasELFSignedGOT());
3768
3769 Register TPOff = MRI.createVirtualRegister(&AArch64::GPR64commonRegClass);
3770 switch (Model) {
3772 return selectTLSLocalExecELF(GV, I, MRI);
3774 MIB.buildInstr(AArch64::LOADgot, {TPOff}, {})
3775 .addGlobalAddress(GV, 0, AArch64II::MO_TLS);
3776 break;
3779#ifndef NDEBUG
3780 SMEAttrs Attrs = MF->getInfo<AArch64FunctionInfo>()->getSMEFnAttrs();
3781 assert(!Attrs.hasZAState() && !Attrs.hasStreamingInterfaceOrBody() &&
3782 !Attrs.hasStreamingCompatibleInterface() &&
3783 "unsupported SME features reached GlobalISel TLS lowering");
3784#endif
3785 unsigned Opcode = FuncInfo->hasELFSignedGOT()
3786 ? AArch64::TLSDESC_AUTH_CALLSEQ
3787 : AArch64::TLSDESC_CALLSEQ;
3788
3789 if (TLSModel::GeneralDynamic == Model) {
3790 MIB.buildInstr(Opcode, {}, {}).addGlobalAddress(GV, 0, AArch64II::MO_TLS);
3791 MIB.buildCopy(TPOff, Register(AArch64::X0));
3792 break;
3793 }
3795 // These accesses will need deduplicating if there's more than one.
3797
3798 MIB.buildInstr(Opcode, {}, {})
3799 .addExternalSymbol("_TLS_MODULE_BASE_", AArch64II::MO_TLS);
3800 auto Copy = MIB.buildCopy(LLT::scalar(64), Register(AArch64::X0));
3801 auto Add1 =
3802 MIB.buildInstr(AArch64::ADDXri, {LLT::scalar(64)}, {Copy.getReg(0)})
3803 .addGlobalAddress(GV, 0, AArch64II::MO_TLS | AArch64II::MO_HI12)
3804 .addImm(0);
3805 auto Add2 =
3806 MIB.buildInstr(AArch64::ADDXri, {TPOff}, {Add1.getReg(0)})
3807 .addGlobalAddress(GV, 0,
3810 .addImm(0);
3813 }
3814 }
3816 MIB.buildInstr(AArch64::MOVbaseTLS, {ThreadBase}, {});
3817 auto Add = MIB.buildInstr(AArch64::ADDXrr, {I.getOperand(0).getReg()},
3818 {ThreadBase, TPOff});
3820
3821 I.eraseFromParent();
3822 return true;
3823}
3824
3825bool AArch64InstructionSelector::selectTLSGlobalValueMachO(
3826 MachineInstr &I, MachineRegisterInfo &MRI) {
3827 const auto &GlobalOp = I.getOperand(1);
3828 assert(GlobalOp.getOffset() == 0 &&
3829 "Shouldn't have an offset on TLS globals!");
3830
3831 const GlobalValue &GV = *GlobalOp.getGlobal();
3832 MF->getFrameInfo().setAdjustsStack(true);
3833 auto LoadGOT =
3834 MIB.buildInstr(AArch64::LOADgot, {&AArch64::GPR64commonRegClass}, {})
3835 .addGlobalAddress(&GV, 0, AArch64II::MO_TLS);
3836
3837 auto Load = MIB.buildInstr(AArch64::LDRXui, {&AArch64::GPR64commonRegClass},
3838 {LoadGOT.getReg(0)})
3839 .addImm(0);
3840
3841 MIB.buildCopy(Register(AArch64::X0), LoadGOT.getReg(0));
3842 // TLS calls preserve all registers except those that absolutely must be
3843 // trashed: X0 (it takes an argument), LR (it's a call) and NZCV (let's not be
3844 // silly).
3845 unsigned Opcode = getBLRCallOpcode(*MF);
3846
3847 // With ptrauth-calls, the tlv access thunk pointer is authenticated (IA, 0).
3848 if (MF->getFunction().hasFnAttribute("ptrauth-calls")) {
3849 assert(Opcode == AArch64::BLR);
3850 Opcode = AArch64::BLRAAZ;
3851 }
3852
3853 MIB.buildInstr(Opcode, {}, {Load})
3854 .setOperandDead(1) // implicit-def $lr
3855 .addUse(AArch64::X0, RegState::Implicit)
3856 .addDef(AArch64::X0, RegState::Implicit)
3857 .addRegMask(TRI.getTLSCallPreservedMask());
3858
3859 MIB.buildCopy(I.getOperand(0).getReg(), Register(AArch64::X0));
3860 RBI.constrainGenericRegister(I.getOperand(0).getReg(), AArch64::GPR64RegClass,
3861 MRI);
3862 I.eraseFromParent();
3863 return true;
3864}
3865
3866bool AArch64InstructionSelector::selectTLSGlobalValue(
3867 MachineInstr &I, MachineRegisterInfo &MRI) {
3868 // We don't support instructions with emulated TLS variables yet.
3869 if (TM.useEmulatedTLS())
3870 return false;
3871
3872 if (STI.isTargetELF())
3873 return selectTLSGlobalValueELF(I, MRI);
3874
3875 if (STI.isTargetMachO())
3876 return selectTLSGlobalValueMachO(I, MRI);
3877
3878 return false;
3879}
3880
3881MachineInstr *AArch64InstructionSelector::emitScalarToVector(
3882 unsigned EltSize, const TargetRegisterClass *DstRC, Register Scalar,
3883 MachineIRBuilder &MIRBuilder) const {
3884 auto Undef = MIRBuilder.buildInstr(TargetOpcode::IMPLICIT_DEF, {DstRC}, {});
3885
3886 auto BuildFn = [&](unsigned SubregIndex) {
3887 auto Ins =
3888 MIRBuilder
3889 .buildInstr(TargetOpcode::INSERT_SUBREG, {DstRC}, {Undef, Scalar})
3890 .addImm(SubregIndex);
3893 return &*Ins;
3894 };
3895
3896 switch (EltSize) {
3897 case 8:
3898 return BuildFn(AArch64::bsub);
3899 case 16:
3900 return BuildFn(AArch64::hsub);
3901 case 32:
3902 return BuildFn(AArch64::ssub);
3903 case 64:
3904 return BuildFn(AArch64::dsub);
3905 default:
3906 return nullptr;
3907 }
3908}
3909
3910MachineInstr *
3911AArch64InstructionSelector::emitNarrowVector(Register DstReg, Register SrcReg,
3912 MachineIRBuilder &MIB,
3913 MachineRegisterInfo &MRI) const {
3914 LLT DstTy = MRI.getType(DstReg);
3915 const TargetRegisterClass *RC =
3916 getRegClassForTypeOnBank(DstTy, *RBI.getRegBank(SrcReg, MRI, TRI));
3917 if (RC != &AArch64::FPR32RegClass && RC != &AArch64::FPR64RegClass) {
3918 LLVM_DEBUG(dbgs() << "Unsupported register class!\n");
3919 return nullptr;
3920 }
3921 unsigned SubReg = 0;
3922 if (!getSubRegForClass(RC, TRI, SubReg))
3923 return nullptr;
3924 if (SubReg != AArch64::ssub && SubReg != AArch64::dsub) {
3925 LLVM_DEBUG(dbgs() << "Unsupported destination size! ("
3926 << DstTy.getSizeInBits() << "\n");
3927 return nullptr;
3928 }
3929 auto Copy = MIB.buildInstr(TargetOpcode::COPY, {DstReg}, {})
3930 .addReg(SrcReg, {}, SubReg);
3931 RBI.constrainGenericRegister(DstReg, *RC, MRI);
3932 return Copy;
3933}
3934
3935bool AArch64InstructionSelector::selectMergeValues(
3936 MachineInstr &I, MachineRegisterInfo &MRI) {
3937 assert(I.getOpcode() == TargetOpcode::G_MERGE_VALUES && "unexpected opcode");
3938 const LLT DstTy = MRI.getType(I.getOperand(0).getReg());
3939 const LLT SrcTy = MRI.getType(I.getOperand(1).getReg());
3940 assert(!DstTy.isVector() && !SrcTy.isVector() && "invalid merge operation");
3941 const RegisterBank &RB = *RBI.getRegBank(I.getOperand(1).getReg(), MRI, TRI);
3942
3943 if (I.getNumOperands() != 3)
3944 return false;
3945
3946 // Merging 2 s64s into an s128.
3947 if (DstTy == LLT::scalar(128)) {
3948 if (SrcTy.getSizeInBits() != 64)
3949 return false;
3950 Register DstReg = I.getOperand(0).getReg();
3951 Register Src1Reg = I.getOperand(1).getReg();
3952 Register Src2Reg = I.getOperand(2).getReg();
3953 auto Tmp = MIB.buildInstr(TargetOpcode::IMPLICIT_DEF, {DstTy}, {});
3954 MachineInstr *InsMI = emitLaneInsert(std::nullopt, Tmp.getReg(0), Src1Reg,
3955 /* LaneIdx */ 0, RB, MIB);
3956 if (!InsMI)
3957 return false;
3958 MachineInstr *Ins2MI = emitLaneInsert(DstReg, InsMI->getOperand(0).getReg(),
3959 Src2Reg, /* LaneIdx */ 1, RB, MIB);
3960 if (!Ins2MI)
3961 return false;
3964 I.eraseFromParent();
3965 return true;
3966 }
3967
3968 if (RB.getID() != AArch64::GPRRegBankID)
3969 return false;
3970
3971 if (DstTy.getSizeInBits() != 64 || SrcTy.getSizeInBits() != 32)
3972 return false;
3973
3974 auto *DstRC = &AArch64::GPR64RegClass;
3975 Register SubToRegDef = MRI.createVirtualRegister(DstRC);
3976 MachineInstr &SubRegMI = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
3977 TII.get(TargetOpcode::SUBREG_TO_REG))
3978 .addDef(SubToRegDef)
3979 .addUse(I.getOperand(1).getReg())
3980 .addImm(AArch64::sub_32);
3981 Register SubToRegDef2 = MRI.createVirtualRegister(DstRC);
3982 // Need to anyext the second scalar before we can use bfm
3983 MachineInstr &SubRegMI2 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
3984 TII.get(TargetOpcode::SUBREG_TO_REG))
3985 .addDef(SubToRegDef2)
3986 .addUse(I.getOperand(2).getReg())
3987 .addImm(AArch64::sub_32);
3988 MachineInstr &BFM =
3989 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AArch64::BFMXri))
3990 .addDef(I.getOperand(0).getReg())
3991 .addUse(SubToRegDef)
3992 .addUse(SubToRegDef2)
3993 .addImm(32)
3994 .addImm(31);
3995 constrainSelectedInstRegOperands(SubRegMI, TII, TRI, RBI);
3996 constrainSelectedInstRegOperands(SubRegMI2, TII, TRI, RBI);
3998 I.eraseFromParent();
3999 return true;
4000}
4001
4002static bool getLaneCopyOpcode(unsigned &CopyOpc, unsigned &ExtractSubReg,
4003 const unsigned EltSize) {
4004 // Choose a lane copy opcode and subregister based off of the size of the
4005 // vector's elements.
4006 switch (EltSize) {
4007 case 8:
4008 CopyOpc = AArch64::DUPi8;
4009 ExtractSubReg = AArch64::bsub;
4010 break;
4011 case 16:
4012 CopyOpc = AArch64::DUPi16;
4013 ExtractSubReg = AArch64::hsub;
4014 break;
4015 case 32:
4016 CopyOpc = AArch64::DUPi32;
4017 ExtractSubReg = AArch64::ssub;
4018 break;
4019 case 64:
4020 CopyOpc = AArch64::DUPi64;
4021 ExtractSubReg = AArch64::dsub;
4022 break;
4023 default:
4024 // Unknown size, bail out.
4025 LLVM_DEBUG(dbgs() << "Elt size '" << EltSize << "' unsupported.\n");
4026 return false;
4027 }
4028 return true;
4029}
4030
4031MachineInstr *AArch64InstructionSelector::emitExtractVectorElt(
4032 std::optional<Register> DstReg, const RegisterBank &DstRB, LLT ScalarTy,
4033 Register VecReg, unsigned LaneIdx, MachineIRBuilder &MIRBuilder) const {
4034 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
4035 unsigned CopyOpc = 0;
4036 unsigned ExtractSubReg = 0;
4037 if (!getLaneCopyOpcode(CopyOpc, ExtractSubReg, ScalarTy.getSizeInBits())) {
4038 LLVM_DEBUG(
4039 dbgs() << "Couldn't determine lane copy opcode for instruction.\n");
4040 return nullptr;
4041 }
4042
4043 const TargetRegisterClass *DstRC =
4044 getRegClassForTypeOnBank(ScalarTy, DstRB, true);
4045 if (!DstRC) {
4046 LLVM_DEBUG(dbgs() << "Could not determine destination register class.\n");
4047 return nullptr;
4048 }
4049
4050 const RegisterBank &VecRB = *RBI.getRegBank(VecReg, MRI, TRI);
4051 const LLT &VecTy = MRI.getType(VecReg);
4052 const TargetRegisterClass *VecRC =
4053 getRegClassForTypeOnBank(VecTy, VecRB, true);
4054 if (!VecRC) {
4055 LLVM_DEBUG(dbgs() << "Could not determine source register class.\n");
4056 return nullptr;
4057 }
4058
4059 // The register that we're going to copy into.
4060 Register InsertReg = VecReg;
4061 if (!DstReg)
4062 DstReg = MRI.createVirtualRegister(DstRC);
4063 // If the lane index is 0, we just use a subregister COPY.
4064 if (LaneIdx == 0) {
4065 auto Copy = MIRBuilder.buildInstr(TargetOpcode::COPY, {*DstReg}, {})
4066 .addReg(VecReg, {}, ExtractSubReg);
4067 RBI.constrainGenericRegister(*DstReg, *DstRC, MRI);
4068 return &*Copy;
4069 }
4070
4071 // Lane copies require 128-bit wide registers. If we're dealing with an
4072 // unpacked vector, then we need to move up to that width. Insert an implicit
4073 // def and a subregister insert to get us there.
4074 if (VecTy.getSizeInBits() != 128) {
4075 MachineInstr *ScalarToVector = emitScalarToVector(
4076 VecTy.getSizeInBits(), &AArch64::FPR128RegClass, VecReg, MIRBuilder);
4077 if (!ScalarToVector)
4078 return nullptr;
4079 InsertReg = ScalarToVector->getOperand(0).getReg();
4080 }
4081
4082 MachineInstr *LaneCopyMI =
4083 MIRBuilder.buildInstr(CopyOpc, {*DstReg}, {InsertReg}).addImm(LaneIdx);
4084 constrainSelectedInstRegOperands(*LaneCopyMI, TII, TRI, RBI);
4085
4086 // Make sure that we actually constrain the initial copy.
4087 RBI.constrainGenericRegister(*DstReg, *DstRC, MRI);
4088 return LaneCopyMI;
4089}
4090
4091bool AArch64InstructionSelector::selectExtractElt(
4092 MachineInstr &I, MachineRegisterInfo &MRI) {
4093 assert(I.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT &&
4094 "unexpected opcode!");
4095 Register DstReg = I.getOperand(0).getReg();
4096 const LLT NarrowTy = MRI.getType(DstReg);
4097 const Register SrcReg = I.getOperand(1).getReg();
4098 const LLT WideTy = MRI.getType(SrcReg);
4099 assert(WideTy.getSizeInBits() >= NarrowTy.getSizeInBits() &&
4100 "source register size too small!");
4101 assert(!NarrowTy.isVector() && "cannot extract vector into vector!");
4102
4103 // Need the lane index to determine the correct copy opcode.
4104 MachineOperand &LaneIdxOp = I.getOperand(2);
4105 assert(LaneIdxOp.isReg() && "Lane index operand was not a register?");
4106
4107 // Find the index to extract from.
4108 auto VRegAndVal = getIConstantVRegValWithLookThrough(LaneIdxOp.getReg(), MRI);
4109 if (!VRegAndVal)
4110 return false;
4111 unsigned LaneIdx = VRegAndVal->Value.getSExtValue();
4112
4113 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
4114 if (DstRB.getID() == AArch64::GPRRegBankID) {
4115 unsigned Opcode;
4116 switch (WideTy.getScalarSizeInBits()) {
4117 case 8:
4118 Opcode = AArch64::UMOVvi8;
4119 break;
4120 case 16:
4121 Opcode = AArch64::UMOVvi16;
4122 break;
4123 case 32:
4124 Opcode = AArch64::UMOVvi32;
4125 break;
4126 default:
4127 return false;
4128 }
4129
4130 if (WideTy.getSizeInBits() != 128) {
4131 MachineInstr *ScalarToVector = emitScalarToVector(
4132 WideTy.getSizeInBits(), &AArch64::FPR128RegClass, SrcReg, MIB);
4133 assert(ScalarToVector && "Didn't expect emitScalarToVector to fail!");
4134 I.getOperand(1).setReg(ScalarToVector->getOperand(0).getReg());
4135 }
4136
4137 I.setDesc(TII.get(Opcode));
4138 I.getOperand(2).ChangeToImmediate(LaneIdx);
4140 return true;
4141 }
4142
4143 MachineInstr *Extract = emitExtractVectorElt(DstReg, DstRB, NarrowTy, SrcReg,
4144 LaneIdx, MIB);
4145 if (!Extract)
4146 return false;
4147
4148 I.eraseFromParent();
4149 return true;
4150}
4151
4152bool AArch64InstructionSelector::selectSplitVectorUnmerge(
4153 MachineInstr &I, MachineRegisterInfo &MRI) {
4154 unsigned NumElts = I.getNumOperands() - 1;
4155 Register SrcReg = I.getOperand(NumElts).getReg();
4156 const LLT NarrowTy = MRI.getType(I.getOperand(0).getReg());
4157 const LLT SrcTy = MRI.getType(SrcReg);
4158
4159 assert(NarrowTy.isVector() && "Expected an unmerge into vectors");
4160 if (SrcTy.getSizeInBits() > 128) {
4161 LLVM_DEBUG(dbgs() << "Unexpected vector type for vec split unmerge");
4162 return false;
4163 }
4164
4165 // We implement a split vector operation by treating the sub-vectors as
4166 // scalars and extracting them.
4167 const RegisterBank &DstRB =
4168 *RBI.getRegBank(I.getOperand(0).getReg(), MRI, TRI);
4169 for (unsigned OpIdx = 0; OpIdx < NumElts; ++OpIdx) {
4170 Register Dst = I.getOperand(OpIdx).getReg();
4171 MachineInstr *Extract =
4172 emitExtractVectorElt(Dst, DstRB, NarrowTy, SrcReg, OpIdx, MIB);
4173 if (!Extract)
4174 return false;
4175 }
4176 I.eraseFromParent();
4177 return true;
4178}
4179
4180bool AArch64InstructionSelector::selectUnmergeValues(MachineInstr &I,
4181 MachineRegisterInfo &MRI) {
4182 assert(I.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
4183 "unexpected opcode");
4184
4185 // The last operand is the vector source register, and every other operand is
4186 // a register to unpack into.
4187 unsigned NumElts = I.getNumOperands() - 1;
4188 Register SrcReg = I.getOperand(NumElts).getReg();
4189 Register LoReg = I.getOperand(0).getReg();
4190 Register HiReg = I.getOperand(1).getReg();
4191 const LLT NarrowTy = MRI.getType(LoReg);
4192 const LLT WideTy = MRI.getType(SrcReg);
4193 const RegisterBank &LoRB = *RBI.getRegBank(LoReg, MRI, TRI);
4194 const RegisterBank &HiRB = *RBI.getRegBank(HiReg, MRI, TRI);
4195 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
4196
4197 // Handle unmerging a 128-bit FPR value into two 64-bit GPR values.
4198 if (NarrowTy == LLT::scalar(64) && WideTy == LLT::scalar(128) &&
4199 LoRB.getID() == AArch64::GPRRegBankID &&
4200 HiRB.getID() == AArch64::GPRRegBankID &&
4201 SrcRB.getID() == AArch64::FPRRegBankID) {
4202 MachineInstr &Lo = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
4203 TII.get(AArch64::UMOVvi64), LoReg)
4204 .addUse(SrcReg)
4205 .addImm(0);
4206 MachineInstr &Hi = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
4207 TII.get(AArch64::UMOVvi64), HiReg)
4208 .addUse(SrcReg)
4209 .addImm(1);
4212 I.eraseFromParent();
4213 return true;
4214 }
4215
4216 // TODO: Handle other unmerges into GPRs and from scalars to scalars.
4217 if (LoRB.getID() != AArch64::FPRRegBankID ||
4218 HiRB.getID() != AArch64::FPRRegBankID) {
4219 LLVM_DEBUG(dbgs() << "Unmerging vector-to-gpr and scalar-to-scalar "
4220 "currently unsupported.\n");
4221 return false;
4222 }
4223
4224 assert(WideTy.getSizeInBits() > NarrowTy.getSizeInBits() &&
4225 "source register size too small!");
4226
4227 if (!NarrowTy.isScalar())
4228 return selectSplitVectorUnmerge(I, MRI);
4229
4230 // Choose a lane copy opcode and subregister based off of the size of the
4231 // vector's elements.
4232 unsigned CopyOpc = 0;
4233 unsigned ExtractSubReg = 0;
4234 if (!getLaneCopyOpcode(CopyOpc, ExtractSubReg, NarrowTy.getSizeInBits()))
4235 return false;
4236
4237 // Set up for the lane copies.
4238 MachineBasicBlock &MBB = *I.getParent();
4239
4240 // Stores the registers we'll be copying from.
4241 SmallVector<Register, 4> InsertRegs;
4242
4243 // We'll use the first register twice, so we only need NumElts-1 registers.
4244 unsigned NumInsertRegs = NumElts - 1;
4245
4246 // If our elements fit into exactly 128 bits, then we can copy from the source
4247 // directly. Otherwise, we need to do a bit of setup with some subregister
4248 // inserts.
4249 if (NarrowTy.getSizeInBits() * NumElts == 128) {
4250 InsertRegs.assign(NumInsertRegs, SrcReg);
4251 } else {
4252 // No. We have to perform subregister inserts. For each insert, create an
4253 // implicit def and a subregister insert, and save the register we create.
4254 // For scalar sources, treat as a pseudo-vector of NarrowTy elements.
4255 unsigned EltSize = WideTy.isVector() ? WideTy.getScalarSizeInBits()
4256 : NarrowTy.getSizeInBits();
4257 const TargetRegisterClass *RC = getRegClassForTypeOnBank(
4258 LLT::fixed_vector(NumElts, EltSize), *RBI.getRegBank(SrcReg, MRI, TRI));
4259 unsigned SubReg = 0;
4260 bool Found = getSubRegForClass(RC, TRI, SubReg);
4261 (void)Found;
4262 assert(Found && "expected to find last operand's subeg idx");
4263 for (unsigned Idx = 0; Idx < NumInsertRegs; ++Idx) {
4264 Register ImpDefReg = MRI.createVirtualRegister(&AArch64::FPR128RegClass);
4265 MachineInstr &ImpDefMI =
4266 *BuildMI(MBB, I, I.getDebugLoc(), TII.get(TargetOpcode::IMPLICIT_DEF),
4267 ImpDefReg);
4268
4269 // Now, create the subregister insert from SrcReg.
4270 Register InsertReg = MRI.createVirtualRegister(&AArch64::FPR128RegClass);
4271 MachineInstr &InsMI =
4272 *BuildMI(MBB, I, I.getDebugLoc(),
4273 TII.get(TargetOpcode::INSERT_SUBREG), InsertReg)
4274 .addUse(ImpDefReg)
4275 .addUse(SrcReg)
4276 .addImm(SubReg);
4277
4278 constrainSelectedInstRegOperands(ImpDefMI, TII, TRI, RBI);
4280
4281 // Save the register so that we can copy from it after.
4282 InsertRegs.push_back(InsertReg);
4283 }
4284 }
4285
4286 // Now that we've created any necessary subregister inserts, we can
4287 // create the copies.
4288 //
4289 // Perform the first copy separately as a subregister copy.
4290 Register CopyTo = I.getOperand(0).getReg();
4291 auto FirstCopy = MIB.buildInstr(TargetOpcode::COPY, {CopyTo}, {})
4292 .addReg(InsertRegs[0], {}, ExtractSubReg);
4293 constrainSelectedInstRegOperands(*FirstCopy, TII, TRI, RBI);
4294
4295 // Now, perform the remaining copies as vector lane copies.
4296 unsigned LaneIdx = 1;
4297 for (Register InsReg : InsertRegs) {
4298 Register CopyTo = I.getOperand(LaneIdx).getReg();
4299 MachineInstr &CopyInst =
4300 *BuildMI(MBB, I, I.getDebugLoc(), TII.get(CopyOpc), CopyTo)
4301 .addUse(InsReg)
4302 .addImm(LaneIdx);
4303 constrainSelectedInstRegOperands(CopyInst, TII, TRI, RBI);
4304 ++LaneIdx;
4305 }
4306
4307 // Separately constrain the first copy's destination. Because of the
4308 // limitation in constrainOperandRegClass, we can't guarantee that this will
4309 // actually be constrained. So, do it ourselves using the second operand.
4310 const TargetRegisterClass *RC =
4311 MRI.getRegClassOrNull(I.getOperand(1).getReg());
4312 if (!RC) {
4313 LLVM_DEBUG(dbgs() << "Couldn't constrain copy destination.\n");
4314 return false;
4315 }
4316
4317 RBI.constrainGenericRegister(CopyTo, *RC, MRI);
4318 I.eraseFromParent();
4319 return true;
4320}
4321
4322bool AArch64InstructionSelector::selectConcatVectors(
4323 MachineInstr &I, MachineRegisterInfo &MRI) {
4324 assert(I.getOpcode() == TargetOpcode::G_CONCAT_VECTORS &&
4325 "Unexpected opcode");
4326 Register Dst = I.getOperand(0).getReg();
4327 Register Op1 = I.getOperand(1).getReg();
4328 Register Op2 = I.getOperand(2).getReg();
4329 MachineInstr *ConcatMI = emitVectorConcat(Dst, Op1, Op2, MIB);
4330 if (!ConcatMI)
4331 return false;
4332 I.eraseFromParent();
4333 return true;
4334}
4335
4336unsigned
4337AArch64InstructionSelector::emitConstantPoolEntry(const Constant *CPVal,
4338 MachineFunction &MF) const {
4339 Type *CPTy = CPVal->getType();
4341
4342 MachineConstantPool *MCP = MF.getConstantPool();
4343 return MCP->getConstantPoolIndex(CPVal, Alignment);
4344}
4345
4346MachineInstr *AArch64InstructionSelector::emitLoadFromConstantPool(
4347 const Constant *CPVal, MachineIRBuilder &MIRBuilder) const {
4348 const TargetRegisterClass *RC;
4349 unsigned Opc;
4350 bool IsTiny = TM.getCodeModel() == CodeModel::Tiny;
4351 unsigned Size = MIRBuilder.getDataLayout().getTypeStoreSize(CPVal->getType());
4352 switch (Size) {
4353 case 16:
4354 RC = &AArch64::FPR128RegClass;
4355 Opc = IsTiny ? AArch64::LDRQl : AArch64::LDRQui;
4356 break;
4357 case 8:
4358 RC = &AArch64::FPR64RegClass;
4359 Opc = IsTiny ? AArch64::LDRDl : AArch64::LDRDui;
4360 break;
4361 case 4:
4362 RC = &AArch64::FPR32RegClass;
4363 Opc = IsTiny ? AArch64::LDRSl : AArch64::LDRSui;
4364 break;
4365 case 2:
4366 RC = &AArch64::FPR16RegClass;
4367 Opc = AArch64::LDRHui;
4368 break;
4369 default:
4370 LLVM_DEBUG(dbgs() << "Could not load from constant pool of type "
4371 << *CPVal->getType());
4372 return nullptr;
4373 }
4374
4375 MachineInstr *LoadMI = nullptr;
4376 auto &MF = MIRBuilder.getMF();
4377 unsigned CPIdx = emitConstantPoolEntry(CPVal, MF);
4378 if (IsTiny && (Size == 16 || Size == 8 || Size == 4)) {
4379 // Use load(literal) for tiny code model.
4380 LoadMI = &*MIRBuilder.buildInstr(Opc, {RC}, {}).addConstantPoolIndex(CPIdx);
4381 } else {
4382 auto Adrp =
4383 MIRBuilder.buildInstr(AArch64::ADRP, {&AArch64::GPR64RegClass}, {})
4384 .addConstantPoolIndex(CPIdx, 0, AArch64II::MO_PAGE);
4385
4386 LoadMI = &*MIRBuilder.buildInstr(Opc, {RC}, {Adrp})
4387 .addConstantPoolIndex(
4389
4391 }
4392
4393 MachinePointerInfo PtrInfo = MachinePointerInfo::getConstantPool(MF);
4394 LoadMI->addMemOperand(MF, MF.getMachineMemOperand(PtrInfo,
4396 Size, Align(Size)));
4398 return LoadMI;
4399}
4400
4401/// Return an <Opcode, SubregIndex> pair to do an vector elt insert of a given
4402/// size and RB.
4403static std::pair<unsigned, unsigned>
4404getInsertVecEltOpInfo(const RegisterBank &RB, unsigned EltSize) {
4405 unsigned Opc, SubregIdx;
4406 if (RB.getID() == AArch64::GPRRegBankID) {
4407 if (EltSize == 8) {
4408 Opc = AArch64::INSvi8gpr;
4409 SubregIdx = AArch64::bsub;
4410 } else if (EltSize == 16) {
4411 Opc = AArch64::INSvi16gpr;
4412 SubregIdx = AArch64::ssub;
4413 } else if (EltSize == 32) {
4414 Opc = AArch64::INSvi32gpr;
4415 SubregIdx = AArch64::ssub;
4416 } else if (EltSize == 64) {
4417 Opc = AArch64::INSvi64gpr;
4418 SubregIdx = AArch64::dsub;
4419 } else {
4420 llvm_unreachable("invalid elt size!");
4421 }
4422 } else {
4423 if (EltSize == 8) {
4424 Opc = AArch64::INSvi8lane;
4425 SubregIdx = AArch64::bsub;
4426 } else if (EltSize == 16) {
4427 Opc = AArch64::INSvi16lane;
4428 SubregIdx = AArch64::hsub;
4429 } else if (EltSize == 32) {
4430 Opc = AArch64::INSvi32lane;
4431 SubregIdx = AArch64::ssub;
4432 } else if (EltSize == 64) {
4433 Opc = AArch64::INSvi64lane;
4434 SubregIdx = AArch64::dsub;
4435 } else {
4436 llvm_unreachable("invalid elt size!");
4437 }
4438 }
4439 return std::make_pair(Opc, SubregIdx);
4440}
4441
4442MachineInstr *AArch64InstructionSelector::emitInstr(
4443 unsigned Opcode, std::initializer_list<llvm::DstOp> DstOps,
4444 std::initializer_list<llvm::SrcOp> SrcOps, MachineIRBuilder &MIRBuilder,
4445 const ComplexRendererFns &RenderFns) const {
4446 assert(Opcode && "Expected an opcode?");
4447 assert(!isPreISelGenericOpcode(Opcode) &&
4448 "Function should only be used to produce selected instructions!");
4449 auto MI = MIRBuilder.buildInstr(Opcode, DstOps, SrcOps);
4450 if (RenderFns)
4451 for (auto &Fn : *RenderFns)
4452 Fn(MI);
4454 return &*MI;
4455}
4456
4457MachineInstr *AArch64InstructionSelector::emitAddSub(
4458 const std::array<std::array<unsigned, 2>, 5> &AddrModeAndSizeToOpcode,
4459 Register Dst, MachineOperand &LHS, MachineOperand &RHS,
4460 MachineIRBuilder &MIRBuilder) const {
4461 MachineRegisterInfo &MRI = MIRBuilder.getMF().getRegInfo();
4462 assert(LHS.isReg() && RHS.isReg() && "Expected register operands?");
4463 auto Ty = MRI.getType(LHS.getReg());
4464 assert(!Ty.isVector() && "Expected a scalar or pointer?");
4465 unsigned Size = Ty.getSizeInBits();
4466 assert((Size == 32 || Size == 64) && "Expected a 32-bit or 64-bit type only");
4467 bool Is32Bit = Size == 32;
4468
4469 // INSTRri form with positive arithmetic immediate.
4470 if (auto Fns = selectArithImmed(RHS))
4471 return emitInstr(AddrModeAndSizeToOpcode[0][Is32Bit], {Dst}, {LHS},
4472 MIRBuilder, Fns);
4473
4474 // INSTRri form with negative arithmetic immediate.
4475 if (auto Fns = selectNegArithImmed(RHS))
4476 return emitInstr(AddrModeAndSizeToOpcode[3][Is32Bit], {Dst}, {LHS},
4477 MIRBuilder, Fns);
4478
4479 // INSTRrx form.
4480 if (auto Fns = selectArithExtendedRegister(RHS))
4481 return emitInstr(AddrModeAndSizeToOpcode[4][Is32Bit], {Dst}, {LHS},
4482 MIRBuilder, Fns);
4483
4484 // INSTRrs form.
4485 if (auto Fns = selectShiftedRegister(RHS))
4486 return emitInstr(AddrModeAndSizeToOpcode[1][Is32Bit], {Dst}, {LHS},
4487 MIRBuilder, Fns);
4488 return emitInstr(AddrModeAndSizeToOpcode[2][Is32Bit], {Dst}, {LHS, RHS},
4489 MIRBuilder);
4490}
4491
4492MachineInstr *
4493AArch64InstructionSelector::emitADD(Register DefReg, MachineOperand &LHS,
4494 MachineOperand &RHS,
4495 MachineIRBuilder &MIRBuilder) const {
4496 const std::array<std::array<unsigned, 2>, 5> OpcTable{
4497 {{AArch64::ADDXri, AArch64::ADDWri},
4498 {AArch64::ADDXrs, AArch64::ADDWrs},
4499 {AArch64::ADDXrr, AArch64::ADDWrr},
4500 {AArch64::SUBXri, AArch64::SUBWri},
4501 {AArch64::ADDXrx, AArch64::ADDWrx}}};
4502 return emitAddSub(OpcTable, DefReg, LHS, RHS, MIRBuilder);
4503}
4504
4505MachineInstr *
4506AArch64InstructionSelector::emitADDS(Register Dst, MachineOperand &LHS,
4507 MachineOperand &RHS,
4508 MachineIRBuilder &MIRBuilder) const {
4509 const std::array<std::array<unsigned, 2>, 5> OpcTable{
4510 {{AArch64::ADDSXri, AArch64::ADDSWri},
4511 {AArch64::ADDSXrs, AArch64::ADDSWrs},
4512 {AArch64::ADDSXrr, AArch64::ADDSWrr},
4513 {AArch64::SUBSXri, AArch64::SUBSWri},
4514 {AArch64::ADDSXrx, AArch64::ADDSWrx}}};
4515 return emitAddSub(OpcTable, Dst, LHS, RHS, MIRBuilder);
4516}
4517
4518MachineInstr *
4519AArch64InstructionSelector::emitSUBS(Register Dst, MachineOperand &LHS,
4520 MachineOperand &RHS,
4521 MachineIRBuilder &MIRBuilder) const {
4522 const std::array<std::array<unsigned, 2>, 5> OpcTable{
4523 {{AArch64::SUBSXri, AArch64::SUBSWri},
4524 {AArch64::SUBSXrs, AArch64::SUBSWrs},
4525 {AArch64::SUBSXrr, AArch64::SUBSWrr},
4526 {AArch64::ADDSXri, AArch64::ADDSWri},
4527 {AArch64::SUBSXrx, AArch64::SUBSWrx}}};
4528 return emitAddSub(OpcTable, Dst, LHS, RHS, MIRBuilder);
4529}
4530
4531MachineInstr *
4532AArch64InstructionSelector::emitADCS(Register Dst, MachineOperand &LHS,
4533 MachineOperand &RHS,
4534 MachineIRBuilder &MIRBuilder) const {
4535 assert(LHS.isReg() && RHS.isReg() && "Expected register operands?");
4536 MachineRegisterInfo *MRI = MIRBuilder.getMRI();
4537 bool Is32Bit = (MRI->getType(LHS.getReg()).getSizeInBits() == 32);
4538 static const unsigned OpcTable[2] = {AArch64::ADCSXr, AArch64::ADCSWr};
4539 return emitInstr(OpcTable[Is32Bit], {Dst}, {LHS, RHS}, MIRBuilder);
4540}
4541
4542MachineInstr *
4543AArch64InstructionSelector::emitSBCS(Register Dst, MachineOperand &LHS,
4544 MachineOperand &RHS,
4545 MachineIRBuilder &MIRBuilder) const {
4546 assert(LHS.isReg() && RHS.isReg() && "Expected register operands?");
4547 MachineRegisterInfo *MRI = MIRBuilder.getMRI();
4548 bool Is32Bit = (MRI->getType(LHS.getReg()).getSizeInBits() == 32);
4549 static const unsigned OpcTable[2] = {AArch64::SBCSXr, AArch64::SBCSWr};
4550 return emitInstr(OpcTable[Is32Bit], {Dst}, {LHS, RHS}, MIRBuilder);
4551}
4552
4553MachineInstr *
4554AArch64InstructionSelector::emitCMP(MachineOperand &LHS, MachineOperand &RHS,
4555 MachineIRBuilder &MIRBuilder) const {
4556 MachineRegisterInfo &MRI = MIRBuilder.getMF().getRegInfo();
4557 bool Is32Bit = MRI.getType(LHS.getReg()).getSizeInBits() == 32;
4558 auto RC = Is32Bit ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass;
4559 return emitSUBS(MRI.createVirtualRegister(RC), LHS, RHS, MIRBuilder);
4560}
4561
4562MachineInstr *
4563AArch64InstructionSelector::emitCMN(MachineOperand &LHS, MachineOperand &RHS,
4564 MachineIRBuilder &MIRBuilder) const {
4565 MachineRegisterInfo &MRI = MIRBuilder.getMF().getRegInfo();
4566 bool Is32Bit = (MRI.getType(LHS.getReg()).getSizeInBits() == 32);
4567 auto RC = Is32Bit ? &AArch64::GPR32RegClass : &AArch64::GPR64RegClass;
4568 return emitADDS(MRI.createVirtualRegister(RC), LHS, RHS, MIRBuilder);
4569}
4570
4571MachineInstr *
4572AArch64InstructionSelector::emitTST(MachineOperand &LHS, MachineOperand &RHS,
4573 MachineIRBuilder &MIRBuilder) const {
4574 assert(LHS.isReg() && RHS.isReg() && "Expected register operands?");
4575 MachineRegisterInfo &MRI = MIRBuilder.getMF().getRegInfo();
4576 LLT Ty = MRI.getType(LHS.getReg());
4577 unsigned RegSize = Ty.getSizeInBits();
4578 bool Is32Bit = (RegSize == 32);
4579 const unsigned OpcTable[3][2] = {{AArch64::ANDSXri, AArch64::ANDSWri},
4580 {AArch64::ANDSXrs, AArch64::ANDSWrs},
4581 {AArch64::ANDSXrr, AArch64::ANDSWrr}};
4582 // ANDS needs a logical immediate for its immediate form. Check if we can
4583 // fold one in.
4584 if (auto ValAndVReg = getIConstantVRegValWithLookThrough(RHS.getReg(), MRI)) {
4585 int64_t Imm = ValAndVReg->Value.getSExtValue();
4586
4588 auto TstMI = MIRBuilder.buildInstr(OpcTable[0][Is32Bit], {Ty}, {LHS});
4591 return &*TstMI;
4592 }
4593 }
4594
4595 if (auto Fns = selectLogicalShiftedRegister(RHS))
4596 return emitInstr(OpcTable[1][Is32Bit], {Ty}, {LHS}, MIRBuilder, Fns);
4597 return emitInstr(OpcTable[2][Is32Bit], {Ty}, {LHS, RHS}, MIRBuilder);
4598}
4599
4600MachineInstr *AArch64InstructionSelector::emitIntegerCompare(
4601 MachineOperand &LHS, MachineOperand &RHS, MachineOperand &Predicate,
4602 MachineIRBuilder &MIRBuilder) const {
4603 assert(LHS.isReg() && RHS.isReg() && "Expected LHS and RHS to be registers!");
4604 assert(Predicate.isPredicate() && "Expected predicate?");
4605 MachineRegisterInfo &MRI = MIRBuilder.getMF().getRegInfo();
4606 LLT CmpTy = MRI.getType(LHS.getReg());
4607 assert(!CmpTy.isVector() && "Expected scalar or pointer");
4608 unsigned Size = CmpTy.getSizeInBits();
4609 (void)Size;
4610 assert((Size == 32 || Size == 64) && "Expected a 32-bit or 64-bit LHS/RHS?");
4611 // Fold the compare into a cmn or tst if possible.
4612 if (auto FoldCmp = tryFoldIntegerCompare(LHS, RHS, Predicate, MIRBuilder))
4613 return FoldCmp;
4614 return emitCMP(LHS, RHS, MIRBuilder);
4615}
4616
4617MachineInstr *AArch64InstructionSelector::emitCSetForFCmp(
4618 Register Dst, CmpInst::Predicate Pred, MachineIRBuilder &MIRBuilder) const {
4619 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
4620#ifndef NDEBUG
4621 LLT Ty = MRI.getType(Dst);
4622 assert(!Ty.isVector() && Ty.getSizeInBits() == 32 &&
4623 "Expected a 32-bit scalar register?");
4624#endif
4625 const Register ZReg = AArch64::WZR;
4626 AArch64CC::CondCode CC1, CC2;
4627 changeFCMPPredToAArch64CC(Pred, CC1, CC2);
4628 auto InvCC1 = AArch64CC::getInvertedCondCode(CC1);
4629 if (CC2 == AArch64CC::AL)
4630 return emitCSINC(/*Dst=*/Dst, /*Src1=*/ZReg, /*Src2=*/ZReg, InvCC1,
4631 MIRBuilder);
4632 const TargetRegisterClass *RC = &AArch64::GPR32RegClass;
4633 Register Def1Reg = MRI.createVirtualRegister(RC);
4634 Register Def2Reg = MRI.createVirtualRegister(RC);
4635 auto InvCC2 = AArch64CC::getInvertedCondCode(CC2);
4636 emitCSINC(/*Dst=*/Def1Reg, /*Src1=*/ZReg, /*Src2=*/ZReg, InvCC1, MIRBuilder);
4637 emitCSINC(/*Dst=*/Def2Reg, /*Src1=*/ZReg, /*Src2=*/ZReg, InvCC2, MIRBuilder);
4638 auto OrMI = MIRBuilder.buildInstr(AArch64::ORRWrr, {Dst}, {Def1Reg, Def2Reg});
4640 return &*OrMI;
4641}
4642
4643MachineInstr *AArch64InstructionSelector::emitFPCompare(
4644 Register LHS, Register RHS, MachineIRBuilder &MIRBuilder,
4645 std::optional<CmpInst::Predicate> Pred) const {
4646 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
4647 LLT Ty = MRI.getType(LHS);
4648 if (Ty.isVector())
4649 return nullptr;
4650 unsigned OpSize = Ty.getSizeInBits();
4651 assert(OpSize == 16 || OpSize == 32 || OpSize == 64);
4652
4653 // If this is a compare against +0.0, then we don't have
4654 // to explicitly materialize a constant.
4655 bool ShouldUseImm = mi_match(RHS, MRI, m_PosZeroFP());
4656
4657 auto IsEqualityPred = [](CmpInst::Predicate P) {
4658 return P == CmpInst::FCMP_OEQ || P == CmpInst::FCMP_ONE ||
4660 };
4661 if (!ShouldUseImm && Pred && IsEqualityPred(*Pred)) {
4662 // Try commuting the operands.
4663 if (mi_match(LHS, MRI, m_PosZeroFP())) {
4664 ShouldUseImm = true;
4665 std::swap(LHS, RHS);
4666 }
4667 }
4668 unsigned CmpOpcTbl[2][3] = {
4669 {AArch64::FCMPHrr, AArch64::FCMPSrr, AArch64::FCMPDrr},
4670 {AArch64::FCMPHri, AArch64::FCMPSri, AArch64::FCMPDri}};
4671 unsigned CmpOpc =
4672 CmpOpcTbl[ShouldUseImm][OpSize == 16 ? 0 : (OpSize == 32 ? 1 : 2)];
4673
4674 // Partially build the compare. Decide if we need to add a use for the
4675 // third operand based off whether or not we're comparing against 0.0.
4676 auto CmpMI = MIRBuilder.buildInstr(CmpOpc).addUse(LHS);
4678 if (!ShouldUseImm)
4679 CmpMI.addUse(RHS);
4681 return &*CmpMI;
4682}
4683
4684MachineInstr *AArch64InstructionSelector::emitVectorConcat(
4685 std::optional<Register> Dst, Register Op1, Register Op2,
4686 MachineIRBuilder &MIRBuilder) const {
4687 // We implement a vector concat by:
4688 // 1. Use scalar_to_vector to insert the lower vector into the larger dest
4689 // 2. Insert the upper vector into the destination's upper element
4690 // TODO: some of this code is common with G_BUILD_VECTOR handling.
4691 MachineRegisterInfo &MRI = MIRBuilder.getMF().getRegInfo();
4692
4693 const LLT Op1Ty = MRI.getType(Op1);
4694 const LLT Op2Ty = MRI.getType(Op2);
4695
4696 if (Op1Ty != Op2Ty) {
4697 LLVM_DEBUG(dbgs() << "Could not do vector concat of differing vector tys");
4698 return nullptr;
4699 }
4700 assert(Op1Ty.isVector() && "Expected a vector for vector concat");
4701
4702 if (Op1Ty.getSizeInBits() >= 128) {
4703 LLVM_DEBUG(dbgs() << "Vector concat not supported for full size vectors");
4704 return nullptr;
4705 }
4706
4707 // At the moment we just support 64 bit vector concats.
4708 if (Op1Ty.getSizeInBits() != 64) {
4709 LLVM_DEBUG(dbgs() << "Vector concat supported for 64b vectors");
4710 return nullptr;
4711 }
4712
4713 const LLT ScalarTy = LLT::scalar(Op1Ty.getSizeInBits());
4714 const RegisterBank &FPRBank = *RBI.getRegBank(Op1, MRI, TRI);
4715 const TargetRegisterClass *DstRC =
4716 getRegClassForTypeOnBank(Op1Ty.multiplyElements(2), FPRBank);
4717
4718 MachineInstr *WidenedOp1 =
4719 emitScalarToVector(ScalarTy.getSizeInBits(), DstRC, Op1, MIRBuilder);
4720 MachineInstr *WidenedOp2 =
4721 emitScalarToVector(ScalarTy.getSizeInBits(), DstRC, Op2, MIRBuilder);
4722 if (!WidenedOp1 || !WidenedOp2) {
4723 LLVM_DEBUG(dbgs() << "Could not emit a vector from scalar value");
4724 return nullptr;
4725 }
4726
4727 // Now do the insert of the upper element.
4728 unsigned InsertOpc, InsSubRegIdx;
4729 std::tie(InsertOpc, InsSubRegIdx) =
4730 getInsertVecEltOpInfo(FPRBank, ScalarTy.getSizeInBits());
4731
4732 if (!Dst)
4733 Dst = MRI.createVirtualRegister(DstRC);
4734 auto InsElt =
4735 MIRBuilder
4736 .buildInstr(InsertOpc, {*Dst}, {WidenedOp1->getOperand(0).getReg()})
4737 .addImm(1) /* Lane index */
4738 .addUse(WidenedOp2->getOperand(0).getReg())
4739 .addImm(0);
4741 return &*InsElt;
4742}
4743
4744MachineInstr *
4745AArch64InstructionSelector::emitCSINC(Register Dst, Register Src1,
4746 Register Src2, AArch64CC::CondCode Pred,
4747 MachineIRBuilder &MIRBuilder) const {
4748 auto &MRI = *MIRBuilder.getMRI();
4749 const RegClassOrRegBank &RegClassOrBank = MRI.getRegClassOrRegBank(Dst);
4750 // If we used a register class, then this won't necessarily have an LLT.
4751 // Compute the size based off whether or not we have a class or bank.
4752 unsigned Size;
4753 if (const auto *RC = dyn_cast<const TargetRegisterClass *>(RegClassOrBank))
4754 Size = TRI.getRegSizeInBits(*RC);
4755 else
4756 Size = MRI.getType(Dst).getSizeInBits();
4757 // Some opcodes use s1.
4758 assert(Size <= 64 && "Expected 64 bits or less only!");
4759 static const unsigned OpcTable[2] = {AArch64::CSINCWr, AArch64::CSINCXr};
4760 unsigned Opc = OpcTable[Size == 64];
4761 auto CSINC = MIRBuilder.buildInstr(Opc, {Dst}, {Src1, Src2}).addImm(Pred);
4763 return &*CSINC;
4764}
4765
4766MachineInstr *AArch64InstructionSelector::emitCarryIn(MachineInstr &I,
4767 Register CarryReg) {
4768 MachineRegisterInfo *MRI = MIB.getMRI();
4769 unsigned Opcode = I.getOpcode();
4770
4771 // If the instruction is a SUB, we need to negate the carry,
4772 // because borrowing is indicated by carry-flag == 0.
4773 bool NeedsNegatedCarry =
4774 (Opcode == TargetOpcode::G_USUBE || Opcode == TargetOpcode::G_SSUBE);
4775
4776 // If the previous instruction will already produce the correct carry, do not
4777 // emit a carry generating instruction. E.g. for G_UADDE/G_USUBE sequences
4778 // generated during legalization of wide add/sub. This optimization depends on
4779 // these sequences not being interrupted by other instructions.
4780 // We have to select the previous instruction before the carry-using
4781 // instruction is deleted by the calling function, otherwise the previous
4782 // instruction might become dead and would get deleted.
4783 MachineInstr *SrcMI = MRI->getVRegDef(CarryReg);
4784
4785 // Debug instructions (e.g., DBG_VALUE) do not modify NZCV, so skip all that
4786 // immediately precede I.
4787 MachineInstr *PrevMI = I.getPrevNode();
4788 while (PrevMI && PrevMI->isDebugInstr())
4789 PrevMI = PrevMI->getPrevNode();
4790
4791 if (SrcMI == PrevMI) {
4792 if (auto *CarrySrcMI = dyn_cast<GAddSubCarryOut>(SrcMI)) {
4793 bool ProducesNegatedCarry = CarrySrcMI->isSub();
4794 if (NeedsNegatedCarry == ProducesNegatedCarry &&
4795 CarrySrcMI->isUnsigned() &&
4796 CarrySrcMI->getCarryOutReg() == CarryReg &&
4797 selectAndRestoreState(*SrcMI))
4798 return nullptr;
4799 }
4800 }
4801
4802 Register DeadReg = MRI->createVirtualRegister(&AArch64::GPR32RegClass);
4803
4804 if (NeedsNegatedCarry) {
4805 // (0 - Carry) sets !C in NZCV when Carry == 1
4806 Register ZReg = AArch64::WZR;
4807 return emitInstr(AArch64::SUBSWrr, {DeadReg}, {ZReg, CarryReg}, MIB);
4808 }
4809
4810 // (Carry - 1) sets !C in NZCV when Carry == 0
4811 auto Fns = select12BitValueWithLeftShift(1);
4812 return emitInstr(AArch64::SUBSWri, {DeadReg}, {CarryReg}, MIB, Fns);
4813}
4814
4815bool AArch64InstructionSelector::selectOverflowOp(MachineInstr &I,
4816 MachineRegisterInfo &MRI) {
4817 auto &CarryMI = cast<GAddSubCarryOut>(I);
4818
4819 if (auto *CarryInMI = dyn_cast<GAddSubCarryInOut>(&I)) {
4820 // Set NZCV carry according to carry-in VReg
4821 emitCarryIn(I, CarryInMI->getCarryInReg());
4822 }
4823
4824 // Emit the operation and get the correct condition code.
4825 auto OpAndCC = emitOverflowOp(I.getOpcode(), CarryMI.getDstReg(),
4826 CarryMI.getLHS(), CarryMI.getRHS(), MIB);
4827
4828 Register CarryOutReg = CarryMI.getCarryOutReg();
4829
4830 // Don't convert carry-out to VReg if it is never used
4831 if (MRI.use_nodbg_empty(CarryOutReg)) {
4832 OpAndCC.first->addRegisterDead(AArch64::NZCV, &TRI);
4833 } else {
4834 // Now, put the overflow result in the register given by the first operand
4835 // to the overflow op. CSINC increments the result when the predicate is
4836 // false, so to get the increment when it's true, we need to use the
4837 // inverse. In this case, we want to increment when carry is set.
4838 Register ZReg = AArch64::WZR;
4839 emitCSINC(/*Dst=*/CarryOutReg, /*Src1=*/ZReg, /*Src2=*/ZReg,
4840 getInvertedCondCode(OpAndCC.second), MIB);
4841 }
4842
4843 I.eraseFromParent();
4844 return true;
4845}
4846
4847std::pair<MachineInstr *, AArch64CC::CondCode>
4848AArch64InstructionSelector::emitOverflowOp(unsigned Opcode, Register Dst,
4849 MachineOperand &LHS,
4850 MachineOperand &RHS,
4851 MachineIRBuilder &MIRBuilder) const {
4852 switch (Opcode) {
4853 default:
4854 llvm_unreachable("Unexpected opcode!");
4855 case TargetOpcode::G_SADDO:
4856 return std::make_pair(emitADDS(Dst, LHS, RHS, MIRBuilder), AArch64CC::VS);
4857 case TargetOpcode::G_UADDO:
4858 return std::make_pair(emitADDS(Dst, LHS, RHS, MIRBuilder), AArch64CC::HS);
4859 case TargetOpcode::G_SSUBO:
4860 return std::make_pair(emitSUBS(Dst, LHS, RHS, MIRBuilder), AArch64CC::VS);
4861 case TargetOpcode::G_USUBO:
4862 return std::make_pair(emitSUBS(Dst, LHS, RHS, MIRBuilder), AArch64CC::LO);
4863 case TargetOpcode::G_SADDE:
4864 return std::make_pair(emitADCS(Dst, LHS, RHS, MIRBuilder), AArch64CC::VS);
4865 case TargetOpcode::G_UADDE:
4866 return std::make_pair(emitADCS(Dst, LHS, RHS, MIRBuilder), AArch64CC::HS);
4867 case TargetOpcode::G_SSUBE:
4868 return std::make_pair(emitSBCS(Dst, LHS, RHS, MIRBuilder), AArch64CC::VS);
4869 case TargetOpcode::G_USUBE:
4870 return std::make_pair(emitSBCS(Dst, LHS, RHS, MIRBuilder), AArch64CC::LO);
4871 }
4872}
4873
4874/// Returns true if @p Val is a tree of AND/OR/CMP operations that can be
4875/// expressed as a conjunction.
4876/// \param CanNegate Set to true if we can negate the whole sub-tree just by
4877/// changing the conditions on the CMP tests.
4878/// (this means we can call emitConjunctionRec() with
4879/// Negate==true on this sub-tree)
4880/// \param MustBeFirst Set to true if this subtree needs to be negated and we
4881/// cannot do the negation naturally. We are required to
4882/// emit the subtree first in this case.
4883/// \param WillNegate Is true if are called when the result of this
4884/// subexpression must be negated. This happens when the
4885/// outer expression is an OR. We can use this fact to know
4886/// that we have a double negation (or (or ...) ...) that
4887/// can be implemented for free.
4888static bool canEmitConjunction(Register Val, bool &CanNegate, bool &MustBeFirst,
4889 bool WillNegate, MachineRegisterInfo &MRI,
4890 unsigned Depth = 0) {
4891 if (!MRI.hasOneNonDBGUse(Val))
4892 return false;
4893 MachineInstr *ValDef = MRI.getVRegDef(Val);
4894 unsigned Opcode = ValDef->getOpcode();
4895 if (isa<GAnyCmp>(ValDef)) {
4896 CanNegate = true;
4897 MustBeFirst = false;
4898 return true;
4899 }
4900 // Protect against exponential runtime and stack overflow.
4901 if (Depth > 6)
4902 return false;
4903 if (Opcode == TargetOpcode::G_AND || Opcode == TargetOpcode::G_OR) {
4904 bool IsOR = Opcode == TargetOpcode::G_OR;
4905 Register O0 = ValDef->getOperand(1).getReg();
4906 Register O1 = ValDef->getOperand(2).getReg();
4907 bool CanNegateL;
4908 bool MustBeFirstL;
4909 if (!canEmitConjunction(O0, CanNegateL, MustBeFirstL, IsOR, MRI, Depth + 1))
4910 return false;
4911 bool CanNegateR;
4912 bool MustBeFirstR;
4913 if (!canEmitConjunction(O1, CanNegateR, MustBeFirstR, IsOR, MRI, Depth + 1))
4914 return false;
4915
4916 if (MustBeFirstL && MustBeFirstR)
4917 return false;
4918
4919 if (IsOR) {
4920 // For an OR expression we need to be able to naturally negate at least
4921 // one side or we cannot do the transformation at all.
4922 if (!CanNegateL && !CanNegateR)
4923 return false;
4924 // If we the result of the OR will be negated and we can naturally negate
4925 // the leaves, then this sub-tree as a whole negates naturally.
4926 CanNegate = WillNegate && CanNegateL && CanNegateR;
4927 // If we cannot naturally negate the whole sub-tree, then this must be
4928 // emitted first.
4929 MustBeFirst = !CanNegate;
4930 } else {
4931 assert(Opcode == TargetOpcode::G_AND && "Must be G_AND");
4932 // We cannot naturally negate an AND operation.
4933 CanNegate = false;
4934 MustBeFirst = MustBeFirstL || MustBeFirstR;
4935 }
4936 return true;
4937 }
4938 return false;
4939}
4940
4941MachineInstr *AArch64InstructionSelector::emitConditionalComparison(
4944 MachineIRBuilder &MIB) const {
4945 auto &MRI = *MIB.getMRI();
4946 LLT OpTy = MRI.getType(LHS);
4947 unsigned CCmpOpc;
4948 std::optional<ValueAndVReg> C;
4950 assert(OpTy.getSizeInBits() == 32 || OpTy.getSizeInBits() == 64);
4952 if (!C || C->Value.sgt(31) || C->Value.slt(-31))
4953 CCmpOpc = OpTy.getSizeInBits() == 32 ? AArch64::CCMPWr : AArch64::CCMPXr;
4954 else if (C->Value.ule(31))
4955 CCmpOpc = OpTy.getSizeInBits() == 32 ? AArch64::CCMPWi : AArch64::CCMPXi;
4956 else
4957 CCmpOpc = OpTy.getSizeInBits() == 32 ? AArch64::CCMNWi : AArch64::CCMNXi;
4958 } else {
4959 assert(OpTy.getSizeInBits() == 16 || OpTy.getSizeInBits() == 32 ||
4960 OpTy.getSizeInBits() == 64);
4961 switch (OpTy.getSizeInBits()) {
4962 case 16:
4963 assert(STI.hasFullFP16() && "Expected Full FP16 for fp16 comparisons");
4964 CCmpOpc = AArch64::FCCMPHrr;
4965 break;
4966 case 32:
4967 CCmpOpc = AArch64::FCCMPSrr;
4968 break;
4969 case 64:
4970 CCmpOpc = AArch64::FCCMPDrr;
4971 break;
4972 default:
4973 return nullptr;
4974 }
4975 }
4977 unsigned NZCV = AArch64CC::getNZCVToSatisfyCondCode(InvOutCC);
4978 auto CCmp =
4979 MIB.buildInstr(CCmpOpc, {}, {LHS});
4980 if (CCmpOpc == AArch64::CCMPWi || CCmpOpc == AArch64::CCMPXi)
4981 CCmp.addImm(C->Value.getZExtValue());
4982 else if (CCmpOpc == AArch64::CCMNWi || CCmpOpc == AArch64::CCMNXi)
4983 CCmp.addImm(C->Value.abs().getZExtValue());
4984 else
4985 CCmp.addReg(RHS);
4986 CCmp.addImm(NZCV).addImm(Predicate);
4988 return &*CCmp;
4989}
4990
4991MachineInstr *AArch64InstructionSelector::emitConjunctionRec(
4992 Register Val, AArch64CC::CondCode &OutCC, bool Negate, Register CCOp,
4993 AArch64CC::CondCode Predicate, MachineIRBuilder &MIB) const {
4994 // We're at a tree leaf, produce a conditional comparison operation.
4995 auto &MRI = *MIB.getMRI();
4996 MachineInstr *ValDef = MRI.getVRegDef(Val);
4997 unsigned Opcode = ValDef->getOpcode();
4998 if (auto *Cmp = dyn_cast<GAnyCmp>(ValDef)) {
4999 Register LHS = Cmp->getLHSReg();
5000 Register RHS = Cmp->getRHSReg();
5001 CmpInst::Predicate CC = Cmp->getCond();
5002 if (Negate)
5004 if (isa<GICmp>(Cmp)) {
5005 OutCC = changeICMPPredToAArch64CC(CC, RHS, MIB.getMRI());
5006 } else {
5007 // Handle special FP cases.
5008 AArch64CC::CondCode ExtraCC;
5009 changeFPCCToANDAArch64CC(CC, OutCC, ExtraCC);
5010 // Some floating point conditions can't be tested with a single condition
5011 // code. Construct an additional comparison in this case.
5012 if (ExtraCC != AArch64CC::AL) {
5013 MachineInstr *ExtraCmp;
5014 if (!CCOp)
5015 ExtraCmp = emitFPCompare(LHS, RHS, MIB, CC);
5016 else
5017 ExtraCmp =
5018 emitConditionalComparison(LHS, RHS, CC, Predicate, ExtraCC, MIB);
5019 CCOp = ExtraCmp->getOperand(0).getReg();
5020 Predicate = ExtraCC;
5021 }
5022 }
5023
5024 // Produce a normal comparison if we are first in the chain
5025 if (!CCOp) {
5026 if (isa<GICmp>(Cmp))
5027 return emitCMP(Cmp->getOperand(2), Cmp->getOperand(3), MIB);
5028 return emitFPCompare(Cmp->getOperand(2).getReg(),
5029 Cmp->getOperand(3).getReg(), MIB);
5030 }
5031 // Otherwise produce a ccmp.
5032 return emitConditionalComparison(LHS, RHS, CC, Predicate, OutCC, MIB);
5033 }
5034 assert(MRI.hasOneNonDBGUse(Val) && "Valid conjunction/disjunction tree");
5035
5036 bool IsOR = Opcode == TargetOpcode::G_OR;
5037
5038 Register LHS = ValDef->getOperand(1).getReg();
5039 bool CanNegateL;
5040 bool MustBeFirstL;
5041 bool ValidL = canEmitConjunction(LHS, CanNegateL, MustBeFirstL, IsOR, MRI);
5042 assert(ValidL && "Valid conjunction/disjunction tree");
5043 (void)ValidL;
5044
5045 Register RHS = ValDef->getOperand(2).getReg();
5046 bool CanNegateR;
5047 bool MustBeFirstR;
5048 bool ValidR = canEmitConjunction(RHS, CanNegateR, MustBeFirstR, IsOR, MRI);
5049 assert(ValidR && "Valid conjunction/disjunction tree");
5050 (void)ValidR;
5051
5052 // Swap sub-tree that must come first to the right side.
5053 if (MustBeFirstL) {
5054 assert(!MustBeFirstR && "Valid conjunction/disjunction tree");
5055 std::swap(LHS, RHS);
5056 std::swap(CanNegateL, CanNegateR);
5057 std::swap(MustBeFirstL, MustBeFirstR);
5058 }
5059
5060 bool NegateR;
5061 bool NegateAfterR;
5062 bool NegateL;
5063 bool NegateAfterAll;
5064 if (Opcode == TargetOpcode::G_OR) {
5065 // Swap the sub-tree that we can negate naturally to the left.
5066 if (!CanNegateL) {
5067 assert(CanNegateR && "at least one side must be negatable");
5068 assert(!MustBeFirstR && "invalid conjunction/disjunction tree");
5069 assert(!Negate);
5070 std::swap(LHS, RHS);
5071 NegateR = false;
5072 NegateAfterR = true;
5073 } else {
5074 // Negate the left sub-tree if possible, otherwise negate the result.
5075 NegateR = CanNegateR;
5076 NegateAfterR = !CanNegateR;
5077 }
5078 NegateL = true;
5079 NegateAfterAll = !Negate;
5080 } else {
5081 assert(Opcode == TargetOpcode::G_AND &&
5082 "Valid conjunction/disjunction tree");
5083 assert(!Negate && "Valid conjunction/disjunction tree");
5084
5085 NegateL = false;
5086 NegateR = false;
5087 NegateAfterR = false;
5088 NegateAfterAll = false;
5089 }
5090
5091 // Emit sub-trees.
5092 AArch64CC::CondCode RHSCC;
5093 MachineInstr *CmpR =
5094 emitConjunctionRec(RHS, RHSCC, NegateR, CCOp, Predicate, MIB);
5095 if (NegateAfterR)
5096 RHSCC = AArch64CC::getInvertedCondCode(RHSCC);
5097 MachineInstr *CmpL = emitConjunctionRec(
5098 LHS, OutCC, NegateL, CmpR->getOperand(0).getReg(), RHSCC, MIB);
5099 if (NegateAfterAll)
5100 OutCC = AArch64CC::getInvertedCondCode(OutCC);
5101 return CmpL;
5102}
5103
5104MachineInstr *AArch64InstructionSelector::emitConjunction(
5105 Register Val, AArch64CC::CondCode &OutCC, MachineIRBuilder &MIB) const {
5106 bool DummyCanNegate;
5107 bool DummyMustBeFirst;
5108 if (!canEmitConjunction(Val, DummyCanNegate, DummyMustBeFirst, false,
5109 *MIB.getMRI()))
5110 return nullptr;
5111 return emitConjunctionRec(Val, OutCC, false, Register(), AArch64CC::AL, MIB);
5112}
5113
5114bool AArch64InstructionSelector::tryOptSelectConjunction(GSelect &SelI,
5115 MachineInstr &CondMI) {
5116 AArch64CC::CondCode AArch64CC;
5117 MachineInstr *ConjMI = emitConjunction(SelI.getCondReg(), AArch64CC, MIB);
5118 if (!ConjMI)
5119 return false;
5120
5121 emitSelect(SelI.getReg(0), SelI.getTrueReg(), SelI.getFalseReg(), AArch64CC, MIB);
5122 SelI.eraseFromParent();
5123 return true;
5124}
5125
5126bool AArch64InstructionSelector::tryOptSelect(GSelect &I) {
5127 MachineRegisterInfo &MRI = *MIB.getMRI();
5128 // We want to recognize this pattern:
5129 //
5130 // $z = G_FCMP pred, $x, $y
5131 // ...
5132 // $w = G_SELECT $z, $a, $b
5133 //
5134 // Where the value of $z is *only* ever used by the G_SELECT (possibly with
5135 // some copies/truncs in between.)
5136 //
5137 // If we see this, then we can emit something like this:
5138 //
5139 // fcmp $x, $y
5140 // fcsel $w, $a, $b, pred
5141 //
5142 // Rather than emitting both of the rather long sequences in the standard
5143 // G_FCMP/G_SELECT select methods.
5144
5145 // First, check if the condition is defined by a compare.
5146 MachineInstr *CondDef = MRI.getVRegDef(I.getOperand(1).getReg());
5147
5148 // We can only fold if all of the defs have one use.
5149 Register CondDefReg = CondDef->getOperand(0).getReg();
5150 if (!MRI.hasOneNonDBGUse(CondDefReg)) {
5151 // Unless it's another select.
5152 for (const MachineInstr &UI : MRI.use_nodbg_instructions(CondDefReg)) {
5153 if (CondDef == &UI)
5154 continue;
5155 if (UI.getOpcode() != TargetOpcode::G_SELECT)
5156 return false;
5157 }
5158 }
5159
5160 // Is the condition defined by a compare?
5161 unsigned CondOpc = CondDef->getOpcode();
5162 if (CondOpc != TargetOpcode::G_ICMP && CondOpc != TargetOpcode::G_FCMP) {
5163 if (tryOptSelectConjunction(I, *CondDef))
5164 return true;
5165 return false;
5166 }
5167
5169 if (CondOpc == TargetOpcode::G_ICMP) {
5170 auto &PredOp = CondDef->getOperand(1);
5171 emitIntegerCompare(CondDef->getOperand(2), CondDef->getOperand(3), PredOp,
5172 MIB);
5173 auto Pred = static_cast<CmpInst::Predicate>(PredOp.getPredicate());
5174 CondCode =
5175 changeICMPPredToAArch64CC(Pred, CondDef->getOperand(3).getReg(), &MRI);
5176 } else {
5177 // Get the condition code for the select.
5178 auto Pred =
5179 static_cast<CmpInst::Predicate>(CondDef->getOperand(1).getPredicate());
5180 AArch64CC::CondCode CondCode2;
5181 changeFCMPPredToAArch64CC(Pred, CondCode, CondCode2);
5182
5183 // changeFCMPPredToAArch64CC sets CondCode2 to AL when we require two
5184 // instructions to emit the comparison.
5185 // TODO: Handle FCMP_UEQ and FCMP_ONE. After that, this check will be
5186 // unnecessary.
5187 if (CondCode2 != AArch64CC::AL)
5188 return false;
5189
5190 if (!emitFPCompare(CondDef->getOperand(2).getReg(),
5191 CondDef->getOperand(3).getReg(), MIB)) {
5192 LLVM_DEBUG(dbgs() << "Couldn't emit compare for select!\n");
5193 return false;
5194 }
5195 }
5196
5197 // Emit the select.
5198 emitSelect(I.getOperand(0).getReg(), I.getOperand(2).getReg(),
5199 I.getOperand(3).getReg(), CondCode, MIB);
5200 I.eraseFromParent();
5201 return true;
5202}
5203
5204MachineInstr *AArch64InstructionSelector::tryFoldIntegerCompare(
5205 MachineOperand &LHS, MachineOperand &RHS, MachineOperand &Predicate,
5206 MachineIRBuilder &MIRBuilder) const {
5207 assert(LHS.isReg() && RHS.isReg() && Predicate.isPredicate() &&
5208 "Unexpected MachineOperand");
5209 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
5210 // We want to find this sort of thing:
5211 // x = G_SUB 0, y
5212 // G_ICMP z, x
5213 //
5214 // In this case, we can fold the G_SUB into the G_ICMP using a CMN instead.
5215 // e.g:
5216 //
5217 // cmn z, y
5218
5219 // Check if the RHS or LHS of the G_ICMP is defined by a SUB
5220 MachineInstr *LHSDef = getDefIgnoringCopies(LHS.getReg(), MRI);
5221 MachineInstr *RHSDef = getDefIgnoringCopies(RHS.getReg(), MRI);
5222 auto P = static_cast<CmpInst::Predicate>(Predicate.getPredicate());
5223
5224 // Given this:
5225 //
5226 // x = G_SUB 0, y
5227 // G_ICMP z, x
5228 //
5229 // Produce this:
5230 //
5231 // cmn z, y
5232 if (isCMN(RHSDef, P, MRI))
5233 return emitCMN(LHS, RHSDef->getOperand(2), MIRBuilder);
5234
5235 // Same idea here, but with the LHS of the compare instead:
5236 //
5237 // Given this:
5238 //
5239 // x = G_SUB 0, y
5240 // G_ICMP x, z
5241 //
5242 // Produce this:
5243 //
5244 // cmn y, z
5245 //
5246 // But be careful! We need to swap the predicate!
5247 if (isCMN(LHSDef, P, MRI)) {
5248 if (!CmpInst::isEquality(P)) {
5251 }
5252 return emitCMN(LHSDef->getOperand(2), RHS, MIRBuilder);
5253 }
5254
5255 // Given this:
5256 //
5257 // z = G_AND x, y
5258 // G_ICMP z, 0
5259 //
5260 // Produce this if the compare is signed:
5261 //
5262 // tst x, y
5263 if (!CmpInst::isUnsigned(P) && LHSDef &&
5264 LHSDef->getOpcode() == TargetOpcode::G_AND) {
5265 // Make sure that the RHS is 0.
5266 auto ValAndVReg = getIConstantVRegValWithLookThrough(RHS.getReg(), MRI);
5267 if (!ValAndVReg || ValAndVReg->Value != 0)
5268 return nullptr;
5269
5270 return emitTST(LHSDef->getOperand(1),
5271 LHSDef->getOperand(2), MIRBuilder);
5272 }
5273
5274 return nullptr;
5275}
5276
5277bool AArch64InstructionSelector::selectShuffleVector(
5278 MachineInstr &I, MachineRegisterInfo &MRI) {
5279 const LLT DstTy = MRI.getType(I.getOperand(0).getReg());
5280 Register Src1Reg = I.getOperand(1).getReg();
5281 Register Src2Reg = I.getOperand(2).getReg();
5282 ArrayRef<int> Mask = I.getOperand(3).getShuffleMask();
5283 assert(DstTy == MRI.getType(Src1Reg) &&
5284 "Expected equal shuffle types during selection");
5285
5286 MachineBasicBlock &MBB = *I.getParent();
5287 MachineFunction &MF = *MBB.getParent();
5288 LLVMContext &Ctx = MF.getFunction().getContext();
5289
5290 unsigned BytesPerElt = DstTy.getElementType().getSizeInBits() / 8;
5291 int NumElts = DstTy.getNumElements();
5292
5293 SmallVector<int> NewMask;
5294 bool FirstUsed = false;
5295 bool SecondUsed = false;
5296 for (int M : Mask) {
5297 // Map any undef or zero lanes to 255.
5298 if (M < 0 || VT->getKnownBits(M < NumElts ? Src1Reg : Src2Reg,
5299 APInt::getOneBitSet(NumElts, M % NumElts))
5300 .isZero()) {
5301 for (unsigned Byte = 0; Byte < BytesPerElt; ++Byte)
5302 NewMask.push_back(255);
5303 continue;
5304 }
5305
5306 FirstUsed |= M < NumElts;
5307 SecondUsed |= M >= NumElts;
5308 for (unsigned Byte = 0; Byte < BytesPerElt; ++Byte) {
5309 unsigned Offset = Byte + M * BytesPerElt;
5310 NewMask.push_back(Offset);
5311 }
5312 }
5313
5314 // If the first is unused or all zeros, use the second src in a tbl1.
5315 if (!FirstUsed) {
5316 int ByteLanes = DstTy.getSizeInBits() == 128 ? 16 : 8;
5317 for (int &M : NewMask) {
5318 if (M != 255) {
5319 assert(M >= ByteLanes && M < 2 * ByteLanes);
5320 M -= ByteLanes;
5321 }
5322 }
5323 std::swap(Src1Reg, Src2Reg);
5324 std::swap(FirstUsed, SecondUsed);
5325 }
5326
5327 // Use a constant pool to load the index vector for TBL.
5329 transform(NewMask, std::back_inserter(CstIdxs), [&Ctx](int M) {
5330 return ConstantInt::get(Type::getInt8Ty(Ctx), M);
5331 });
5332 Constant *CPVal = ConstantVector::get(CstIdxs);
5333 MachineInstr *IndexLoad = emitLoadFromConstantPool(CPVal, MIB);
5334 if (!IndexLoad) {
5335 LLVM_DEBUG(dbgs() << "Could not load from a constant pool");
5336 return false;
5337 }
5338
5339 if (DstTy.getSizeInBits() != 128) {
5340 assert(DstTy.getSizeInBits() == 64 && "Unexpected shuffle result ty");
5341 // This case can be done with TBL1.
5342 MachineInstr *Concat =
5343 emitVectorConcat(std::nullopt, Src1Reg, Src2Reg, MIB);
5344 if (!Concat) {
5345 LLVM_DEBUG(dbgs() << "Could not do vector concat for tbl1");
5346 return false;
5347 }
5348
5349 // The constant pool load will be 64 bits, so need to convert to FPR128 reg.
5350 IndexLoad = emitScalarToVector(64, &AArch64::FPR128RegClass,
5351 IndexLoad->getOperand(0).getReg(), MIB);
5352
5353 auto TBL1 = MIB.buildInstr(
5354 AArch64::TBLv16i8One, {&AArch64::FPR128RegClass},
5355 {Concat->getOperand(0).getReg(), IndexLoad->getOperand(0).getReg()});
5357
5358 auto Copy =
5359 MIB.buildInstr(TargetOpcode::COPY, {I.getOperand(0).getReg()}, {})
5360 .addReg(TBL1.getReg(0), {}, AArch64::dsub);
5361 RBI.constrainGenericRegister(Copy.getReg(0), AArch64::FPR64RegClass, MRI);
5362 I.eraseFromParent();
5363 return true;
5364 }
5365
5366 if (!SecondUsed) {
5367 auto TBL1 = MIB.buildInstr(AArch64::TBLv16i8One, {I.getOperand(0)},
5368 {Src1Reg, IndexLoad->getOperand(0)});
5370 I.eraseFromParent();
5371 return true;
5372 }
5373
5374 // For TBL2 we need to emit a REG_SEQUENCE to tie together two consecutive
5375 // Q registers for regalloc.
5376 SmallVector<Register, 2> Regs = {Src1Reg, Src2Reg};
5377 auto RegSeq = createQTuple(Regs, MIB);
5378 auto TBL2 = MIB.buildInstr(AArch64::TBLv16i8Two, {I.getOperand(0)},
5379 {RegSeq, IndexLoad->getOperand(0)});
5381 I.eraseFromParent();
5382 return true;
5383}
5384
5385MachineInstr *AArch64InstructionSelector::emitLaneInsert(
5386 std::optional<Register> DstReg, Register SrcReg, Register EltReg,
5387 unsigned LaneIdx, const RegisterBank &RB,
5388 MachineIRBuilder &MIRBuilder) const {
5389 MachineInstr *InsElt = nullptr;
5390 const TargetRegisterClass *DstRC = &AArch64::FPR128RegClass;
5391 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
5392
5393 // Create a register to define with the insert if one wasn't passed in.
5394 if (!DstReg)
5395 DstReg = MRI.createVirtualRegister(DstRC);
5396
5397 unsigned EltSize = MRI.getType(EltReg).getSizeInBits();
5398 unsigned Opc = getInsertVecEltOpInfo(RB, EltSize).first;
5399
5400 if (RB.getID() == AArch64::FPRRegBankID) {
5401 auto InsSub = emitScalarToVector(EltSize, DstRC, EltReg, MIRBuilder);
5402 InsElt = MIRBuilder.buildInstr(Opc, {*DstReg}, {SrcReg})
5403 .addImm(LaneIdx)
5404 .addUse(InsSub->getOperand(0).getReg())
5405 .addImm(0);
5406 } else {
5407 InsElt = MIRBuilder.buildInstr(Opc, {*DstReg}, {SrcReg})
5408 .addImm(LaneIdx)
5409 .addUse(EltReg);
5410 }
5411
5413 return InsElt;
5414}
5415
5416bool AArch64InstructionSelector::selectUSMovFromExtend(
5417 MachineInstr &MI, MachineRegisterInfo &MRI) {
5418 if (MI.getOpcode() != TargetOpcode::G_SEXT &&
5419 MI.getOpcode() != TargetOpcode::G_ZEXT &&
5420 MI.getOpcode() != TargetOpcode::G_ANYEXT)
5421 return false;
5422 bool IsSigned = MI.getOpcode() == TargetOpcode::G_SEXT;
5423 const Register DefReg = MI.getOperand(0).getReg();
5424 const LLT DstTy = MRI.getType(DefReg);
5425 unsigned DstSize = DstTy.getSizeInBits();
5426
5427 if (DstSize != 32 && DstSize != 64)
5428 return false;
5429
5430 MachineInstr *Extract = getOpcodeDef(TargetOpcode::G_EXTRACT_VECTOR_ELT,
5431 MI.getOperand(1).getReg(), MRI);
5432 int64_t Lane;
5433 if (!Extract || !mi_match(Extract->getOperand(2).getReg(), MRI, m_ICst(Lane)))
5434 return false;
5435 Register Src0 = Extract->getOperand(1).getReg();
5436
5437 const LLT VecTy = MRI.getType(Src0);
5438 if (VecTy.isScalableVector())
5439 return false;
5440
5441 if (VecTy.getSizeInBits() != 128) {
5442 const MachineInstr *ScalarToVector = emitScalarToVector(
5443 VecTy.getSizeInBits(), &AArch64::FPR128RegClass, Src0, MIB);
5444 assert(ScalarToVector && "Didn't expect emitScalarToVector to fail!");
5445 Src0 = ScalarToVector->getOperand(0).getReg();
5446 }
5447
5448 unsigned Opcode;
5449 if (DstSize == 64 && VecTy.getScalarSizeInBits() == 32)
5450 Opcode = IsSigned ? AArch64::SMOVvi32to64 : AArch64::UMOVvi32;
5451 else if (DstSize == 64 && VecTy.getScalarSizeInBits() == 16)
5452 Opcode = IsSigned ? AArch64::SMOVvi16to64 : AArch64::UMOVvi16;
5453 else if (DstSize == 64 && VecTy.getScalarSizeInBits() == 8)
5454 Opcode = IsSigned ? AArch64::SMOVvi8to64 : AArch64::UMOVvi8;
5455 else if (DstSize == 32 && VecTy.getScalarSizeInBits() == 16)
5456 Opcode = IsSigned ? AArch64::SMOVvi16to32 : AArch64::UMOVvi16;
5457 else if (DstSize == 32 && VecTy.getScalarSizeInBits() == 8)
5458 Opcode = IsSigned ? AArch64::SMOVvi8to32 : AArch64::UMOVvi8;
5459 else
5460 llvm_unreachable("Unexpected type combo for S/UMov!");
5461
5462 // We may need to generate one of these, depending on the type and sign of the
5463 // input:
5464 // DstReg = SMOV Src0, Lane;
5465 // NewReg = UMOV Src0, Lane; DstReg = SUBREG_TO_REG NewReg, sub_32;
5466 MachineInstr *ExtI = nullptr;
5467 if (DstSize == 64 && !IsSigned) {
5468 Register NewReg = MRI.createVirtualRegister(&AArch64::GPR32RegClass);
5469 MIB.buildInstr(Opcode, {NewReg}, {Src0}).addImm(Lane);
5470 ExtI = MIB.buildInstr(AArch64::SUBREG_TO_REG, {DefReg}, {})
5471 .addUse(NewReg)
5472 .addImm(AArch64::sub_32);
5473 RBI.constrainGenericRegister(DefReg, AArch64::GPR64RegClass, MRI);
5474 } else
5475 ExtI = MIB.buildInstr(Opcode, {DefReg}, {Src0}).addImm(Lane);
5476
5478 MI.eraseFromParent();
5479 return true;
5480}
5481
5482bool AArch64InstructionSelector::selectIndexedExtLoad(
5483 MachineInstr &MI, MachineRegisterInfo &MRI) {
5484 auto &ExtLd = cast<GIndexedAnyExtLoad>(MI);
5485 Register Dst = ExtLd.getDstReg();
5486 Register WriteBack = ExtLd.getWritebackReg();
5487 Register Base = ExtLd.getBaseReg();
5488 Register Offset = ExtLd.getOffsetReg();
5489 LLT Ty = MRI.getType(Dst);
5490 assert(Ty.getSizeInBits() <= 64); // Only for scalar GPRs.
5491 unsigned MemSizeBits = ExtLd.getMMO().getMemoryType().getSizeInBits();
5492 bool IsPre = ExtLd.isPre();
5493 bool IsSExt = isa<GIndexedSExtLoad>(ExtLd);
5494 unsigned InsertIntoSubReg = 0;
5495 bool IsDst64 = Ty.getSizeInBits() == 64;
5496
5497 // ZExt/SExt should be on gpr but can handle extload and zextload of fpr, so
5498 // long as they are scalar.
5499 bool IsFPR = RBI.getRegBank(Dst, MRI, TRI)->getID() == AArch64::FPRRegBankID;
5500 if ((IsSExt && IsFPR) || Ty.isVector())
5501 return false;
5502
5503 unsigned Opc = 0;
5504 LLT NewLdDstTy;
5505 LLT s32 = LLT::scalar(32);
5506 LLT s64 = LLT::scalar(64);
5507
5508 if (MemSizeBits == 8) {
5509 if (IsSExt) {
5510 if (IsDst64)
5511 Opc = IsPre ? AArch64::LDRSBXpre : AArch64::LDRSBXpost;
5512 else
5513 Opc = IsPre ? AArch64::LDRSBWpre : AArch64::LDRSBWpost;
5514 NewLdDstTy = IsDst64 ? s64 : s32;
5515 } else if (IsFPR) {
5516 Opc = IsPre ? AArch64::LDRBpre : AArch64::LDRBpost;
5517 InsertIntoSubReg = AArch64::bsub;
5518 NewLdDstTy = LLT::scalar(MemSizeBits);
5519 } else {
5520 Opc = IsPre ? AArch64::LDRBBpre : AArch64::LDRBBpost;
5521 InsertIntoSubReg = IsDst64 ? AArch64::sub_32 : 0;
5522 NewLdDstTy = s32;
5523 }
5524 } else if (MemSizeBits == 16) {
5525 if (IsSExt) {
5526 if (IsDst64)
5527 Opc = IsPre ? AArch64::LDRSHXpre : AArch64::LDRSHXpost;
5528 else
5529 Opc = IsPre ? AArch64::LDRSHWpre : AArch64::LDRSHWpost;
5530 NewLdDstTy = IsDst64 ? s64 : s32;
5531 } else if (IsFPR) {
5532 Opc = IsPre ? AArch64::LDRHpre : AArch64::LDRHpost;
5533 InsertIntoSubReg = AArch64::hsub;
5534 NewLdDstTy = LLT::scalar(MemSizeBits);
5535 } else {
5536 Opc = IsPre ? AArch64::LDRHHpre : AArch64::LDRHHpost;
5537 InsertIntoSubReg = IsDst64 ? AArch64::sub_32 : 0;
5538 NewLdDstTy = s32;
5539 }
5540 } else if (MemSizeBits == 32) {
5541 if (IsSExt) {
5542 Opc = IsPre ? AArch64::LDRSWpre : AArch64::LDRSWpost;
5543 NewLdDstTy = s64;
5544 } else if (IsFPR) {
5545 Opc = IsPre ? AArch64::LDRSpre : AArch64::LDRSpost;
5546 InsertIntoSubReg = AArch64::ssub;
5547 NewLdDstTy = LLT::scalar(MemSizeBits);
5548 } else {
5549 Opc = IsPre ? AArch64::LDRWpre : AArch64::LDRWpost;
5550 InsertIntoSubReg = IsDst64 ? AArch64::sub_32 : 0;
5551 NewLdDstTy = s32;
5552 }
5553 } else {
5554 llvm_unreachable("Unexpected size for indexed load");
5555 }
5556
5557 auto Cst = getIConstantVRegVal(Offset, MRI);
5558 if (!Cst)
5559 return false; // Shouldn't happen, but just in case.
5560
5561 auto LdMI = MIB.buildInstr(Opc, {WriteBack, NewLdDstTy}, {Base})
5562 .addImm(Cst->getSExtValue());
5563 LdMI.cloneMemRefs(ExtLd);
5565 // Make sure to select the load with the MemTy as the dest type, and then
5566 // insert into a larger reg if needed.
5567 if (InsertIntoSubReg) {
5568 // Generate a SUBREG_TO_REG.
5569 auto SubToReg = MIB.buildInstr(TargetOpcode::SUBREG_TO_REG, {Dst}, {})
5570 .addUse(LdMI.getReg(1))
5571 .addImm(InsertIntoSubReg);
5573 SubToReg.getReg(0),
5574 *getRegClassForTypeOnBank(MRI.getType(Dst),
5575 *RBI.getRegBank(Dst, MRI, TRI)),
5576 MRI);
5577 } else {
5578 auto Copy = MIB.buildCopy(Dst, LdMI.getReg(1));
5579 selectCopy(*Copy, TII, MRI, TRI, RBI);
5580 }
5581 MI.eraseFromParent();
5582
5583 return true;
5584}
5585
5586bool AArch64InstructionSelector::selectIndexedLoad(MachineInstr &MI,
5587 MachineRegisterInfo &MRI) {
5588 auto &Ld = cast<GIndexedLoad>(MI);
5589 Register Dst = Ld.getDstReg();
5590 Register WriteBack = Ld.getWritebackReg();
5591 Register Base = Ld.getBaseReg();
5592 Register Offset = Ld.getOffsetReg();
5593 assert(MRI.getType(Dst).getSizeInBits() <= 128 &&
5594 "Unexpected type for indexed load");
5595 unsigned MemSize = Ld.getMMO().getMemoryType().getSizeInBytes();
5596
5597 if (MemSize < MRI.getType(Dst).getSizeInBytes())
5598 return selectIndexedExtLoad(MI, MRI);
5599
5600 unsigned Opc = 0;
5601 if (Ld.isPre()) {
5602 static constexpr unsigned GPROpcodes[] = {
5603 AArch64::LDRBBpre, AArch64::LDRHHpre, AArch64::LDRWpre,
5604 AArch64::LDRXpre};
5605 static constexpr unsigned FPROpcodes[] = {
5606 AArch64::LDRBpre, AArch64::LDRHpre, AArch64::LDRSpre, AArch64::LDRDpre,
5607 AArch64::LDRQpre};
5608 Opc = (RBI.getRegBank(Dst, MRI, TRI)->getID() == AArch64::FPRRegBankID)
5609 ? FPROpcodes[Log2_32(MemSize)]
5610 : GPROpcodes[Log2_32(MemSize)];
5611 ;
5612 } else {
5613 static constexpr unsigned GPROpcodes[] = {
5614 AArch64::LDRBBpost, AArch64::LDRHHpost, AArch64::LDRWpost,
5615 AArch64::LDRXpost};
5616 static constexpr unsigned FPROpcodes[] = {
5617 AArch64::LDRBpost, AArch64::LDRHpost, AArch64::LDRSpost,
5618 AArch64::LDRDpost, AArch64::LDRQpost};
5619 Opc = (RBI.getRegBank(Dst, MRI, TRI)->getID() == AArch64::FPRRegBankID)
5620 ? FPROpcodes[Log2_32(MemSize)]
5621 : GPROpcodes[Log2_32(MemSize)];
5622 ;
5623 }
5624 auto Cst = getIConstantVRegVal(Offset, MRI);
5625 if (!Cst)
5626 return false; // Shouldn't happen, but just in case.
5627 auto LdMI =
5628 MIB.buildInstr(Opc, {WriteBack, Dst}, {Base}).addImm(Cst->getSExtValue());
5629 LdMI.cloneMemRefs(Ld);
5631 MI.eraseFromParent();
5632 return true;
5633}
5634
5635bool AArch64InstructionSelector::selectIndexedStore(GIndexedStore &I,
5636 MachineRegisterInfo &MRI) {
5637 Register Dst = I.getWritebackReg();
5638 Register Val = I.getValueReg();
5639 Register Base = I.getBaseReg();
5640 Register Offset = I.getOffsetReg();
5641 assert(MRI.getType(Val).getSizeInBits() <= 128 &&
5642 "Unexpected type for indexed store");
5643
5644 LocationSize MemSize = I.getMMO().getSize();
5645 unsigned MemSizeInBytes = MemSize.getValue();
5646
5647 assert(MemSizeInBytes && MemSizeInBytes <= 16 &&
5648 "Unexpected indexed store size");
5649 unsigned MemSizeLog2 = Log2_32(MemSizeInBytes);
5650
5651 unsigned Opc = 0;
5652 if (I.isPre()) {
5653 static constexpr unsigned GPROpcodes[] = {
5654 AArch64::STRBBpre, AArch64::STRHHpre, AArch64::STRWpre,
5655 AArch64::STRXpre};
5656 static constexpr unsigned FPROpcodes[] = {
5657 AArch64::STRBpre, AArch64::STRHpre, AArch64::STRSpre, AArch64::STRDpre,
5658 AArch64::STRQpre};
5659
5660 if (RBI.getRegBank(Val, MRI, TRI)->getID() == AArch64::FPRRegBankID)
5661 Opc = FPROpcodes[MemSizeLog2];
5662 else
5663 Opc = GPROpcodes[MemSizeLog2];
5664 } else {
5665 static constexpr unsigned GPROpcodes[] = {
5666 AArch64::STRBBpost, AArch64::STRHHpost, AArch64::STRWpost,
5667 AArch64::STRXpost};
5668 static constexpr unsigned FPROpcodes[] = {
5669 AArch64::STRBpost, AArch64::STRHpost, AArch64::STRSpost,
5670 AArch64::STRDpost, AArch64::STRQpost};
5671
5672 if (RBI.getRegBank(Val, MRI, TRI)->getID() == AArch64::FPRRegBankID)
5673 Opc = FPROpcodes[MemSizeLog2];
5674 else
5675 Opc = GPROpcodes[MemSizeLog2];
5676 }
5677
5678 auto Cst = getIConstantVRegVal(Offset, MRI);
5679 if (!Cst)
5680 return false; // Shouldn't happen, but just in case.
5681 auto Str =
5682 MIB.buildInstr(Opc, {Dst}, {Val, Base}).addImm(Cst->getSExtValue());
5683 Str.cloneMemRefs(I);
5685 I.eraseFromParent();
5686 return true;
5687}
5688
5689MachineInstr *
5690AArch64InstructionSelector::emitConstantMOVVector(DstOp Dst, APInt Imm,
5691 MachineRegisterInfo &MRI) {
5692 unsigned DstSize = Imm.getBitWidth();
5693 assert((DstSize == 64 || DstSize == 128) &&
5694 "Unexpected vector constant size");
5695
5697 if (AArch64_IMM::expandVectorMOVImm(Imm, Insns, STI)) {
5698 for (AArch64_IMM::ImmInsnModel Insn : Insns) {
5699 switch (Insn.Opcode) {
5700 case AArch64::FMOVD0: {
5701 // Currently emit a MOVIv2d_ns in both cases to match SDAG.
5702 auto Mov =
5703 MIB.buildInstr(
5704 AArch64::MOVIv2d_ns,
5705 {DstSize == 128 ? Dst : DstOp(&AArch64::FPR128RegClass)}, {})
5706 .addImm(0);
5708 if (DstSize != 128) {
5709 Mov = MIB.buildInstr(TargetOpcode::COPY, {Dst}, {})
5710 .addReg(Mov.getReg(0), {}, AArch64::dsub);
5711 RBI.constrainGenericRegister(Mov.getReg(0), AArch64::FPR64RegClass,
5712 MRI);
5713 }
5714 return &*Mov;
5715 }
5716 case AArch64::FMOVDi:
5717 case AArch64::FMOVv2f32_ns:
5718 case AArch64::FMOVv2f64_ns:
5719 case AArch64::FMOVv4f32_ns:
5720 case AArch64::FMOVv4f16_ns:
5721 case AArch64::FMOVv8f16_ns:
5722 case AArch64::MOVID:
5723 case AArch64::MOVIv16b_ns:
5724 case AArch64::MOVIv2d_ns:
5725 case AArch64::MOVIv2i32:
5726 case AArch64::MOVIv2s_msl:
5727 case AArch64::MOVIv4i16:
5728 case AArch64::MOVIv4i32:
5729 case AArch64::MOVIv4s_msl:
5730 case AArch64::MOVIv8b_ns:
5731 case AArch64::MOVIv8i16:
5732 case AArch64::MVNIv2i32:
5733 case AArch64::MVNIv2s_msl:
5734 case AArch64::MVNIv4i16:
5735 case AArch64::MVNIv4i32:
5736 case AArch64::MVNIv4s_msl:
5737 case AArch64::MVNIv8i16: {
5738 auto Mov = MIB.buildInstr(Insn.Opcode, {Dst}, {});
5739 if (Insn.Op1)
5740 Mov.addImm(*Insn.Op1);
5741 if (Insn.Op2)
5742 Mov.addImm(*Insn.Op2);
5744 return &*Mov;
5745 }
5746 case AArch64::DUPM_ZI: {
5747 auto Mov = MIB.buildInstr(Insn.Opcode, {&AArch64::ZPRRegClass}, {})
5748 .addImm(*Insn.Op1);
5750 Mov = MIB.buildInstr(TargetOpcode::COPY, {Dst}, {})
5751 .addReg(Mov.getReg(0), {},
5752 DstSize == 64 ? AArch64::dsub : AArch64::zsub);
5753 RBI.constrainGenericRegister(Mov.getReg(0),
5754 DstSize == 64 ? AArch64::FPR64RegClass
5755 : AArch64::FPR128RegClass,
5756 MRI);
5757 return &*Mov;
5758 }
5759 case AArch64::DUP_ZI_D: {
5760 auto Mov = MIB.buildInstr(Insn.Opcode, {&AArch64::ZPRRegClass}, {})
5761 .addImm(*Insn.Op1)
5762 .addImm(*Insn.Op2);
5764 Mov = MIB.buildInstr(TargetOpcode::COPY, {Dst}, {})
5765 .addReg(Mov.getReg(0), {},
5766 DstSize == 64 ? AArch64::dsub : AArch64::zsub);
5767 RBI.constrainGenericRegister(Mov.getReg(0),
5768 DstSize == 64 ? AArch64::FPR64RegClass
5769 : AArch64::FPR128RegClass,
5770 MRI);
5771 return &*Mov;
5772 }
5773 default:
5774 llvm_unreachable("Unexpected node in expandVectorMOVImm\n");
5775 }
5776 }
5777 }
5778 return nullptr;
5779}
5780
5781MachineInstr *AArch64InstructionSelector::emitConstantVector(
5782 Register Dst, Constant *CV, APInt Imm, MachineRegisterInfo &MRI) {
5783 if (auto *MovI = emitConstantMOVVector(Dst, Imm, MRI))
5784 return MovI;
5785
5786 auto *CPLoad = emitLoadFromConstantPool(CV, MIB);
5787 if (!CPLoad) {
5788 LLVM_DEBUG(dbgs() << "Could not generate cp load for constant vector!");
5789 return nullptr;
5790 }
5791
5792 auto Copy = MIB.buildCopy(Dst, CPLoad->getOperand(0));
5794 Dst, *MRI.getRegClass(CPLoad->getOperand(0).getReg()), MRI);
5795 return &*Copy;
5796}
5797
5798bool AArch64InstructionSelector::tryOptConstantBuildVec(
5799 MachineInstr &I, LLT DstTy, MachineRegisterInfo &MRI) {
5800 assert(I.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
5801 unsigned DstSize = DstTy.getSizeInBits();
5802 assert(DstSize <= 128 && "Unexpected build_vec type!");
5803 if (DstSize < 32)
5804 return false;
5805 // Check if we're building a constant vector, in which case we want to
5806 // generate a constant pool load instead of a vector insert sequence.
5808 APInt Imm(DstSize, 0);
5809 for (unsigned Idx = 1; Idx < I.getNumOperands(); ++Idx) {
5810 Register OpReg = I.getOperand(Idx).getReg();
5811 if (auto AnyConst = getAnyConstantVRegValWithLookThrough(
5812 OpReg, MRI, /*LookThroughInstrs=*/true,
5813 /*LookThroughAnyExt=*/true)) {
5814 MachineInstr *DefMI = MRI.getVRegDef(AnyConst->VReg);
5815 Imm |= AnyConst->Value.trunc(DstTy.getScalarSizeInBits())
5816 .zext(DstSize)
5817 .shl((Idx - 1) * DstTy.getScalarSizeInBits());
5818
5819 if (DefMI->getOpcode() == TargetOpcode::G_CONSTANT) {
5820 Csts.emplace_back(
5821 ConstantInt::get(MIB.getMF().getFunction().getContext(),
5822 std::move(AnyConst->Value)));
5823 continue;
5824 }
5825
5826 if (DefMI->getOpcode() == TargetOpcode::G_FCONSTANT) {
5827 Csts.emplace_back(
5828 const_cast<ConstantFP *>(DefMI->getOperand(1).getFPImm()));
5829 continue;
5830 }
5831 }
5832 return false;
5833 }
5834 Constant *CV = ConstantVector::get(Csts);
5835 if (!emitConstantVector(I.getOperand(0).getReg(), CV, Imm, MRI))
5836 return false;
5837 I.eraseFromParent();
5838 return true;
5839}
5840
5841bool AArch64InstructionSelector::tryOptBuildVecToSubregToReg(
5842 MachineInstr &I, MachineRegisterInfo &MRI) {
5843 // Given:
5844 // %vec = G_BUILD_VECTOR %elt, %undef, %undef, ... %undef
5845 //
5846 // Select the G_BUILD_VECTOR as a SUBREG_TO_REG from %elt.
5847 Register Dst = I.getOperand(0).getReg();
5848 Register EltReg = I.getOperand(1).getReg();
5849 LLT EltTy = MRI.getType(EltReg);
5850 // If the index isn't on the same bank as its elements, then this can't be a
5851 // SUBREG_TO_REG.
5852 const RegisterBank &EltRB = *RBI.getRegBank(EltReg, MRI, TRI);
5853 const RegisterBank &DstRB = *RBI.getRegBank(Dst, MRI, TRI);
5854 if (EltRB != DstRB)
5855 return false;
5856 if (any_of(drop_begin(I.operands(), 2), [&MRI](const MachineOperand &Op) {
5857 return !getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Op.getReg(), MRI);
5858 }))
5859 return false;
5860 unsigned SubReg;
5861 const TargetRegisterClass *EltRC = getRegClassForTypeOnBank(EltTy, EltRB);
5862 if (!EltRC)
5863 return false;
5864 const TargetRegisterClass *DstRC =
5865 getRegClassForTypeOnBank(MRI.getType(Dst), DstRB);
5866 if (!DstRC)
5867 return false;
5868 if (!getSubRegForClass(EltRC, TRI, SubReg))
5869 return false;
5870 auto SubregToReg = MIB.buildInstr(AArch64::SUBREG_TO_REG, {Dst}, {})
5871 .addUse(EltReg)
5872 .addImm(SubReg);
5873 I.eraseFromParent();
5874 constrainSelectedInstRegOperands(*SubregToReg, TII, TRI, RBI);
5875 return RBI.constrainGenericRegister(Dst, *DstRC, MRI);
5876}
5877
5878bool AArch64InstructionSelector::selectBuildVector(MachineInstr &I,
5879 MachineRegisterInfo &MRI) {
5880 assert(I.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
5881 // Until we port more of the optimized selections, for now just use a vector
5882 // insert sequence.
5883 const LLT DstTy = MRI.getType(I.getOperand(0).getReg());
5884 const LLT EltTy = MRI.getType(I.getOperand(1).getReg());
5885 unsigned EltSize = EltTy.getSizeInBits();
5886
5887 if (tryOptConstantBuildVec(I, DstTy, MRI))
5888 return true;
5889 if (tryOptBuildVecToSubregToReg(I, MRI))
5890 return true;
5891
5892 if (EltSize != 8 && EltSize != 16 && EltSize != 32 && EltSize != 64)
5893 return false; // Don't support all element types yet.
5894 const RegisterBank &RB = *RBI.getRegBank(I.getOperand(1).getReg(), MRI, TRI);
5895
5896 const TargetRegisterClass *DstRC = &AArch64::FPR128RegClass;
5897 MachineInstr *ScalarToVec =
5898 emitScalarToVector(DstTy.getElementType().getSizeInBits(), DstRC,
5899 I.getOperand(1).getReg(), MIB);
5900 if (!ScalarToVec)
5901 return false;
5902
5903 Register DstVec = ScalarToVec->getOperand(0).getReg();
5904 unsigned DstSize = DstTy.getSizeInBits();
5905
5906 // Keep track of the last MI we inserted. Later on, we might be able to save
5907 // a copy using it.
5908 MachineInstr *PrevMI = ScalarToVec;
5909 for (unsigned i = 2, e = DstSize / EltSize + 1; i < e; ++i) {
5910 // Note that if we don't do a subregister copy, we can end up making an
5911 // extra register.
5912 Register OpReg = I.getOperand(i).getReg();
5913 // Do not emit inserts for undefs
5914 if (!getOpcodeDef<GImplicitDef>(OpReg, MRI)) {
5915 PrevMI = &*emitLaneInsert(std::nullopt, DstVec, OpReg, i - 1, RB, MIB);
5916 DstVec = PrevMI->getOperand(0).getReg();
5917 }
5918 }
5919
5920 // If DstTy's size in bits is less than 128, then emit a subregister copy
5921 // from DstVec to the last register we've defined.
5922 if (DstSize < 128) {
5923 // Force this to be FPR using the destination vector.
5924 const TargetRegisterClass *RC =
5925 getRegClassForTypeOnBank(DstTy, *RBI.getRegBank(DstVec, MRI, TRI));
5926 if (!RC)
5927 return false;
5928 if (RC != &AArch64::FPR32RegClass && RC != &AArch64::FPR64RegClass) {
5929 LLVM_DEBUG(dbgs() << "Unsupported register class!\n");
5930 return false;
5931 }
5932
5933 unsigned SubReg = 0;
5934 if (!getSubRegForClass(RC, TRI, SubReg))
5935 return false;
5936 if (SubReg != AArch64::ssub && SubReg != AArch64::dsub) {
5937 LLVM_DEBUG(dbgs() << "Unsupported destination size! (" << DstSize
5938 << "\n");
5939 return false;
5940 }
5941
5943 Register DstReg = I.getOperand(0).getReg();
5944
5945 MIB.buildInstr(TargetOpcode::COPY, {DstReg}, {}).addReg(DstVec, {}, SubReg);
5946 MachineOperand &RegOp = I.getOperand(1);
5947 RegOp.setReg(Reg);
5948 RBI.constrainGenericRegister(DstReg, *RC, MRI);
5949 } else {
5950 // We either have a vector with all elements (except the first one) undef or
5951 // at least one non-undef non-first element. In the first case, we need to
5952 // constrain the output register ourselves as we may have generated an
5953 // INSERT_SUBREG operation which is a generic operation for which the
5954 // output regclass cannot be automatically chosen.
5955 //
5956 // In the second case, there is no need to do this as it may generate an
5957 // instruction like INSvi32gpr where the regclass can be automatically
5958 // chosen.
5959 //
5960 // Also, we save a copy by re-using the destination register on the final
5961 // insert.
5962 PrevMI->getOperand(0).setReg(I.getOperand(0).getReg());
5964
5965 Register DstReg = PrevMI->getOperand(0).getReg();
5966 if (PrevMI == ScalarToVec && DstReg.isVirtual()) {
5967 const TargetRegisterClass *RC =
5968 getRegClassForTypeOnBank(DstTy, *RBI.getRegBank(DstVec, MRI, TRI));
5969 RBI.constrainGenericRegister(DstReg, *RC, MRI);
5970 }
5971 }
5972
5974 return true;
5975}
5976
5977bool AArch64InstructionSelector::selectVectorLoadIntrinsic(unsigned Opc,
5978 unsigned NumVecs,
5979 MachineInstr &I) {
5980 assert(I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS);
5981 assert(Opc && "Expected an opcode?");
5982 assert(NumVecs > 1 && NumVecs < 5 && "Only support 2, 3, or 4 vectors");
5983 auto &MRI = *MIB.getMRI();
5984 LLT Ty = MRI.getType(I.getOperand(0).getReg());
5985 unsigned Size = Ty.getSizeInBits();
5986 assert((Size == 64 || Size == 128) &&
5987 "Destination must be 64 bits or 128 bits?");
5988 unsigned SubReg = Size == 64 ? AArch64::dsub0 : AArch64::qsub0;
5989 auto Ptr = I.getOperand(I.getNumOperands() - 1).getReg();
5990 assert(MRI.getType(Ptr).isPointer() && "Expected a pointer type?");
5991 auto Load = MIB.buildInstr(Opc, {Ty}, {Ptr});
5994 Register SelectedLoadDst = Load->getOperand(0).getReg();
5995 for (unsigned Idx = 0; Idx < NumVecs; ++Idx) {
5996 auto Vec = MIB.buildInstr(TargetOpcode::COPY, {I.getOperand(Idx)}, {})
5997 .addReg(SelectedLoadDst, {}, SubReg + Idx);
5998 // Emit the subreg copies and immediately select them.
5999 // FIXME: We should refactor our copy code into an emitCopy helper and
6000 // clean up uses of this pattern elsewhere in the selector.
6001 selectCopy(*Vec, TII, MRI, TRI, RBI);
6002 }
6003 return true;
6004}
6005
6006bool AArch64InstructionSelector::selectVectorLoadLaneIntrinsic(
6007 unsigned Opc, unsigned NumVecs, MachineInstr &I) {
6008 assert(I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS);
6009 assert(Opc && "Expected an opcode?");
6010 assert(NumVecs > 1 && NumVecs < 5 && "Only support 2, 3, or 4 vectors");
6011 auto &MRI = *MIB.getMRI();
6012 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6013 bool Narrow = Ty.getSizeInBits() == 64;
6014
6015 auto FirstSrcRegIt = I.operands_begin() + NumVecs + 1;
6016 SmallVector<Register, 4> Regs(NumVecs);
6017 std::transform(FirstSrcRegIt, FirstSrcRegIt + NumVecs, Regs.begin(),
6018 [](auto MO) { return MO.getReg(); });
6019
6020 if (Narrow) {
6021 transform(Regs, Regs.begin(), [this](Register Reg) {
6022 return emitScalarToVector(64, &AArch64::FPR128RegClass, Reg, MIB)
6023 ->getOperand(0)
6024 .getReg();
6025 });
6026 Ty = Ty.multiplyElements(2);
6027 }
6028
6029 Register Tuple = createQTuple(Regs, MIB);
6030 auto LaneNo = getIConstantVRegVal((FirstSrcRegIt + NumVecs)->getReg(), MRI);
6031 if (!LaneNo)
6032 return false;
6033
6034 Register Ptr = (FirstSrcRegIt + NumVecs + 1)->getReg();
6035 auto Load = MIB.buildInstr(Opc, {Ty}, {})
6036 .addReg(Tuple)
6037 .addImm(LaneNo->getZExtValue())
6038 .addReg(Ptr);
6041 Register SelectedLoadDst = Load->getOperand(0).getReg();
6042 unsigned SubReg = AArch64::qsub0;
6043 for (unsigned Idx = 0; Idx < NumVecs; ++Idx) {
6044 auto Vec = MIB.buildInstr(TargetOpcode::COPY,
6045 {Narrow ? DstOp(&AArch64::FPR128RegClass)
6046 : DstOp(I.getOperand(Idx).getReg())},
6047 {})
6048 .addReg(SelectedLoadDst, {}, SubReg + Idx);
6049 Register WideReg = Vec.getReg(0);
6050 // Emit the subreg copies and immediately select them.
6051 selectCopy(*Vec, TII, MRI, TRI, RBI);
6052 if (Narrow &&
6053 !emitNarrowVector(I.getOperand(Idx).getReg(), WideReg, MIB, MRI))
6054 return false;
6055 }
6056 return true;
6057}
6058
6059void AArch64InstructionSelector::selectVectorStoreIntrinsic(MachineInstr &I,
6060 unsigned NumVecs,
6061 unsigned Opc) {
6062 MachineRegisterInfo &MRI = I.getParent()->getParent()->getRegInfo();
6063 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6064 Register Ptr = I.getOperand(1 + NumVecs).getReg();
6065
6066 SmallVector<Register, 2> Regs(NumVecs);
6067 std::transform(I.operands_begin() + 1, I.operands_begin() + 1 + NumVecs,
6068 Regs.begin(), [](auto MO) { return MO.getReg(); });
6069
6070 Register Tuple = Ty.getSizeInBits() == 128 ? createQTuple(Regs, MIB)
6071 : createDTuple(Regs, MIB);
6072 auto Store = MIB.buildInstr(Opc, {}, {Tuple, Ptr});
6075}
6076
6077bool AArch64InstructionSelector::selectVectorStoreLaneIntrinsic(
6078 MachineInstr &I, unsigned NumVecs, unsigned Opc) {
6079 MachineRegisterInfo &MRI = I.getParent()->getParent()->getRegInfo();
6080 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6081 bool Narrow = Ty.getSizeInBits() == 64;
6082
6083 SmallVector<Register, 2> Regs(NumVecs);
6084 std::transform(I.operands_begin() + 1, I.operands_begin() + 1 + NumVecs,
6085 Regs.begin(), [](auto MO) { return MO.getReg(); });
6086
6087 if (Narrow)
6088 transform(Regs, Regs.begin(), [this](Register Reg) {
6089 return emitScalarToVector(64, &AArch64::FPR128RegClass, Reg, MIB)
6090 ->getOperand(0)
6091 .getReg();
6092 });
6093
6094 Register Tuple = createQTuple(Regs, MIB);
6095
6096 auto LaneNo = getIConstantVRegVal(I.getOperand(1 + NumVecs).getReg(), MRI);
6097 if (!LaneNo)
6098 return false;
6099 Register Ptr = I.getOperand(1 + NumVecs + 1).getReg();
6100 auto Store = MIB.buildInstr(Opc, {}, {})
6101 .addReg(Tuple)
6102 .addImm(LaneNo->getZExtValue())
6103 .addReg(Ptr);
6106 return true;
6107}
6108
6109bool AArch64InstructionSelector::selectIntrinsicWithSideEffects(
6110 MachineInstr &I, MachineRegisterInfo &MRI) {
6111 // Find the intrinsic ID.
6112 unsigned IntrinID = cast<GIntrinsic>(I).getIntrinsicID();
6113
6114 const LLT S8 = LLT::scalar(8);
6115 const LLT S16 = LLT::scalar(16);
6116 const LLT S32 = LLT::scalar(32);
6117 const LLT S64 = LLT::scalar(64);
6118 const LLT P0 = LLT::pointer(0, 64);
6119 // Select the instruction.
6120 switch (IntrinID) {
6121 default:
6122 return false;
6123 case Intrinsic::aarch64_ldxp:
6124 case Intrinsic::aarch64_ldaxp: {
6125 auto NewI = MIB.buildInstr(
6126 IntrinID == Intrinsic::aarch64_ldxp ? AArch64::LDXPX : AArch64::LDAXPX,
6127 {I.getOperand(0).getReg(), I.getOperand(1).getReg()},
6128 {I.getOperand(3)});
6129 NewI.cloneMemRefs(I);
6131 break;
6132 }
6133 case Intrinsic::aarch64_neon_ld1x2: {
6134 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6135 unsigned Opc = 0;
6136 if (Ty == LLT::fixed_vector(8, S8))
6137 Opc = AArch64::LD1Twov8b;
6138 else if (Ty == LLT::fixed_vector(16, S8))
6139 Opc = AArch64::LD1Twov16b;
6140 else if (Ty == LLT::fixed_vector(4, S16))
6141 Opc = AArch64::LD1Twov4h;
6142 else if (Ty == LLT::fixed_vector(8, S16))
6143 Opc = AArch64::LD1Twov8h;
6144 else if (Ty == LLT::fixed_vector(2, S32))
6145 Opc = AArch64::LD1Twov2s;
6146 else if (Ty == LLT::fixed_vector(4, S32))
6147 Opc = AArch64::LD1Twov4s;
6148 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6149 Opc = AArch64::LD1Twov2d;
6150 else if (Ty == S64 || Ty == P0)
6151 Opc = AArch64::LD1Twov1d;
6152 else
6153 llvm_unreachable("Unexpected type for ld1x2!");
6154 selectVectorLoadIntrinsic(Opc, 2, I);
6155 break;
6156 }
6157 case Intrinsic::aarch64_neon_ld1x3: {
6158 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6159 unsigned Opc = 0;
6160 if (Ty == LLT::fixed_vector(8, S8))
6161 Opc = AArch64::LD1Threev8b;
6162 else if (Ty == LLT::fixed_vector(16, S8))
6163 Opc = AArch64::LD1Threev16b;
6164 else if (Ty == LLT::fixed_vector(4, S16))
6165 Opc = AArch64::LD1Threev4h;
6166 else if (Ty == LLT::fixed_vector(8, S16))
6167 Opc = AArch64::LD1Threev8h;
6168 else if (Ty == LLT::fixed_vector(2, S32))
6169 Opc = AArch64::LD1Threev2s;
6170 else if (Ty == LLT::fixed_vector(4, S32))
6171 Opc = AArch64::LD1Threev4s;
6172 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6173 Opc = AArch64::LD1Threev2d;
6174 else if (Ty == S64 || Ty == P0)
6175 Opc = AArch64::LD1Threev1d;
6176 else
6177 llvm_unreachable("Unexpected type for ld1x3!");
6178 selectVectorLoadIntrinsic(Opc, 3, I);
6179 break;
6180 }
6181 case Intrinsic::aarch64_neon_ld1x4: {
6182 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6183 unsigned Opc = 0;
6184 if (Ty == LLT::fixed_vector(8, S8))
6185 Opc = AArch64::LD1Fourv8b;
6186 else if (Ty == LLT::fixed_vector(16, S8))
6187 Opc = AArch64::LD1Fourv16b;
6188 else if (Ty == LLT::fixed_vector(4, S16))
6189 Opc = AArch64::LD1Fourv4h;
6190 else if (Ty == LLT::fixed_vector(8, S16))
6191 Opc = AArch64::LD1Fourv8h;
6192 else if (Ty == LLT::fixed_vector(2, S32))
6193 Opc = AArch64::LD1Fourv2s;
6194 else if (Ty == LLT::fixed_vector(4, S32))
6195 Opc = AArch64::LD1Fourv4s;
6196 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6197 Opc = AArch64::LD1Fourv2d;
6198 else if (Ty == S64 || Ty == P0)
6199 Opc = AArch64::LD1Fourv1d;
6200 else
6201 llvm_unreachable("Unexpected type for ld1x4!");
6202 selectVectorLoadIntrinsic(Opc, 4, I);
6203 break;
6204 }
6205 case Intrinsic::aarch64_neon_ld2: {
6206 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6207 unsigned Opc = 0;
6208 if (Ty == LLT::fixed_vector(8, S8))
6209 Opc = AArch64::LD2Twov8b;
6210 else if (Ty == LLT::fixed_vector(16, S8))
6211 Opc = AArch64::LD2Twov16b;
6212 else if (Ty == LLT::fixed_vector(4, S16))
6213 Opc = AArch64::LD2Twov4h;
6214 else if (Ty == LLT::fixed_vector(8, S16))
6215 Opc = AArch64::LD2Twov8h;
6216 else if (Ty == LLT::fixed_vector(2, S32))
6217 Opc = AArch64::LD2Twov2s;
6218 else if (Ty == LLT::fixed_vector(4, S32))
6219 Opc = AArch64::LD2Twov4s;
6220 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6221 Opc = AArch64::LD2Twov2d;
6222 else if (Ty == S64 || Ty == P0)
6223 Opc = AArch64::LD1Twov1d;
6224 else
6225 llvm_unreachable("Unexpected type for ld2!");
6226 selectVectorLoadIntrinsic(Opc, 2, I);
6227 break;
6228 }
6229 case Intrinsic::aarch64_neon_ld2lane: {
6230 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6231 unsigned Opc;
6232 if (Ty == LLT::fixed_vector(8, S8) || Ty == LLT::fixed_vector(16, S8))
6233 Opc = AArch64::LD2i8;
6234 else if (Ty == LLT::fixed_vector(4, S16) || Ty == LLT::fixed_vector(8, S16))
6235 Opc = AArch64::LD2i16;
6236 else if (Ty == LLT::fixed_vector(2, S32) || Ty == LLT::fixed_vector(4, S32))
6237 Opc = AArch64::LD2i32;
6238 else if (Ty == LLT::fixed_vector(2, S64) ||
6239 Ty == LLT::fixed_vector(2, P0) || Ty == S64 || Ty == P0)
6240 Opc = AArch64::LD2i64;
6241 else
6242 llvm_unreachable("Unexpected type for ld2lane!");
6243 if (!selectVectorLoadLaneIntrinsic(Opc, 2, I))
6244 return false;
6245 break;
6246 }
6247 case Intrinsic::aarch64_neon_ld2r: {
6248 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6249 unsigned Opc = 0;
6250 if (Ty == LLT::fixed_vector(8, S8))
6251 Opc = AArch64::LD2Rv8b;
6252 else if (Ty == LLT::fixed_vector(16, S8))
6253 Opc = AArch64::LD2Rv16b;
6254 else if (Ty == LLT::fixed_vector(4, S16))
6255 Opc = AArch64::LD2Rv4h;
6256 else if (Ty == LLT::fixed_vector(8, S16))
6257 Opc = AArch64::LD2Rv8h;
6258 else if (Ty == LLT::fixed_vector(2, S32))
6259 Opc = AArch64::LD2Rv2s;
6260 else if (Ty == LLT::fixed_vector(4, S32))
6261 Opc = AArch64::LD2Rv4s;
6262 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6263 Opc = AArch64::LD2Rv2d;
6264 else if (Ty == S64 || Ty == P0)
6265 Opc = AArch64::LD2Rv1d;
6266 else
6267 llvm_unreachable("Unexpected type for ld2r!");
6268 selectVectorLoadIntrinsic(Opc, 2, I);
6269 break;
6270 }
6271 case Intrinsic::aarch64_neon_ld3: {
6272 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6273 unsigned Opc = 0;
6274 if (Ty == LLT::fixed_vector(8, S8))
6275 Opc = AArch64::LD3Threev8b;
6276 else if (Ty == LLT::fixed_vector(16, S8))
6277 Opc = AArch64::LD3Threev16b;
6278 else if (Ty == LLT::fixed_vector(4, S16))
6279 Opc = AArch64::LD3Threev4h;
6280 else if (Ty == LLT::fixed_vector(8, S16))
6281 Opc = AArch64::LD3Threev8h;
6282 else if (Ty == LLT::fixed_vector(2, S32))
6283 Opc = AArch64::LD3Threev2s;
6284 else if (Ty == LLT::fixed_vector(4, S32))
6285 Opc = AArch64::LD3Threev4s;
6286 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6287 Opc = AArch64::LD3Threev2d;
6288 else if (Ty == S64 || Ty == P0)
6289 Opc = AArch64::LD1Threev1d;
6290 else
6291 llvm_unreachable("Unexpected type for ld3!");
6292 selectVectorLoadIntrinsic(Opc, 3, I);
6293 break;
6294 }
6295 case Intrinsic::aarch64_neon_ld3lane: {
6296 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6297 unsigned Opc;
6298 if (Ty == LLT::fixed_vector(8, S8) || Ty == LLT::fixed_vector(16, S8))
6299 Opc = AArch64::LD3i8;
6300 else if (Ty == LLT::fixed_vector(4, S16) || Ty == LLT::fixed_vector(8, S16))
6301 Opc = AArch64::LD3i16;
6302 else if (Ty == LLT::fixed_vector(2, S32) || Ty == LLT::fixed_vector(4, S32))
6303 Opc = AArch64::LD3i32;
6304 else if (Ty == LLT::fixed_vector(2, S64) ||
6305 Ty == LLT::fixed_vector(2, P0) || Ty == S64 || Ty == P0)
6306 Opc = AArch64::LD3i64;
6307 else
6308 llvm_unreachable("Unexpected type for ld3lane!");
6309 if (!selectVectorLoadLaneIntrinsic(Opc, 3, I))
6310 return false;
6311 break;
6312 }
6313 case Intrinsic::aarch64_neon_ld3r: {
6314 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6315 unsigned Opc = 0;
6316 if (Ty == LLT::fixed_vector(8, S8))
6317 Opc = AArch64::LD3Rv8b;
6318 else if (Ty == LLT::fixed_vector(16, S8))
6319 Opc = AArch64::LD3Rv16b;
6320 else if (Ty == LLT::fixed_vector(4, S16))
6321 Opc = AArch64::LD3Rv4h;
6322 else if (Ty == LLT::fixed_vector(8, S16))
6323 Opc = AArch64::LD3Rv8h;
6324 else if (Ty == LLT::fixed_vector(2, S32))
6325 Opc = AArch64::LD3Rv2s;
6326 else if (Ty == LLT::fixed_vector(4, S32))
6327 Opc = AArch64::LD3Rv4s;
6328 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6329 Opc = AArch64::LD3Rv2d;
6330 else if (Ty == S64 || Ty == P0)
6331 Opc = AArch64::LD3Rv1d;
6332 else
6333 llvm_unreachable("Unexpected type for ld3r!");
6334 selectVectorLoadIntrinsic(Opc, 3, I);
6335 break;
6336 }
6337 case Intrinsic::aarch64_neon_ld4: {
6338 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6339 unsigned Opc = 0;
6340 if (Ty == LLT::fixed_vector(8, S8))
6341 Opc = AArch64::LD4Fourv8b;
6342 else if (Ty == LLT::fixed_vector(16, S8))
6343 Opc = AArch64::LD4Fourv16b;
6344 else if (Ty == LLT::fixed_vector(4, S16))
6345 Opc = AArch64::LD4Fourv4h;
6346 else if (Ty == LLT::fixed_vector(8, S16))
6347 Opc = AArch64::LD4Fourv8h;
6348 else if (Ty == LLT::fixed_vector(2, S32))
6349 Opc = AArch64::LD4Fourv2s;
6350 else if (Ty == LLT::fixed_vector(4, S32))
6351 Opc = AArch64::LD4Fourv4s;
6352 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6353 Opc = AArch64::LD4Fourv2d;
6354 else if (Ty == S64 || Ty == P0)
6355 Opc = AArch64::LD1Fourv1d;
6356 else
6357 llvm_unreachable("Unexpected type for ld4!");
6358 selectVectorLoadIntrinsic(Opc, 4, I);
6359 break;
6360 }
6361 case Intrinsic::aarch64_neon_ld4lane: {
6362 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6363 unsigned Opc;
6364 if (Ty == LLT::fixed_vector(8, S8) || Ty == LLT::fixed_vector(16, S8))
6365 Opc = AArch64::LD4i8;
6366 else if (Ty == LLT::fixed_vector(4, S16) || Ty == LLT::fixed_vector(8, S16))
6367 Opc = AArch64::LD4i16;
6368 else if (Ty == LLT::fixed_vector(2, S32) || Ty == LLT::fixed_vector(4, S32))
6369 Opc = AArch64::LD4i32;
6370 else if (Ty == LLT::fixed_vector(2, S64) ||
6371 Ty == LLT::fixed_vector(2, P0) || Ty == S64 || Ty == P0)
6372 Opc = AArch64::LD4i64;
6373 else
6374 llvm_unreachable("Unexpected type for ld4lane!");
6375 if (!selectVectorLoadLaneIntrinsic(Opc, 4, I))
6376 return false;
6377 break;
6378 }
6379 case Intrinsic::aarch64_neon_ld4r: {
6380 LLT Ty = MRI.getType(I.getOperand(0).getReg());
6381 unsigned Opc = 0;
6382 if (Ty == LLT::fixed_vector(8, S8))
6383 Opc = AArch64::LD4Rv8b;
6384 else if (Ty == LLT::fixed_vector(16, S8))
6385 Opc = AArch64::LD4Rv16b;
6386 else if (Ty == LLT::fixed_vector(4, S16))
6387 Opc = AArch64::LD4Rv4h;
6388 else if (Ty == LLT::fixed_vector(8, S16))
6389 Opc = AArch64::LD4Rv8h;
6390 else if (Ty == LLT::fixed_vector(2, S32))
6391 Opc = AArch64::LD4Rv2s;
6392 else if (Ty == LLT::fixed_vector(4, S32))
6393 Opc = AArch64::LD4Rv4s;
6394 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6395 Opc = AArch64::LD4Rv2d;
6396 else if (Ty == S64 || Ty == P0)
6397 Opc = AArch64::LD4Rv1d;
6398 else
6399 llvm_unreachable("Unexpected type for ld4r!");
6400 selectVectorLoadIntrinsic(Opc, 4, I);
6401 break;
6402 }
6403 case Intrinsic::aarch64_neon_st1x2: {
6404 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6405 unsigned Opc;
6406 if (Ty == LLT::fixed_vector(8, S8))
6407 Opc = AArch64::ST1Twov8b;
6408 else if (Ty == LLT::fixed_vector(16, S8))
6409 Opc = AArch64::ST1Twov16b;
6410 else if (Ty == LLT::fixed_vector(4, S16))
6411 Opc = AArch64::ST1Twov4h;
6412 else if (Ty == LLT::fixed_vector(8, S16))
6413 Opc = AArch64::ST1Twov8h;
6414 else if (Ty == LLT::fixed_vector(2, S32))
6415 Opc = AArch64::ST1Twov2s;
6416 else if (Ty == LLT::fixed_vector(4, S32))
6417 Opc = AArch64::ST1Twov4s;
6418 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6419 Opc = AArch64::ST1Twov2d;
6420 else if (Ty == S64 || Ty == P0)
6421 Opc = AArch64::ST1Twov1d;
6422 else
6423 llvm_unreachable("Unexpected type for st1x2!");
6424 selectVectorStoreIntrinsic(I, 2, Opc);
6425 break;
6426 }
6427 case Intrinsic::aarch64_neon_st1x3: {
6428 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6429 unsigned Opc;
6430 if (Ty == LLT::fixed_vector(8, S8))
6431 Opc = AArch64::ST1Threev8b;
6432 else if (Ty == LLT::fixed_vector(16, S8))
6433 Opc = AArch64::ST1Threev16b;
6434 else if (Ty == LLT::fixed_vector(4, S16))
6435 Opc = AArch64::ST1Threev4h;
6436 else if (Ty == LLT::fixed_vector(8, S16))
6437 Opc = AArch64::ST1Threev8h;
6438 else if (Ty == LLT::fixed_vector(2, S32))
6439 Opc = AArch64::ST1Threev2s;
6440 else if (Ty == LLT::fixed_vector(4, S32))
6441 Opc = AArch64::ST1Threev4s;
6442 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6443 Opc = AArch64::ST1Threev2d;
6444 else if (Ty == S64 || Ty == P0)
6445 Opc = AArch64::ST1Threev1d;
6446 else
6447 llvm_unreachable("Unexpected type for st1x3!");
6448 selectVectorStoreIntrinsic(I, 3, Opc);
6449 break;
6450 }
6451 case Intrinsic::aarch64_neon_st1x4: {
6452 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6453 unsigned Opc;
6454 if (Ty == LLT::fixed_vector(8, S8))
6455 Opc = AArch64::ST1Fourv8b;
6456 else if (Ty == LLT::fixed_vector(16, S8))
6457 Opc = AArch64::ST1Fourv16b;
6458 else if (Ty == LLT::fixed_vector(4, S16))
6459 Opc = AArch64::ST1Fourv4h;
6460 else if (Ty == LLT::fixed_vector(8, S16))
6461 Opc = AArch64::ST1Fourv8h;
6462 else if (Ty == LLT::fixed_vector(2, S32))
6463 Opc = AArch64::ST1Fourv2s;
6464 else if (Ty == LLT::fixed_vector(4, S32))
6465 Opc = AArch64::ST1Fourv4s;
6466 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6467 Opc = AArch64::ST1Fourv2d;
6468 else if (Ty == S64 || Ty == P0)
6469 Opc = AArch64::ST1Fourv1d;
6470 else
6471 llvm_unreachable("Unexpected type for st1x4!");
6472 selectVectorStoreIntrinsic(I, 4, Opc);
6473 break;
6474 }
6475 case Intrinsic::aarch64_neon_st2: {
6476 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6477 unsigned Opc;
6478 if (Ty == LLT::fixed_vector(8, S8))
6479 Opc = AArch64::ST2Twov8b;
6480 else if (Ty == LLT::fixed_vector(16, S8))
6481 Opc = AArch64::ST2Twov16b;
6482 else if (Ty == LLT::fixed_vector(4, S16))
6483 Opc = AArch64::ST2Twov4h;
6484 else if (Ty == LLT::fixed_vector(8, S16))
6485 Opc = AArch64::ST2Twov8h;
6486 else if (Ty == LLT::fixed_vector(2, S32))
6487 Opc = AArch64::ST2Twov2s;
6488 else if (Ty == LLT::fixed_vector(4, S32))
6489 Opc = AArch64::ST2Twov4s;
6490 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6491 Opc = AArch64::ST2Twov2d;
6492 else if (Ty == S64 || Ty == P0)
6493 Opc = AArch64::ST1Twov1d;
6494 else
6495 llvm_unreachable("Unexpected type for st2!");
6496 selectVectorStoreIntrinsic(I, 2, Opc);
6497 break;
6498 }
6499 case Intrinsic::aarch64_neon_st3: {
6500 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6501 unsigned Opc;
6502 if (Ty == LLT::fixed_vector(8, S8))
6503 Opc = AArch64::ST3Threev8b;
6504 else if (Ty == LLT::fixed_vector(16, S8))
6505 Opc = AArch64::ST3Threev16b;
6506 else if (Ty == LLT::fixed_vector(4, S16))
6507 Opc = AArch64::ST3Threev4h;
6508 else if (Ty == LLT::fixed_vector(8, S16))
6509 Opc = AArch64::ST3Threev8h;
6510 else if (Ty == LLT::fixed_vector(2, S32))
6511 Opc = AArch64::ST3Threev2s;
6512 else if (Ty == LLT::fixed_vector(4, S32))
6513 Opc = AArch64::ST3Threev4s;
6514 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6515 Opc = AArch64::ST3Threev2d;
6516 else if (Ty == S64 || Ty == P0)
6517 Opc = AArch64::ST1Threev1d;
6518 else
6519 llvm_unreachable("Unexpected type for st3!");
6520 selectVectorStoreIntrinsic(I, 3, Opc);
6521 break;
6522 }
6523 case Intrinsic::aarch64_neon_st4: {
6524 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6525 unsigned Opc;
6526 if (Ty == LLT::fixed_vector(8, S8))
6527 Opc = AArch64::ST4Fourv8b;
6528 else if (Ty == LLT::fixed_vector(16, S8))
6529 Opc = AArch64::ST4Fourv16b;
6530 else if (Ty == LLT::fixed_vector(4, S16))
6531 Opc = AArch64::ST4Fourv4h;
6532 else if (Ty == LLT::fixed_vector(8, S16))
6533 Opc = AArch64::ST4Fourv8h;
6534 else if (Ty == LLT::fixed_vector(2, S32))
6535 Opc = AArch64::ST4Fourv2s;
6536 else if (Ty == LLT::fixed_vector(4, S32))
6537 Opc = AArch64::ST4Fourv4s;
6538 else if (Ty == LLT::fixed_vector(2, S64) || Ty == LLT::fixed_vector(2, P0))
6539 Opc = AArch64::ST4Fourv2d;
6540 else if (Ty == S64 || Ty == P0)
6541 Opc = AArch64::ST1Fourv1d;
6542 else
6543 llvm_unreachable("Unexpected type for st4!");
6544 selectVectorStoreIntrinsic(I, 4, Opc);
6545 break;
6546 }
6547 case Intrinsic::aarch64_neon_st2lane: {
6548 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6549 unsigned Opc;
6550 if (Ty == LLT::fixed_vector(8, S8) || Ty == LLT::fixed_vector(16, S8))
6551 Opc = AArch64::ST2i8;
6552 else if (Ty == LLT::fixed_vector(4, S16) || Ty == LLT::fixed_vector(8, S16))
6553 Opc = AArch64::ST2i16;
6554 else if (Ty == LLT::fixed_vector(2, S32) || Ty == LLT::fixed_vector(4, S32))
6555 Opc = AArch64::ST2i32;
6556 else if (Ty == LLT::fixed_vector(2, S64) ||
6557 Ty == LLT::fixed_vector(2, P0) || Ty == S64 || Ty == P0)
6558 Opc = AArch64::ST2i64;
6559 else
6560 llvm_unreachable("Unexpected type for st2lane!");
6561 if (!selectVectorStoreLaneIntrinsic(I, 2, Opc))
6562 return false;
6563 break;
6564 }
6565 case Intrinsic::aarch64_neon_st3lane: {
6566 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6567 unsigned Opc;
6568 if (Ty == LLT::fixed_vector(8, S8) || Ty == LLT::fixed_vector(16, S8))
6569 Opc = AArch64::ST3i8;
6570 else if (Ty == LLT::fixed_vector(4, S16) || Ty == LLT::fixed_vector(8, S16))
6571 Opc = AArch64::ST3i16;
6572 else if (Ty == LLT::fixed_vector(2, S32) || Ty == LLT::fixed_vector(4, S32))
6573 Opc = AArch64::ST3i32;
6574 else if (Ty == LLT::fixed_vector(2, S64) ||
6575 Ty == LLT::fixed_vector(2, P0) || Ty == S64 || Ty == P0)
6576 Opc = AArch64::ST3i64;
6577 else
6578 llvm_unreachable("Unexpected type for st3lane!");
6579 if (!selectVectorStoreLaneIntrinsic(I, 3, Opc))
6580 return false;
6581 break;
6582 }
6583 case Intrinsic::aarch64_neon_st4lane: {
6584 LLT Ty = MRI.getType(I.getOperand(1).getReg());
6585 unsigned Opc;
6586 if (Ty == LLT::fixed_vector(8, S8) || Ty == LLT::fixed_vector(16, S8))
6587 Opc = AArch64::ST4i8;
6588 else if (Ty == LLT::fixed_vector(4, S16) || Ty == LLT::fixed_vector(8, S16))
6589 Opc = AArch64::ST4i16;
6590 else if (Ty == LLT::fixed_vector(2, S32) || Ty == LLT::fixed_vector(4, S32))
6591 Opc = AArch64::ST4i32;
6592 else if (Ty == LLT::fixed_vector(2, S64) ||
6593 Ty == LLT::fixed_vector(2, P0) || Ty == S64 || Ty == P0)
6594 Opc = AArch64::ST4i64;
6595 else
6596 llvm_unreachable("Unexpected type for st4lane!");
6597 if (!selectVectorStoreLaneIntrinsic(I, 4, Opc))
6598 return false;
6599 break;
6600 }
6601 case Intrinsic::aarch64_mops_memset_tag: {
6602 // Transform
6603 // %dst:gpr(p0) = \
6604 // G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aarch64.mops.memset.tag),
6605 // \ %dst:gpr(p0), %val:gpr(s64), %n:gpr(s64)
6606 // where %dst is updated, into
6607 // %Rd:GPR64common, %Rn:GPR64) = \
6608 // MOPSMemorySetTaggingPseudo \
6609 // %Rd:GPR64common, %Rn:GPR64, %Rm:GPR64
6610 // where Rd and Rn are tied.
6611 // It is expected that %val has been extended to s64 in legalization.
6612 // Note that the order of the size/value operands are swapped.
6613
6614 Register DstDef = I.getOperand(0).getReg();
6615 // I.getOperand(1) is the intrinsic function
6616 Register DstUse = I.getOperand(2).getReg();
6617 Register ValUse = I.getOperand(3).getReg();
6618 Register SizeUse = I.getOperand(4).getReg();
6619
6620 // MOPSMemorySetTaggingPseudo has two defs; the intrinsic call has only one.
6621 // Therefore an additional virtual register is required for the updated size
6622 // operand. This value is not accessible via the semantics of the intrinsic.
6624
6625 auto Memset = MIB.buildInstr(AArch64::MOPSMemorySetTaggingPseudo,
6626 {DstDef, SizeDef}, {DstUse, SizeUse, ValUse});
6627 Memset.cloneMemRefs(I);
6628 Memset.setOperandDead(5); // implicit-def $nzcv
6630 break;
6631 }
6632 case Intrinsic::ptrauth_resign_load_relative: {
6633 Register DstReg = I.getOperand(0).getReg();
6634 Register ValReg = I.getOperand(2).getReg();
6635 uint64_t AUTKey = I.getOperand(3).getImm();
6636 Register AUTDisc = I.getOperand(4).getReg();
6637 uint64_t PACKey = I.getOperand(5).getImm();
6638 Register PACDisc = I.getOperand(6).getReg();
6639 int64_t Addend = I.getOperand(7).getImm();
6640
6641 Register AUTAddrDisc = AUTDisc;
6642 uint16_t AUTConstDiscC = 0;
6643 std::tie(AUTConstDiscC, AUTAddrDisc) =
6645
6646 Register PACAddrDisc = PACDisc;
6647 uint16_t PACConstDiscC = 0;
6648 std::tie(PACConstDiscC, PACAddrDisc) =
6650
6651 MIB.buildCopy({AArch64::X16}, {ValReg});
6652
6653 MIB.buildInstr(AArch64::AUTRELLOADPAC)
6654 .addImm(AUTKey)
6655 .addImm(AUTConstDiscC)
6656 .addUse(AUTAddrDisc)
6657 .addImm(PACKey)
6658 .addImm(PACConstDiscC)
6659 .addUse(PACAddrDisc)
6660 .addImm(Addend)
6661 .setOperandDead(8) // implicit-def $x17
6662 .setOperandDead(9) // implicit-def $nzcv
6663 .constrainAllUses(TII, TRI, RBI);
6664 MIB.buildCopy({DstReg}, Register(AArch64::X16));
6665
6666 RBI.constrainGenericRegister(DstReg, AArch64::GPR64RegClass, MRI);
6667 I.eraseFromParent();
6668 return true;
6669 }
6670 }
6671
6672 I.eraseFromParent();
6673 return true;
6674}
6675
6676bool AArch64InstructionSelector::selectIntrinsic(MachineInstr &I,
6677 MachineRegisterInfo &MRI) {
6678 unsigned IntrinID = cast<GIntrinsic>(I).getIntrinsicID();
6679
6680 switch (IntrinID) {
6681 default:
6682 break;
6683 case Intrinsic::ptrauth_resign: {
6684 Register DstReg = I.getOperand(0).getReg();
6685 Register ValReg = I.getOperand(2).getReg();
6686 uint64_t AUTKey = I.getOperand(3).getImm();
6687 Register AUTDisc = I.getOperand(4).getReg();
6688 uint64_t PACKey = I.getOperand(5).getImm();
6689 Register PACDisc = I.getOperand(6).getReg();
6690
6691 Register AUTAddrDisc = AUTDisc;
6692 uint16_t AUTConstDiscC = 0;
6693 std::tie(AUTConstDiscC, AUTAddrDisc) =
6695
6696 Register PACAddrDisc = PACDisc;
6697 uint16_t PACConstDiscC = 0;
6698 std::tie(PACConstDiscC, PACAddrDisc) =
6700
6701 MIB.buildCopy({AArch64::X16}, {ValReg});
6702 MIB.buildInstr(AArch64::AUTPAC)
6703 .addImm(AUTKey)
6704 .addImm(AUTConstDiscC)
6705 .addUse(AUTAddrDisc)
6706 .addImm(PACKey)
6707 .addImm(PACConstDiscC)
6708 .addUse(PACAddrDisc)
6709 .setOperandDead(7) // implicit-def $x17
6710 .setOperandDead(8) // implicit-def $nzcv
6711 .constrainAllUses(TII, TRI, RBI);
6712 MIB.buildCopy({DstReg}, Register(AArch64::X16));
6713
6714 RBI.constrainGenericRegister(DstReg, AArch64::GPR64RegClass, MRI);
6715 I.eraseFromParent();
6716 return true;
6717 }
6718 case Intrinsic::ptrauth_auth_with_pc_and_resign: {
6719 Register DstReg = I.getOperand(0).getReg();
6720 Register ValReg = I.getOperand(2).getReg();
6721 uint64_t AUTKey = I.getOperand(3).getImm();
6722 Register AUTDisc = I.getOperand(4).getReg();
6723 Register AUTPC = I.getOperand(5).getReg();
6724 uint64_t PACKey = I.getOperand(6).getImm();
6725 Register PACDisc = I.getOperand(7).getReg();
6726
6727 assert((AUTKey == AArch64PACKey::IA || AUTKey == AArch64PACKey::IB) &&
6728 "auth_with_pc_and_resign only supports IA and IB keys");
6729
6730 uint16_t PACConstDiscC = 0;
6731 Register PACAddrDisc;
6732 std::tie(PACConstDiscC, PACAddrDisc) =
6734
6735 if (!PACAddrDisc.isValid())
6736 PACAddrDisc = AArch64::XZR;
6737
6738 MIB.buildCopy({AArch64::X17}, {ValReg});
6739 MIB.buildCopy({AArch64::X16}, {AUTDisc});
6740 MIB.buildCopy({AArch64::X15}, {AUTPC});
6741
6742 MIB.buildInstr(AArch64::AUTPCPAC)
6743 .addImm(AUTKey)
6744 .addImm(PACKey)
6745 .addImm(PACConstDiscC)
6746 .addUse(PACAddrDisc)
6747 .setOperandDead(5) // implicit-def $x15
6748 .setOperandDead(6) // implicit-def $x16
6749 .setOperandDead(7) // implicit-def $nzcv
6750 .constrainAllUses(TII, TRI, RBI);
6751
6752 MIB.buildCopy({DstReg}, Register(AArch64::X17));
6753 RBI.constrainGenericRegister(DstReg, AArch64::GPR64RegClass, MRI);
6754 I.eraseFromParent();
6755 return true;
6756 }
6757 case Intrinsic::ptrauth_auth: {
6758 Register DstReg = I.getOperand(0).getReg();
6759 Register ValReg = I.getOperand(2).getReg();
6760 uint64_t AUTKey = I.getOperand(3).getImm();
6761 Register AUTDisc = I.getOperand(4).getReg();
6762
6763 Register AUTAddrDisc = AUTDisc;
6764 uint16_t AUTConstDiscC = 0;
6765 std::tie(AUTConstDiscC, AUTAddrDisc) =
6767
6768 if (STI.isX16X17Safer()) {
6769 MIB.buildCopy({AArch64::X16}, {ValReg});
6770 MIB.buildInstr(AArch64::AUTx16x17)
6771 .addImm(AUTKey)
6772 .addImm(AUTConstDiscC)
6773 .addUse(AUTAddrDisc)
6774 .setOperandDead(4) // implicit-def $x17
6775 .setOperandDead(5) // implicit-def $nzcv
6776 .constrainAllUses(TII, TRI, RBI);
6777 MIB.buildCopy({DstReg}, Register(AArch64::X16));
6778 } else {
6779 Register ScratchReg =
6780 MRI.createVirtualRegister(&AArch64::GPR64commonRegClass);
6781 auto Auth = MIB.buildInstr(AArch64::AUTxMxN)
6782 .addDef(DstReg)
6783 .addDef(ScratchReg)
6784 .addUse(ValReg)
6785 .addImm(AUTKey)
6786 .addImm(AUTConstDiscC)
6787 .addUse(AUTAddrDisc);
6789 Auth.constrainAllUses(TII, TRI, RBI);
6790 }
6791
6792 RBI.constrainGenericRegister(DstReg, AArch64::GPR64RegClass, MRI);
6793 I.eraseFromParent();
6794 return true;
6795 }
6796 case Intrinsic::frameaddress:
6797 case Intrinsic::returnaddress: {
6798 MachineFunction &MF = *I.getParent()->getParent();
6799 MachineFrameInfo &MFI = MF.getFrameInfo();
6800
6801 unsigned Depth = I.getOperand(2).getImm();
6802 Register DstReg = I.getOperand(0).getReg();
6803 RBI.constrainGenericRegister(DstReg, AArch64::GPR64RegClass, MRI);
6804
6805 if (Depth == 0 && IntrinID == Intrinsic::returnaddress) {
6806 if (!MFReturnAddr) {
6807 // Insert the copy from LR/X30 into the entry block, before it can be
6808 // clobbered by anything.
6809 MFI.setReturnAddressIsTaken(true);
6810 MFReturnAddr = getFunctionLiveInPhysReg(
6811 MF, TII, AArch64::LR, AArch64::GPR64RegClass, I.getDebugLoc());
6812 }
6813
6814 if (STI.hasPAuth()) {
6815 MIB.buildInstr(AArch64::XPACI, {DstReg}, {MFReturnAddr});
6816 } else {
6817 MIB.buildCopy({Register(AArch64::LR)}, {MFReturnAddr});
6818 MIB.buildInstr(AArch64::XPACLRI);
6819 MIB.buildCopy({DstReg}, {Register(AArch64::LR)});
6820 }
6821
6822 I.eraseFromParent();
6823 return true;
6824 }
6825
6826 MFI.setFrameAddressIsTaken(true);
6827 Register FrameAddr(AArch64::FP);
6828 while (Depth--) {
6829 Register NextFrame = MRI.createVirtualRegister(&AArch64::GPR64spRegClass);
6830 auto Ldr =
6831 MIB.buildInstr(AArch64::LDRXui, {NextFrame}, {FrameAddr}).addImm(0);
6833 FrameAddr = NextFrame;
6834 }
6835
6836 if (IntrinID == Intrinsic::frameaddress)
6837 MIB.buildCopy({DstReg}, {FrameAddr});
6838 else {
6839 MFI.setReturnAddressIsTaken(true);
6840
6841 if (STI.hasPAuth()) {
6842 Register TmpReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
6843 MIB.buildInstr(AArch64::LDRXui, {TmpReg}, {FrameAddr}).addImm(1);
6844 MIB.buildInstr(AArch64::XPACI, {DstReg}, {TmpReg});
6845 } else {
6846 MIB.buildInstr(AArch64::LDRXui, {Register(AArch64::LR)}, {FrameAddr})
6847 .addImm(1);
6848 MIB.buildInstr(AArch64::XPACLRI);
6849 MIB.buildCopy({DstReg}, {Register(AArch64::LR)});
6850 }
6851 }
6852
6853 I.eraseFromParent();
6854 return true;
6855 }
6856 case Intrinsic::aarch64_neon_tbl2:
6857 SelectTable(I, MRI, 2, AArch64::TBLv8i8Two, AArch64::TBLv16i8Two, false);
6858 return true;
6859 case Intrinsic::aarch64_neon_tbl3:
6860 SelectTable(I, MRI, 3, AArch64::TBLv8i8Three, AArch64::TBLv16i8Three,
6861 false);
6862 return true;
6863 case Intrinsic::aarch64_neon_tbl4:
6864 SelectTable(I, MRI, 4, AArch64::TBLv8i8Four, AArch64::TBLv16i8Four, false);
6865 return true;
6866 case Intrinsic::aarch64_neon_tbx2:
6867 SelectTable(I, MRI, 2, AArch64::TBXv8i8Two, AArch64::TBXv16i8Two, true);
6868 return true;
6869 case Intrinsic::aarch64_neon_tbx3:
6870 SelectTable(I, MRI, 3, AArch64::TBXv8i8Three, AArch64::TBXv16i8Three, true);
6871 return true;
6872 case Intrinsic::aarch64_neon_tbx4:
6873 SelectTable(I, MRI, 4, AArch64::TBXv8i8Four, AArch64::TBXv16i8Four, true);
6874 return true;
6875 case Intrinsic::swift_async_context_addr:
6876 auto Sub = MIB.buildInstr(AArch64::SUBXri, {I.getOperand(0).getReg()},
6877 {Register(AArch64::FP)})
6878 .addImm(8)
6879 .addImm(0);
6881
6883 MF->getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(true);
6884 I.eraseFromParent();
6885 return true;
6886 }
6887 return false;
6888}
6889
6890// G_PTRAUTH_GLOBAL_VALUE lowering
6891//
6892// We have 3 lowering alternatives to choose from:
6893// - MOVaddrPAC: similar to MOVaddr, with added PAC.
6894// If the GV doesn't need a GOT load (i.e., is locally defined)
6895// materialize the pointer using adrp+add+pac. See LowerMOVaddrPAC.
6896//
6897// - LOADgotPAC: similar to LOADgot, with added PAC.
6898// If the GV needs a GOT load, materialize the pointer using the usual
6899// GOT adrp+ldr, +pac. Pointers in GOT are assumed to be not signed, the GOT
6900// section is assumed to be read-only (for example, via relro mechanism). See
6901// LowerMOVaddrPAC.
6902//
6903// - LOADauthptrstatic: similar to LOADgot, but use a
6904// special stub slot instead of a GOT slot.
6905// Load a signed pointer for symbol 'sym' from a stub slot named
6906// 'sym$auth_ptr$key$disc' filled by dynamic linker during relocation
6907// resolving. This usually lowers to adrp+ldr, but also emits an entry into
6908// .data with an
6909// @AUTH relocation. See LowerLOADauthptrstatic.
6910//
6911// All 3 are pseudos that are expand late to longer sequences: this lets us
6912// provide integrity guarantees on the to-be-signed intermediate values.
6913//
6914// LOADauthptrstatic is undesirable because it requires a large section filled
6915// with often similarly-signed pointers, making it a good harvesting target.
6916// Thus, it's only used for ptrauth references to extern_weak to avoid null
6917// checks.
6918
6919bool AArch64InstructionSelector::selectPtrAuthGlobalValue(
6920 MachineInstr &I, MachineRegisterInfo &MRI) const {
6921 Register DefReg = I.getOperand(0).getReg();
6922 Register Addr = I.getOperand(1).getReg();
6923 uint64_t Key = I.getOperand(2).getImm();
6924 Register AddrDisc = I.getOperand(3).getReg();
6925 uint64_t Disc = I.getOperand(4).getImm();
6926 int64_t Offset = 0;
6927
6929 report_fatal_error("key in ptrauth global out of range [0, " +
6930 Twine((int)AArch64PACKey::LAST) + "]");
6931
6932 // Blend only works if the integer discriminator is 16-bit wide.
6933 if (!isUInt<16>(Disc))
6935 "constant discriminator in ptrauth global out of range [0, 0xffff]");
6936
6937 // Choosing between 3 lowering alternatives is target-specific.
6938 if (!STI.isTargetELF() && !STI.isTargetMachO())
6939 report_fatal_error("ptrauth global lowering only supported on MachO/ELF");
6940
6941 if (!MRI.hasOneDef(Addr))
6942 return false;
6943
6944 // First match any offset we take from the real global.
6945 const MachineInstr *DefMI = &*MRI.def_instr_begin(Addr);
6946 if (DefMI->getOpcode() == TargetOpcode::G_PTR_ADD) {
6947 Register OffsetReg = DefMI->getOperand(2).getReg();
6948 if (!MRI.hasOneDef(OffsetReg))
6949 return false;
6950 const MachineInstr &OffsetMI = *MRI.def_instr_begin(OffsetReg);
6951 if (OffsetMI.getOpcode() != TargetOpcode::G_CONSTANT)
6952 return false;
6953
6954 Addr = DefMI->getOperand(1).getReg();
6955 if (!MRI.hasOneDef(Addr))
6956 return false;
6957
6958 DefMI = &*MRI.def_instr_begin(Addr);
6959 Offset = OffsetMI.getOperand(1).getCImm()->getSExtValue();
6960 }
6961
6962 // We should be left with a genuine unauthenticated GlobalValue.
6963 const GlobalValue *GV;
6964 if (DefMI->getOpcode() == TargetOpcode::G_GLOBAL_VALUE) {
6965 GV = DefMI->getOperand(1).getGlobal();
6967 } else if (DefMI->getOpcode() == AArch64::G_ADD_LOW) {
6968 GV = DefMI->getOperand(2).getGlobal();
6970 } else {
6971 return false;
6972 }
6973
6974 MachineIRBuilder MIB(I);
6975
6976 // Classify the reference to determine whether it needs a GOT load.
6977 unsigned OpFlags = STI.ClassifyGlobalReference(GV, TM);
6978 const bool NeedsGOTLoad = ((OpFlags & AArch64II::MO_GOT) != 0);
6979 assert(((OpFlags & (~AArch64II::MO_GOT)) == 0) &&
6980 "unsupported non-GOT op flags on ptrauth global reference");
6981 assert((!GV->hasExternalWeakLinkage() || NeedsGOTLoad) &&
6982 "unsupported non-GOT reference to weak ptrauth global");
6983
6984 std::optional<APInt> AddrDiscVal = getIConstantVRegVal(AddrDisc, MRI);
6985 bool HasAddrDisc = !AddrDiscVal || *AddrDiscVal != 0;
6986
6987 // Non-extern_weak:
6988 // - No GOT load needed -> MOVaddrPAC
6989 // - GOT load for non-extern_weak -> LOADgotPAC
6990 // Note that we disallow extern_weak refs to avoid null checks later.
6991 if (!GV->hasExternalWeakLinkage()) {
6992 MIB.buildInstr(NeedsGOTLoad ? AArch64::LOADgotPAC : AArch64::MOVaddrPAC)
6994 .addImm(Key)
6995 .addReg(HasAddrDisc ? AddrDisc : AArch64::XZR)
6996 .addImm(Disc)
6997 .constrainAllUses(TII, TRI, RBI);
6998 MIB.buildCopy(DefReg, Register(AArch64::X16));
6999 RBI.constrainGenericRegister(DefReg, AArch64::GPR64RegClass, MRI);
7000 I.eraseFromParent();
7001 return true;
7002 }
7003
7004 // extern_weak -> LOADauthptrstatic
7005
7006 // Offsets and extern_weak don't mix well: ptrauth aside, you'd get the
7007 // offset alone as a pointer if the symbol wasn't available, which would
7008 // probably break null checks in users. Ptrauth complicates things further:
7009 // error out.
7010 if (Offset != 0)
7012 "unsupported non-zero offset in weak ptrauth global reference");
7013
7014 if (HasAddrDisc)
7015 report_fatal_error("unsupported weak addr-div ptrauth global");
7016
7017 MIB.buildInstr(AArch64::LOADauthptrstatic, {DefReg}, {})
7018 .addGlobalAddress(GV, Offset)
7019 .addImm(Key)
7020 .addImm(Disc);
7021 RBI.constrainGenericRegister(DefReg, AArch64::GPR64RegClass, MRI);
7022
7023 I.eraseFromParent();
7024 return true;
7025}
7026
7027void AArch64InstructionSelector::SelectTable(MachineInstr &I,
7028 MachineRegisterInfo &MRI,
7029 unsigned NumVec, unsigned Opc1,
7030 unsigned Opc2, bool isExt) {
7031 Register DstReg = I.getOperand(0).getReg();
7032 unsigned Opc = MRI.getType(DstReg) == LLT::fixed_vector(8, 8) ? Opc1 : Opc2;
7033
7034 // Create the REG_SEQUENCE
7036 for (unsigned i = 0; i < NumVec; i++)
7037 Regs.push_back(I.getOperand(i + 2 + isExt).getReg());
7038 Register RegSeq = createQTuple(Regs, MIB);
7039
7040 Register IdxReg = I.getOperand(2 + NumVec + isExt).getReg();
7041 MachineInstrBuilder Instr;
7042 if (isExt) {
7043 Register Reg = I.getOperand(2).getReg();
7044 Instr = MIB.buildInstr(Opc, {DstReg}, {Reg, RegSeq, IdxReg});
7045 } else
7046 Instr = MIB.buildInstr(Opc, {DstReg}, {RegSeq, IdxReg});
7048 I.eraseFromParent();
7049}
7050
7051InstructionSelector::ComplexRendererFns
7052AArch64InstructionSelector::selectShiftA_32(const MachineOperand &Root) const {
7053 auto MaybeImmed = getImmedFromMO(Root);
7054 if (MaybeImmed == std::nullopt || *MaybeImmed > 31)
7055 return std::nullopt;
7056 uint64_t Enc = (32 - *MaybeImmed) & 0x1f;
7057 return {{[=](MachineInstrBuilder &MIB) { MIB.addImm(Enc); }}};
7058}
7059
7060InstructionSelector::ComplexRendererFns
7061AArch64InstructionSelector::selectShiftB_32(const MachineOperand &Root) const {
7062 auto MaybeImmed = getImmedFromMO(Root);
7063 if (MaybeImmed == std::nullopt || *MaybeImmed > 31)
7064 return std::nullopt;
7065 uint64_t Enc = 31 - *MaybeImmed;
7066 return {{[=](MachineInstrBuilder &MIB) { MIB.addImm(Enc); }}};
7067}
7068
7069InstructionSelector::ComplexRendererFns
7070AArch64InstructionSelector::selectShiftA_64(const MachineOperand &Root) const {
7071 auto MaybeImmed = getImmedFromMO(Root);
7072 if (MaybeImmed == std::nullopt || *MaybeImmed > 63)
7073 return std::nullopt;
7074 uint64_t Enc = (64 - *MaybeImmed) & 0x3f;
7075 return {{[=](MachineInstrBuilder &MIB) { MIB.addImm(Enc); }}};
7076}
7077
7078InstructionSelector::ComplexRendererFns
7079AArch64InstructionSelector::selectShiftB_64(const MachineOperand &Root) const {
7080 auto MaybeImmed = getImmedFromMO(Root);
7081 if (MaybeImmed == std::nullopt || *MaybeImmed > 63)
7082 return std::nullopt;
7083 uint64_t Enc = 63 - *MaybeImmed;
7084 return {{[=](MachineInstrBuilder &MIB) { MIB.addImm(Enc); }}};
7085}
7086
7087template <unsigned ShiftWidth>
7088InstructionSelector::ComplexRendererFns
7089AArch64InstructionSelector::selectShiftMask(MachineOperand &Root) const {
7090 if (!Root.isReg())
7091 return std::nullopt;
7092
7093 MachineRegisterInfo &MRI =
7094 Root.getParent()->getParent()->getParent()->getRegInfo();
7095
7096 Register ShAmtReg = Root.getReg();
7097
7098 // Peek through zext for i32 shifts only. For i64 shifts the zext case
7099 // is already handled by existing patterns in the Shift multiclass.
7100 if (ShiftWidth == 32) {
7101 Register ZExtSrcReg;
7102 if (mi_match(ShAmtReg, MRI, m_GZExt(m_Reg(ZExtSrcReg))))
7103 ShAmtReg = ZExtSrcReg;
7104 }
7105
7106 // Remove AND if the mask covers at least the low log2(ShiftWidth) bits.
7107 APInt AndMask;
7108 Register AndSrcReg;
7109 if (mi_match(ShAmtReg, MRI, m_GAnd(m_Reg(AndSrcReg), m_ICst(AndMask))) &&
7110 MRI.getType(ShAmtReg).getSizeInBits() == ShiftWidth) {
7111 if (AndMask.countr_one() >= Log2_32(ShiftWidth))
7112 ShAmtReg = AndSrcReg;
7113 }
7114
7115 // If shifting by X+/-N where N == 0 mod ShiftWidth, then just shift by X
7116 // to avoid the ADD/SUB. The low log2(ShiftWidth) bits are unchanged, so the
7117 // shift can use X directly; the original ADD/SUB stays for any other users.
7118 Register AddSrcReg;
7119 int64_t AddImm;
7120 if ((mi_match(ShAmtReg, MRI,
7121 m_GAdd(m_Reg(AddSrcReg), m_ICstOrSplat(AddImm))) ||
7122 mi_match(ShAmtReg, MRI,
7123 m_GSub(m_Reg(AddSrcReg), m_ICstOrSplat(AddImm)))) &&
7124 (AddImm % ShiftWidth == 0)) {
7125 ShAmtReg = AddSrcReg;
7126 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(ShAmtReg); }}};
7127 }
7128
7129 // If shifting by N-X where N == 0 mod ShiftWidth, then just shift by -X
7130 // to generate a NEG instead of a SUB from a constant.
7131 Register SubSrcReg;
7132 int64_t SubImm;
7133 if (MRI.hasOneUse(ShAmtReg) &&
7134 mi_match(ShAmtReg, MRI, m_GSub(m_ICst(SubImm), m_Reg(SubSrcReg))) &&
7135 SubImm != 0 && (SubImm % ShiftWidth == 0)) {
7136 return {{[=](MachineInstrBuilder &MIB) {
7137 MachineInstr *I = MIB.getInstr();
7138 MachineRegisterInfo &MRI2 = I->getMF()->getRegInfo();
7139 const TargetRegisterClass &RC =
7140 ShiftWidth == 32 ? AArch64::GPR32RegClass : AArch64::GPR64RegClass;
7141 unsigned SubOpc = ShiftWidth == 32 ? AArch64::SUBWrr : AArch64::SUBXrr;
7142 Register ZeroReg = ShiftWidth == 32 ? AArch64::WZR : AArch64::XZR;
7143 Register NegReg = MRI2.createVirtualRegister(&RC);
7144 auto NegMI = BuildMI(*I->getParent(), *I, I->getDebugLoc(),
7145 TII.get(SubOpc), NegReg)
7146 .addReg(ZeroReg)
7147 .addReg(SubSrcReg);
7149 MIB.addReg(NegReg);
7150 }}};
7151 }
7152
7153 // If shifting by N-X where N == -1 mod ShiftWidth, then just shift by ~X
7154 // to generate a NOT (MVN) instead of a SUB from a constant.
7155 Register NotSrcReg;
7156 int64_t NotImm;
7157 if (MRI.hasOneUse(ShAmtReg) &&
7158 mi_match(ShAmtReg, MRI, m_GSub(m_ICst(NotImm), m_Reg(NotSrcReg))) &&
7159 (NotImm % ShiftWidth == ShiftWidth - 1)) {
7160 return {{[=](MachineInstrBuilder &MIB) {
7161 MachineInstr *I = MIB.getInstr();
7162 MachineRegisterInfo &MRI2 = I->getMF()->getRegInfo();
7163 const TargetRegisterClass &RC =
7164 ShiftWidth == 32 ? AArch64::GPR32RegClass : AArch64::GPR64RegClass;
7165 unsigned NotOpc = ShiftWidth == 32 ? AArch64::ORNWrr : AArch64::ORNXrr;
7166 Register ZeroReg = ShiftWidth == 32 ? AArch64::WZR : AArch64::XZR;
7167 Register NotReg = MRI2.createVirtualRegister(&RC);
7168 auto NotMI = BuildMI(*I->getParent(), *I, I->getDebugLoc(),
7169 TII.get(NotOpc), NotReg)
7170 .addReg(ZeroReg)
7171 .addReg(NotSrcReg);
7173 MIB.addReg(NotReg);
7174 }}};
7175 }
7176
7177 // Only succeed if we changed the shift amount; otherwise let other
7178 // patterns (e.g. zext GPR32 -> SUBREG_TO_REG) match instead.
7179 if (ShAmtReg == Root.getReg())
7180 return std::nullopt;
7181
7182 return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(ShAmtReg); }}};
7183}
7184
7185/// Helper to select an immediate value that can be represented as a 12-bit
7186/// value shifted left by either 0 or 12. If it is possible to do so, return
7187/// the immediate and shift value. If not, return std::nullopt.
7188///
7189/// Used by selectArithImmed and selectNegArithImmed.
7190InstructionSelector::ComplexRendererFns
7191AArch64InstructionSelector::select12BitValueWithLeftShift(
7192 uint64_t Immed) const {
7193 unsigned ShiftAmt;
7194 if (Immed >> 12 == 0) {
7195 ShiftAmt = 0;
7196 } else if ((Immed & 0xfff) == 0 && Immed >> 24 == 0) {
7197 ShiftAmt = 12;
7198 Immed = Immed >> 12;
7199 } else
7200 return std::nullopt;
7201
7202 unsigned ShVal = AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftAmt);
7203 return {{
7204 [=](MachineInstrBuilder &MIB) { MIB.addImm(Immed); },
7205 [=](MachineInstrBuilder &MIB) { MIB.addImm(ShVal); },
7206 }};
7207}
7208
7209/// SelectArithImmed - Select an immediate value that can be represented as
7210/// a 12-bit value shifted left by either 0 or 12. If so, return true with
7211/// Val set to the 12-bit value and Shift set to the shifter operand.
7212InstructionSelector::ComplexRendererFns
7213AArch64InstructionSelector::selectArithImmed(MachineOperand &Root) const {
7214 // This function is called from the addsub_shifted_imm ComplexPattern,
7215 // which lists [imm] as the list of opcode it's interested in, however
7216 // we still need to check whether the operand is actually an immediate
7217 // here because the ComplexPattern opcode list is only used in
7218 // root-level opcode matching.
7219 auto MaybeImmed = getImmedFromMO(Root);
7220 if (MaybeImmed == std::nullopt)
7221 return std::nullopt;
7222 return select12BitValueWithLeftShift(*MaybeImmed);
7223}
7224
7225/// SelectNegArithImmed - As above, but negates the value before trying to
7226/// select it.
7227InstructionSelector::ComplexRendererFns
7228AArch64InstructionSelector::selectNegArithImmed(MachineOperand &Root) const {
7229 // We need a register here, because we need to know if we have a 64 or 32
7230 // bit immediate.
7231 if (!Root.isReg())
7232 return std::nullopt;
7233 auto MaybeImmed = getImmedFromMO(Root);
7234 if (MaybeImmed == std::nullopt)
7235 return std::nullopt;
7236 uint64_t Immed = *MaybeImmed;
7237
7238 // This negation is almost always valid, but "cmp wN, #0" and "cmn wN, #0"
7239 // have the opposite effect on the C flag, so this pattern mustn't match under
7240 // those circumstances.
7241 if (Immed == 0)
7242 return std::nullopt;
7243
7244 // Check if we're dealing with a 32-bit type on the root or a 64-bit type on
7245 // the root.
7246 MachineRegisterInfo &MRI = Root.getParent()->getMF()->getRegInfo();
7247 if (MRI.getType(Root.getReg()).getSizeInBits() == 32)
7248 Immed = ~((uint32_t)Immed) + 1;
7249 else
7250 Immed = ~Immed + 1ULL;
7251
7252 if (Immed & 0xFFFFFFFFFF000000ULL)
7253 return std::nullopt;
7254
7255 Immed &= 0xFFFFFFULL;
7256 return select12BitValueWithLeftShift(Immed);
7257}
7258
7259/// Checks if we are sure that folding MI into load/store addressing mode is
7260/// beneficial or not.
7261///
7262/// Returns:
7263/// - true if folding MI would be beneficial.
7264/// - false if folding MI would be bad.
7265/// - std::nullopt if it is not sure whether folding MI is beneficial.
7266///
7267/// \p MI can be the offset operand of G_PTR_ADD, e.g. G_SHL in the example:
7268///
7269/// %13:gpr(s64) = G_CONSTANT i64 1
7270/// %8:gpr(s64) = G_SHL %6, %13(s64)
7271/// %9:gpr(p0) = G_PTR_ADD %0, %8(s64)
7272/// %12:gpr(s32) = G_LOAD %9(p0) :: (load (s16))
7273std::optional<bool> AArch64InstructionSelector::isWorthFoldingIntoAddrMode(
7274 const MachineInstr &MI, const MachineRegisterInfo &MRI) const {
7275 if (MI.getOpcode() == AArch64::G_SHL) {
7276 // Address operands with shifts are free, except for running on subtargets
7277 // with AddrLSLSlow14.
7278 if (const auto ValAndVeg = getIConstantVRegValWithLookThrough(
7279 MI.getOperand(2).getReg(), MRI)) {
7280 const APInt ShiftVal = ValAndVeg->Value;
7281
7282 // Don't fold if we know this will be slow.
7283 return !(STI.hasAddrLSLSlow14() && (ShiftVal == 1 || ShiftVal == 4));
7284 }
7285 }
7286 return std::nullopt;
7287}
7288
7289/// Return true if it is worth folding MI into an extended register. That is,
7290/// if it's safe to pull it into the addressing mode of a load or store as a
7291/// shift.
7292/// \p IsAddrOperand whether the def of MI is used as an address operand
7293/// (e.g. feeding into an LDR/STR).
7294bool AArch64InstructionSelector::isWorthFoldingIntoExtendedReg(
7295 const MachineInstr &MI, const MachineRegisterInfo &MRI,
7296 bool IsAddrOperand) const {
7297
7298 // Always fold if there is one use, or if we're optimizing for size.
7299 Register DefReg = MI.getOperand(0).getReg();
7300 if (MRI.hasOneNonDBGUse(DefReg) ||
7301 MI.getParent()->getParent()->getFunction().hasOptSize())
7302 return true;
7303
7304 if (IsAddrOperand) {
7305 // If we are already sure that folding MI is good or bad, return the result.
7306 if (const auto Worth = isWorthFoldingIntoAddrMode(MI, MRI))
7307 return *Worth;
7308
7309 // Fold G_PTR_ADD if its offset operand can be folded
7310 if (MI.getOpcode() == AArch64::G_PTR_ADD) {
7311 MachineInstr *OffsetInst =
7312 getDefIgnoringCopies(MI.getOperand(2).getReg(), MRI);
7313
7314 // Note, we already know G_PTR_ADD is used by at least two instructions.
7315 // If we are also sure about whether folding is beneficial or not,
7316 // return the result.
7317 if (const auto Worth = isWorthFoldingIntoAddrMode(*OffsetInst, MRI))
7318 return *Worth;
7319 }
7320 }
7321
7322 // FIXME: Consider checking HasALULSLFast as appropriate.
7323
7324 // We have a fastpath, so folding a shift in and potentially computing it
7325 // many times may be beneficial. Check if this is only used in memory ops.
7326 // If it is, then we should fold.
7327 return all_of(MRI.use_nodbg_instructions(DefReg),
7328 [](MachineInstr &Use) { return Use.mayLoadOrStore(); });
7329}
7330
7331InstructionSelector::ComplexRendererFns
7332AArch64InstructionSelector::selectExtendedSHL(
7333 MachineOperand &Root, MachineOperand &Base, MachineOperand &Offset,
7334 unsigned SizeInBytes, bool WantsExt) const {
7335 assert(Base.isReg() && "Expected base to be a register operand");
7336 assert(Offset.isReg() && "Expected offset to be a register operand");
7337
7338 MachineRegisterInfo &MRI = Root.getParent()->getMF()->getRegInfo();
7339 MachineInstr *OffsetInst = MRI.getVRegDef(Offset.getReg());
7340
7341 unsigned OffsetOpc = OffsetInst->getOpcode();
7342 bool LookedThroughZExt = false;
7343 if (OffsetOpc != TargetOpcode::G_SHL && OffsetOpc != TargetOpcode::G_MUL) {
7344 // Try to look through a ZEXT.
7345 if (OffsetOpc != TargetOpcode::G_ZEXT || !WantsExt)
7346 return std::nullopt;
7347
7348 OffsetInst = MRI.getVRegDef(OffsetInst->getOperand(1).getReg());
7349 OffsetOpc = OffsetInst->getOpcode();
7350 LookedThroughZExt = true;
7351
7352 if (OffsetOpc != TargetOpcode::G_SHL && OffsetOpc != TargetOpcode::G_MUL)
7353 return std::nullopt;
7354 }
7355 // Make sure that the memory op is a valid size.
7356 int64_t LegalShiftVal = Log2_32(SizeInBytes);
7357 if (LegalShiftVal == 0)
7358 return std::nullopt;
7359 if (!isWorthFoldingIntoExtendedReg(*OffsetInst, MRI, true))
7360 return std::nullopt;
7361
7362 // Now, try to find the specific G_CONSTANT. Start by assuming that the
7363 // register we will offset is the LHS, and the register containing the
7364 // constant is the RHS.
7365 Register OffsetReg = OffsetInst->getOperand(1).getReg();
7366 Register ConstantReg = OffsetInst->getOperand(2).getReg();
7367 auto ValAndVReg = getIConstantVRegValWithLookThrough(ConstantReg, MRI);
7368 if (!ValAndVReg) {
7369 // We didn't get a constant on the RHS. If the opcode is a shift, then
7370 // we're done.
7371 if (OffsetOpc == TargetOpcode::G_SHL)
7372 return std::nullopt;
7373
7374 // If we have a G_MUL, we can use either register. Try looking at the RHS.
7375 std::swap(OffsetReg, ConstantReg);
7376 ValAndVReg = getIConstantVRegValWithLookThrough(ConstantReg, MRI);
7377 if (!ValAndVReg)
7378 return std::nullopt;
7379 }
7380
7381 // The value must fit into 3 bits, and must be positive. Make sure that is
7382 // true.
7383 int64_t ImmVal = ValAndVReg->Value.getSExtValue();
7384
7385 // Since we're going to pull this into a shift, the constant value must be
7386 // a power of 2. If we got a multiply, then we need to check this.
7387 if (OffsetOpc == TargetOpcode::G_MUL) {
7388 if (!llvm::has_single_bit<uint32_t>(ImmVal))
7389 return std::nullopt;
7390
7391 // Got a power of 2. So, the amount we'll shift is the log base-2 of that.
7392 ImmVal = Log2_32(ImmVal);
7393 }
7394
7395 if ((ImmVal & 0x7) != ImmVal)
7396 return std::nullopt;
7397
7398 // We are only allowed to shift by LegalShiftVal. This shift value is built
7399 // into the instruction, so we can't just use whatever we want.
7400 if (ImmVal != LegalShiftVal)
7401 return std::nullopt;
7402
7403 unsigned SignExtend = 0;
7404 if (WantsExt) {
7405 // Check if the offset is defined by an extend, unless we looked through a
7406 // G_ZEXT earlier.
7407 if (!LookedThroughZExt) {
7408 MachineInstr *ExtInst = getDefIgnoringCopies(OffsetReg, MRI);
7409 auto Ext = getExtendTypeForInst(*ExtInst, MRI, true);
7411 return std::nullopt;
7412
7413 SignExtend = AArch64_AM::isSignExtendShiftType(Ext) ? 1 : 0;
7414 // We only support SXTW for signed extension here.
7415 if (SignExtend && Ext != AArch64_AM::SXTW)
7416 return std::nullopt;
7417 OffsetReg = ExtInst->getOperand(1).getReg();
7418 }
7419
7420 // Need a 32-bit wide register here.
7421 MachineIRBuilder MIB(*MRI.getVRegDef(Root.getReg()));
7422 OffsetReg = moveScalarRegClass(OffsetReg, AArch64::GPR32RegClass, MIB);
7423 }
7424
7425 // We can use the LHS of the GEP as the base, and the LHS of the shift as an
7426 // offset. Signify that we are shifting by setting the shift flag to 1.
7427 return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(Base.getReg()); },
7428 [=](MachineInstrBuilder &MIB) { MIB.addUse(OffsetReg); },
7429 [=](MachineInstrBuilder &MIB) {
7430 // Need to add both immediates here to make sure that they are both
7431 // added to the instruction.
7432 MIB.addImm(SignExtend);
7433 MIB.addImm(1);
7434 }}};
7435}
7436
7437/// This is used for computing addresses like this:
7438///
7439/// ldr x1, [x2, x3, lsl #3]
7440///
7441/// Where x2 is the base register, and x3 is an offset register. The shift-left
7442/// is a constant value specific to this load instruction. That is, we'll never
7443/// see anything other than a 3 here (which corresponds to the size of the
7444/// element being loaded.)
7445InstructionSelector::ComplexRendererFns
7446AArch64InstructionSelector::selectAddrModeShiftedExtendXReg(
7447 MachineOperand &Root, unsigned SizeInBytes) const {
7448 if (!Root.isReg())
7449 return std::nullopt;
7450 MachineRegisterInfo &MRI = Root.getParent()->getMF()->getRegInfo();
7451
7452 // We want to find something like this:
7453 //
7454 // val = G_CONSTANT LegalShiftVal
7455 // shift = G_SHL off_reg val
7456 // ptr = G_PTR_ADD base_reg shift
7457 // x = G_LOAD ptr
7458 //
7459 // And fold it into this addressing mode:
7460 //
7461 // ldr x, [base_reg, off_reg, lsl #LegalShiftVal]
7462
7463 // Check if we can find the G_PTR_ADD.
7464 MachineInstr *PtrAdd =
7465 getOpcodeDef(TargetOpcode::G_PTR_ADD, Root.getReg(), MRI);
7466 if (!PtrAdd || !isWorthFoldingIntoExtendedReg(*PtrAdd, MRI, true))
7467 return std::nullopt;
7468
7469 // Now, try to match an opcode which will match our specific offset.
7470 // We want a G_SHL or a G_MUL.
7471 MachineInstr *OffsetInst =
7473 return selectExtendedSHL(Root, PtrAdd->getOperand(1),
7474 OffsetInst->getOperand(0), SizeInBytes,
7475 /*WantsExt=*/false);
7476}
7477
7478/// This is used for computing addresses like this:
7479///
7480/// ldr x1, [x2, x3]
7481///
7482/// Where x2 is the base register, and x3 is an offset register.
7483///
7484/// When possible (or profitable) to fold a G_PTR_ADD into the address
7485/// calculation, this will do so. Otherwise, it will return std::nullopt.
7486InstructionSelector::ComplexRendererFns
7487AArch64InstructionSelector::selectAddrModeRegisterOffset(
7488 MachineOperand &Root) const {
7489 MachineRegisterInfo &MRI = Root.getParent()->getMF()->getRegInfo();
7490
7491 // We need a GEP.
7493 if (!mi_match(Root.getReg(), MRI, m_GPtrAdd(m_Reg(Base), m_Reg(Offset))))
7494 return std::nullopt;
7495
7496 // If this is used more than once, let's not bother folding.
7497 // TODO: Check if they are memory ops. If they are, then we can still fold
7498 // without having to recompute anything.
7499 if (!MRI.hasOneNonDBGUse(Root.getReg()))
7500 return std::nullopt;
7501
7502 // Base is the GEP's LHS, offset is its RHS.
7503 return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(Base); },
7504 [=](MachineInstrBuilder &MIB) { MIB.addUse(Offset); },
7505 [=](MachineInstrBuilder &MIB) {
7506 // Need to add both immediates here to make sure that they are both
7507 // added to the instruction.
7508 MIB.addImm(0);
7509 MIB.addImm(0);
7510 }}};
7511}
7512
7513/// This is intended to be equivalent to selectAddrModeXRO in
7514/// AArch64ISelDAGtoDAG. It's used for selecting X register offset loads.
7515InstructionSelector::ComplexRendererFns
7516AArch64InstructionSelector::selectAddrModeXRO(MachineOperand &Root,
7517 unsigned SizeInBytes) const {
7518 MachineRegisterInfo &MRI = Root.getParent()->getMF()->getRegInfo();
7519 if (!Root.isReg())
7520 return std::nullopt;
7521 MachineInstr *PtrAdd =
7522 getOpcodeDef(TargetOpcode::G_PTR_ADD, Root.getReg(), MRI);
7523 if (!PtrAdd)
7524 return std::nullopt;
7525
7526 // Check for an immediates which cannot be encoded in the [base + imm]
7527 // addressing mode, and can't be encoded in an add/sub. If this happens, we'll
7528 // end up with code like:
7529 //
7530 // mov x0, wide
7531 // add x1 base, x0
7532 // ldr x2, [x1, x0]
7533 //
7534 // In this situation, we can use the [base, xreg] addressing mode to save an
7535 // add/sub:
7536 //
7537 // mov x0, wide
7538 // ldr x2, [base, x0]
7539 auto ValAndVReg =
7541 if (ValAndVReg) {
7542 unsigned Scale = Log2_32(SizeInBytes);
7543 int64_t ImmOff = ValAndVReg->Value.getSExtValue();
7544
7545 // Skip immediates that can be selected in the load/store addressing
7546 // mode.
7547 if (ImmOff % SizeInBytes == 0 && ImmOff >= 0 &&
7548 ImmOff < (0x1000 << Scale))
7549 return std::nullopt;
7550
7551 // Helper lambda to decide whether or not it is preferable to emit an add.
7552 auto isPreferredADD = [](int64_t ImmOff) {
7553 // Constants in [0x0, 0xfff] can be encoded in an add.
7554 if ((ImmOff & 0xfffffffffffff000LL) == 0x0LL)
7555 return true;
7556
7557 // Can it be encoded in an add lsl #12?
7558 if ((ImmOff & 0xffffffffff000fffLL) != 0x0LL)
7559 return false;
7560
7561 // It can be encoded in an add lsl #12, but we may not want to. If it is
7562 // possible to select this as a single movz, then prefer that. A single
7563 // movz is faster than an add with a shift.
7564 return (ImmOff & 0xffffffffff00ffffLL) != 0x0LL &&
7565 (ImmOff & 0xffffffffffff0fffLL) != 0x0LL;
7566 };
7567
7568 // If the immediate can be encoded in a single add/sub, then bail out.
7569 if (isPreferredADD(ImmOff) || isPreferredADD(-ImmOff))
7570 return std::nullopt;
7571 }
7572
7573 // Try to fold shifts into the addressing mode.
7574 auto AddrModeFns = selectAddrModeShiftedExtendXReg(Root, SizeInBytes);
7575 if (AddrModeFns)
7576 return AddrModeFns;
7577
7578 // If that doesn't work, see if it's possible to fold in registers from
7579 // a GEP.
7580 return selectAddrModeRegisterOffset(Root);
7581}
7582
7583/// This is used for computing addresses like this:
7584///
7585/// ldr x0, [xBase, wOffset, sxtw #LegalShiftVal]
7586///
7587/// Where we have a 64-bit base register, a 32-bit offset register, and an
7588/// extend (which may or may not be signed).
7589InstructionSelector::ComplexRendererFns
7590AArch64InstructionSelector::selectAddrModeWRO(MachineOperand &Root,
7591 unsigned SizeInBytes) const {
7592 MachineRegisterInfo &MRI = Root.getParent()->getMF()->getRegInfo();
7593
7594 MachineInstr *PtrAdd =
7595 getOpcodeDef(TargetOpcode::G_PTR_ADD, Root.getReg(), MRI);
7596 if (!PtrAdd || !isWorthFoldingIntoExtendedReg(*PtrAdd, MRI, true))
7597 return std::nullopt;
7598
7599 MachineOperand &LHS = PtrAdd->getOperand(1);
7600 MachineOperand &RHS = PtrAdd->getOperand(2);
7601 MachineInstr *OffsetInst = getDefIgnoringCopies(RHS.getReg(), MRI);
7602
7603 // The first case is the same as selectAddrModeXRO, except we need an extend.
7604 // In this case, we try to find a shift and extend, and fold them into the
7605 // addressing mode.
7606 //
7607 // E.g.
7608 //
7609 // off_reg = G_Z/S/ANYEXT ext_reg
7610 // val = G_CONSTANT LegalShiftVal
7611 // shift = G_SHL off_reg val
7612 // ptr = G_PTR_ADD base_reg shift
7613 // x = G_LOAD ptr
7614 //
7615 // In this case we can get a load like this:
7616 //
7617 // ldr x0, [base_reg, ext_reg, sxtw #LegalShiftVal]
7618 auto ExtendedShl = selectExtendedSHL(Root, LHS, OffsetInst->getOperand(0),
7619 SizeInBytes, /*WantsExt=*/true);
7620 if (ExtendedShl)
7621 return ExtendedShl;
7622
7623 // There was no shift. We can try and fold a G_Z/S/ANYEXT in alone though.
7624 //
7625 // e.g.
7626 // ldr something, [base_reg, ext_reg, sxtw]
7627 if (!isWorthFoldingIntoExtendedReg(*OffsetInst, MRI, true))
7628 return std::nullopt;
7629
7630 // Check if this is an extend. We'll get an extend type if it is.
7632 getExtendTypeForInst(*OffsetInst, MRI, /*IsLoadStore=*/true);
7634 return std::nullopt;
7635
7636 // Need a 32-bit wide register.
7637 MachineIRBuilder MIB(*PtrAdd);
7638 Register ExtReg = moveScalarRegClass(OffsetInst->getOperand(1).getReg(),
7639 AArch64::GPR32RegClass, MIB);
7640 unsigned SignExtend = Ext == AArch64_AM::SXTW;
7641
7642 // Base is LHS, offset is ExtReg.
7643 return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(LHS.getReg()); },
7644 [=](MachineInstrBuilder &MIB) { MIB.addUse(ExtReg); },
7645 [=](MachineInstrBuilder &MIB) {
7646 MIB.addImm(SignExtend);
7647 MIB.addImm(0);
7648 }}};
7649}
7650
7651/// Select a "register plus unscaled signed 9-bit immediate" address. This
7652/// should only match when there is an offset that is not valid for a scaled
7653/// immediate addressing mode. The "Size" argument is the size in bytes of the
7654/// memory reference, which is needed here to know what is valid for a scaled
7655/// immediate.
7656InstructionSelector::ComplexRendererFns
7657AArch64InstructionSelector::selectAddrModeUnscaled(MachineOperand &Root,
7658 unsigned Size) const {
7659 MachineRegisterInfo &MRI =
7660 Root.getParent()->getParent()->getParent()->getRegInfo();
7661
7662 if (!Root.isReg())
7663 return std::nullopt;
7664
7665 if (!isBaseWithConstantOffset(Root, MRI))
7666 return std::nullopt;
7667
7668 MachineInstr *RootDef = MRI.getVRegDef(Root.getReg());
7669
7670 MachineOperand &OffImm = RootDef->getOperand(2);
7671 if (!OffImm.isReg())
7672 return std::nullopt;
7673 MachineInstr *RHS = MRI.getVRegDef(OffImm.getReg());
7674 if (RHS->getOpcode() != TargetOpcode::G_CONSTANT)
7675 return std::nullopt;
7676 int64_t RHSC;
7677 MachineOperand &RHSOp1 = RHS->getOperand(1);
7678 if (!RHSOp1.isCImm() || RHSOp1.getCImm()->getBitWidth() > 64)
7679 return std::nullopt;
7680 RHSC = RHSOp1.getCImm()->getSExtValue();
7681
7682 if (RHSC >= -256 && RHSC < 256) {
7683 MachineOperand &Base = RootDef->getOperand(1);
7684 return {{
7685 [=](MachineInstrBuilder &MIB) { MIB.add(Base); },
7686 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC); },
7687 }};
7688 }
7689 return std::nullopt;
7690}
7691
7692InstructionSelector::ComplexRendererFns
7693AArch64InstructionSelector::tryFoldAddLowIntoImm(MachineInstr &RootDef,
7694 unsigned Size,
7695 MachineRegisterInfo &MRI) const {
7696 if (RootDef.getOpcode() != AArch64::G_ADD_LOW)
7697 return std::nullopt;
7698 MachineInstr &Adrp = *MRI.getVRegDef(RootDef.getOperand(1).getReg());
7699 if (Adrp.getOpcode() != AArch64::ADRP)
7700 return std::nullopt;
7701
7702 // TODO: add heuristics like isWorthFoldingADDlow() from SelectionDAG.
7703 auto Offset = Adrp.getOperand(1).getOffset();
7704 if (Offset % Size != 0)
7705 return std::nullopt;
7706
7707 auto GV = Adrp.getOperand(1).getGlobal();
7708 if (GV->isThreadLocal())
7709 return std::nullopt;
7710
7711 auto &MF = *RootDef.getParent()->getParent();
7712 if (GV->getPointerAlignment(MF.getDataLayout()) < Size)
7713 return std::nullopt;
7714
7715 unsigned OpFlags = STI.ClassifyGlobalReference(GV, MF.getTarget());
7716 MachineIRBuilder MIRBuilder(RootDef);
7717 Register AdrpReg = Adrp.getOperand(0).getReg();
7718 return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(AdrpReg); },
7719 [=](MachineInstrBuilder &MIB) {
7720 MIB.addGlobalAddress(GV, Offset,
7721 OpFlags | AArch64II::MO_PAGEOFF |
7723 }}};
7724}
7725
7726/// Select a "register plus scaled unsigned 12-bit immediate" address. The
7727/// "Size" argument is the size in bytes of the memory reference, which
7728/// determines the scale.
7729InstructionSelector::ComplexRendererFns
7730AArch64InstructionSelector::selectAddrModeIndexed(MachineOperand &Root,
7731 unsigned Size) const {
7732 MachineFunction &MF = *Root.getParent()->getParent()->getParent();
7733 MachineRegisterInfo &MRI = MF.getRegInfo();
7734
7735 if (!Root.isReg())
7736 return std::nullopt;
7737
7738 MachineInstr *RootDef = MRI.getVRegDef(Root.getReg());
7739 if (RootDef->getOpcode() == TargetOpcode::G_FRAME_INDEX) {
7740 return {{
7741 [=](MachineInstrBuilder &MIB) { MIB.add(RootDef->getOperand(1)); },
7742 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },
7743 }};
7744 }
7745
7747 // Check if we can fold in the ADD of small code model ADRP + ADD address.
7748 // HACK: ld64 on Darwin doesn't support relocations on PRFM, so we can't fold
7749 // globals into the offset.
7750 MachineInstr *RootParent = Root.getParent();
7751 if (CM == CodeModel::Small &&
7752 !(RootParent->getOpcode() == AArch64::G_AARCH64_PREFETCH &&
7753 STI.isTargetDarwin())) {
7754 auto OpFns = tryFoldAddLowIntoImm(*RootDef, Size, MRI);
7755 if (OpFns)
7756 return OpFns;
7757 }
7758
7759 if (isBaseWithConstantOffset(Root, MRI)) {
7760 MachineOperand &LHS = RootDef->getOperand(1);
7761 MachineOperand &RHS = RootDef->getOperand(2);
7762 MachineInstr *LHSDef = MRI.getVRegDef(LHS.getReg());
7763 MachineInstr *RHSDef = MRI.getVRegDef(RHS.getReg());
7764
7765 int64_t RHSC = (int64_t)RHSDef->getOperand(1).getCImm()->getZExtValue();
7766 unsigned Scale = Log2_32(Size);
7767 if ((RHSC & (Size - 1)) == 0 && RHSC >= 0 && RHSC < (0x1000 << Scale)) {
7768 if (LHSDef->getOpcode() == TargetOpcode::G_FRAME_INDEX)
7769 return {{
7770 [=](MachineInstrBuilder &MIB) { MIB.add(LHSDef->getOperand(1)); },
7771 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC >> Scale); },
7772 }};
7773
7774 return {{
7775 [=](MachineInstrBuilder &MIB) { MIB.add(LHS); },
7776 [=](MachineInstrBuilder &MIB) { MIB.addImm(RHSC >> Scale); },
7777 }};
7778 }
7779 }
7780
7781 // Before falling back to our general case, check if the unscaled
7782 // instructions can handle this. If so, that's preferable.
7783 if (selectAddrModeUnscaled(Root, Size))
7784 return std::nullopt;
7785
7786 return {{
7787 [=](MachineInstrBuilder &MIB) { MIB.add(Root); },
7788 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },
7789 }};
7790}
7791
7792/// Given a shift instruction, return the correct shift type for that
7793/// instruction.
7795 switch (MI.getOpcode()) {
7796 default:
7798 case TargetOpcode::G_SHL:
7799 return AArch64_AM::LSL;
7800 case TargetOpcode::G_LSHR:
7801 return AArch64_AM::LSR;
7802 case TargetOpcode::G_ASHR:
7803 return AArch64_AM::ASR;
7804 case TargetOpcode::G_ROTR:
7805 return AArch64_AM::ROR;
7806 }
7807}
7808
7809/// Select a "shifted register" operand. If the value is not shifted, set the
7810/// shift operand to a default value of "lsl 0".
7811InstructionSelector::ComplexRendererFns
7812AArch64InstructionSelector::selectShiftedRegister(MachineOperand &Root,
7813 bool AllowROR) const {
7814 if (!Root.isReg())
7815 return std::nullopt;
7816 MachineRegisterInfo &MRI =
7817 Root.getParent()->getParent()->getParent()->getRegInfo();
7818
7819 // Check if the operand is defined by an instruction which corresponds to
7820 // a ShiftExtendType. E.g. a G_SHL, G_LSHR, etc.
7821 MachineInstr *ShiftInst = MRI.getVRegDef(Root.getReg());
7823 if (ShType == AArch64_AM::InvalidShiftExtend)
7824 return std::nullopt;
7825 if (ShType == AArch64_AM::ROR && !AllowROR)
7826 return std::nullopt;
7827 if (!isWorthFoldingIntoExtendedReg(*ShiftInst, MRI, false))
7828 return std::nullopt;
7829
7830 // Need an immediate on the RHS.
7831 MachineOperand &ShiftRHS = ShiftInst->getOperand(2);
7832 auto Immed = getImmedFromMO(ShiftRHS);
7833 if (!Immed)
7834 return std::nullopt;
7835
7836 // We have something that we can fold. Fold in the shift's LHS and RHS into
7837 // the instruction.
7838 MachineOperand &ShiftLHS = ShiftInst->getOperand(1);
7839 Register ShiftReg = ShiftLHS.getReg();
7840
7841 unsigned NumBits = MRI.getType(ShiftReg).getSizeInBits();
7842 unsigned Val = *Immed & (NumBits - 1);
7843 unsigned ShiftVal = AArch64_AM::getShifterImm(ShType, Val);
7844
7845 return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(ShiftReg); },
7846 [=](MachineInstrBuilder &MIB) { MIB.addImm(ShiftVal); }}};
7847}
7848
7849AArch64_AM::ShiftExtendType AArch64InstructionSelector::getExtendTypeForInst(
7850 MachineInstr &MI, MachineRegisterInfo &MRI, bool IsLoadStore) const {
7851 unsigned Opc = MI.getOpcode();
7852
7853 // Handle explicit extend instructions first.
7854 if (Opc == TargetOpcode::G_SEXT || Opc == TargetOpcode::G_SEXT_INREG) {
7855 unsigned Size;
7856 if (Opc == TargetOpcode::G_SEXT)
7857 Size = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
7858 else
7859 Size = MI.getOperand(2).getImm();
7860 assert(Size != 64 && "Extend from 64 bits?");
7861 switch (Size) {
7862 case 8:
7863 return IsLoadStore ? AArch64_AM::InvalidShiftExtend : AArch64_AM::SXTB;
7864 case 16:
7865 return IsLoadStore ? AArch64_AM::InvalidShiftExtend : AArch64_AM::SXTH;
7866 case 32:
7867 return AArch64_AM::SXTW;
7868 default:
7870 }
7871 }
7872
7873 if (Opc == TargetOpcode::G_ZEXT || Opc == TargetOpcode::G_ANYEXT) {
7874 unsigned Size = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
7875 assert(Size != 64 && "Extend from 64 bits?");
7876 switch (Size) {
7877 case 8:
7878 return IsLoadStore ? AArch64_AM::InvalidShiftExtend : AArch64_AM::UXTB;
7879 case 16:
7880 return IsLoadStore ? AArch64_AM::InvalidShiftExtend : AArch64_AM::UXTH;
7881 case 32:
7882 return AArch64_AM::UXTW;
7883 default:
7885 }
7886 }
7887
7888 // Don't have an explicit extend. Try to handle a G_AND with a constant mask
7889 // on the RHS.
7890 if (Opc != TargetOpcode::G_AND)
7892
7893 std::optional<uint64_t> MaybeAndMask = getImmedFromMO(MI.getOperand(2));
7894 if (!MaybeAndMask)
7896 uint64_t AndMask = *MaybeAndMask;
7897 switch (AndMask) {
7898 default:
7900 case 0xFF:
7901 return !IsLoadStore ? AArch64_AM::UXTB : AArch64_AM::InvalidShiftExtend;
7902 case 0xFFFF:
7903 return !IsLoadStore ? AArch64_AM::UXTH : AArch64_AM::InvalidShiftExtend;
7904 case 0xFFFFFFFF:
7905 return AArch64_AM::UXTW;
7906 }
7907}
7908
7909Register AArch64InstructionSelector::moveScalarRegClass(
7910 Register Reg, const TargetRegisterClass &RC, MachineIRBuilder &MIB) const {
7911 MachineRegisterInfo &MRI = *MIB.getMRI();
7912 auto Ty = MRI.getType(Reg);
7913 assert(!Ty.isVector() && "Expected scalars only!");
7914 if (Ty.getSizeInBits() == TRI.getRegSizeInBits(RC))
7915 return Reg;
7916
7917 // Create a copy and immediately select it.
7918 // FIXME: We should have an emitCopy function?
7919 auto Copy = MIB.buildCopy({&RC}, {Reg});
7920 selectCopy(*Copy, TII, MRI, TRI, RBI);
7921 return Copy.getReg(0);
7922}
7923
7924/// Select an "extended register" operand. This operand folds in an extend
7925/// followed by an optional left shift.
7926InstructionSelector::ComplexRendererFns
7927AArch64InstructionSelector::selectArithExtendedRegister(
7928 MachineOperand &Root) const {
7929 if (!Root.isReg())
7930 return std::nullopt;
7931 MachineRegisterInfo &MRI =
7932 Root.getParent()->getParent()->getParent()->getRegInfo();
7933
7934 uint64_t ShiftVal = 0;
7935 Register ExtReg;
7937 MachineInstr *RootDef = getDefIgnoringCopies(Root.getReg(), MRI);
7938 if (!RootDef)
7939 return std::nullopt;
7940
7941 if (!isWorthFoldingIntoExtendedReg(*RootDef, MRI, false))
7942 return std::nullopt;
7943
7944 // Check if we can fold a shift and an extend.
7945 if (RootDef->getOpcode() == TargetOpcode::G_SHL) {
7946 // Look for a constant on the RHS of the shift.
7947 MachineOperand &RHS = RootDef->getOperand(2);
7948 std::optional<uint64_t> MaybeShiftVal = getImmedFromMO(RHS);
7949 if (!MaybeShiftVal)
7950 return std::nullopt;
7951 ShiftVal = *MaybeShiftVal;
7952 if (ShiftVal > 4)
7953 return std::nullopt;
7954 // Look for a valid extend instruction on the LHS of the shift.
7955 MachineOperand &LHS = RootDef->getOperand(1);
7956 MachineInstr *ExtDef = getDefIgnoringCopies(LHS.getReg(), MRI);
7957 if (!ExtDef)
7958 return std::nullopt;
7959 Ext = getExtendTypeForInst(*ExtDef, MRI);
7961 return std::nullopt;
7962 ExtReg = ExtDef->getOperand(1).getReg();
7963 } else {
7964 // Didn't get a shift. Try just folding an extend.
7965 Ext = getExtendTypeForInst(*RootDef, MRI);
7967 return std::nullopt;
7968 ExtReg = RootDef->getOperand(1).getReg();
7969
7970 // If we have a 32 bit instruction which zeroes out the high half of a
7971 // register, we get an implicit zero extend for free. Check if we have one.
7972 // FIXME: We actually emit the extend right now even though we don't have
7973 // to.
7974 if (Ext == AArch64_AM::UXTW && MRI.getType(ExtReg).getSizeInBits() == 32) {
7975 MachineInstr *ExtInst = MRI.getVRegDef(ExtReg);
7976 if (isDef32(*ExtInst))
7977 return std::nullopt;
7978 }
7979 }
7980
7981 // We require a GPR32 here. Narrow the ExtReg if needed using a subregister
7982 // copy.
7983 MachineIRBuilder MIB(*RootDef);
7984 ExtReg = moveScalarRegClass(ExtReg, AArch64::GPR32RegClass, MIB);
7985
7986 return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(ExtReg); },
7987 [=](MachineInstrBuilder &MIB) {
7988 MIB.addImm(getArithExtendImm(Ext, ShiftVal));
7989 }}};
7990}
7991
7992InstructionSelector::ComplexRendererFns
7993AArch64InstructionSelector::selectExtractHigh(MachineOperand &Root) const {
7994 if (!Root.isReg())
7995 return std::nullopt;
7996 MachineRegisterInfo &MRI =
7997 Root.getParent()->getParent()->getParent()->getRegInfo();
7998
7999 auto Extract = getDefSrcRegIgnoringCopies(Root.getReg(), MRI);
8000 while (Extract && Extract->MI->getOpcode() == TargetOpcode::G_BITCAST &&
8001 STI.isLittleEndian())
8002 Extract =
8003 getDefSrcRegIgnoringCopies(Extract->MI->getOperand(1).getReg(), MRI);
8004 if (!Extract)
8005 return std::nullopt;
8006
8007 if (auto *Unmerge = dyn_cast<GUnmerge>(Extract->MI)) {
8008 if (Unmerge->getNumDefs() == 2 &&
8009 Extract->Reg == Unmerge->getOperand(1).getReg()) {
8010 Register ExtReg = Unmerge->getSourceReg();
8011 return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(ExtReg); }}};
8012 }
8013 }
8014 if (auto *ExtElt = dyn_cast<GExtractVectorElement>(Extract->MI)) {
8015 LLT SrcTy = MRI.getType(ExtElt->getVectorReg());
8016 auto LaneIdx =
8017 getIConstantVRegValWithLookThrough(ExtElt->getIndexReg(), MRI);
8018 if (LaneIdx && SrcTy == LLT::fixed_vector(2, 64) &&
8019 LaneIdx->Value.getSExtValue() == 1) {
8020 Register ExtReg = ExtElt->getVectorReg();
8021 return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(ExtReg); }}};
8022 }
8023 }
8024 if (auto *Subvec = dyn_cast<GExtractSubvector>(Extract->MI)) {
8025 LLT SrcTy = MRI.getType(Subvec->getSrcVec());
8026 auto LaneIdx = Subvec->getIndexImm();
8027 if (LaneIdx == SrcTy.getNumElements() / 2) {
8028 Register ExtReg = Subvec->getSrcVec();
8029 return {{[=](MachineInstrBuilder &MIB) { MIB.addUse(ExtReg); }}};
8030 }
8031 }
8032
8033 return std::nullopt;
8034}
8035
8036InstructionSelector::ComplexRendererFns
8037AArch64InstructionSelector::selectCVTFixedPointBase(const MachineOperand &Root,
8038 unsigned DstElemWidth,
8039 bool isReciprocal) const {
8040 if (!Root.isReg())
8041 return std::nullopt;
8042 const MachineRegisterInfo &MRI =
8043 Root.getParent()->getParent()->getParent()->getRegInfo();
8044
8045 Register Reg = Root.getReg();
8046 MachineInstr *Dup = getDefIgnoringCopies(Reg, MRI);
8047
8048 if (Dup && Dup->getOpcode() == TargetOpcode::G_SPLAT_VECTOR)
8049 Reg = Dup->getOperand(1).getReg();
8050
8051 std::optional<ValueAndVReg> CstVal =
8053
8054 if (!CstVal)
8055 return std::nullopt;
8056
8057 unsigned CstElemWidth = MRI.getType(Reg).getScalarSizeInBits();
8058 APFloat FVal(0.0);
8059 switch (CstElemWidth) {
8060 case 16:
8061 FVal = APFloat(APFloat::IEEEhalf(), CstVal->Value.trunc(CstElemWidth));
8062 break;
8063 case 32:
8064 FVal = APFloat(APFloat::IEEEsingle(), CstVal->Value);
8065 break;
8066 case 64:
8067 FVal = APFloat(APFloat::IEEEdouble(), CstVal->Value);
8068 break;
8069 default:
8070 return std::nullopt;
8071 };
8072 if (unsigned FBits =
8073 CheckFixedPointOperandConstant(FVal, DstElemWidth, isReciprocal))
8074 return {{[=](MachineInstrBuilder &MIB) { MIB.addImm(FBits); }}};
8075
8076 return std::nullopt;
8077}
8078
8079unsigned AArch64InstructionSelector::getFixedPointWidthFromOperand(
8080 const MachineOperand &Root) const {
8081 return Root.getParent()
8082 ->getMF()
8083 ->getRegInfo()
8084 .getType(Root.getReg())
8086}
8087
8088template <unsigned Width>
8089InstructionSelector::ComplexRendererFns
8090AArch64InstructionSelector::selectCVTFixedPoint(MachineOperand &Root) const {
8091 return selectCVTFixedPointBase(Root, Width, /*isReciprocal*/ false);
8092}
8093
8094template <unsigned Width>
8095InstructionSelector::ComplexRendererFns
8096AArch64InstructionSelector::selectCVTFixedPosRecipOperand(
8097 MachineOperand &Root) const {
8098 return selectCVTFixedPointBase(Root, Width, /*isReciprocal*/ true);
8099}
8100
8101InstructionSelector::ComplexRendererFns
8102AArch64InstructionSelector::selectCVTFixedPointVec(MachineOperand &Root) const {
8103 return selectCVTFixedPointBase(Root, getFixedPointWidthFromOperand(Root),
8104 /*isReciprocal*/ false);
8105}
8106
8107InstructionSelector::ComplexRendererFns
8108AArch64InstructionSelector::selectCVTFixedPosRecipOperandVec(
8109 MachineOperand &Root) const {
8110 return selectCVTFixedPointBase(Root, getFixedPointWidthFromOperand(Root),
8111 /*isReciprocal*/ true);
8112}
8113
8114void AArch64InstructionSelector::renderFixedPointScalarXForm(
8115 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
8116 assert(OpIdx == 3 && MI.getOperand(OpIdx).isImm() &&
8117 "Expected vecshift immediate operand");
8118 MIB.addImm(MI.getOperand(OpIdx).getImm());
8119}
8120
8121void AArch64InstructionSelector::renderFixedPointImm(MachineInstrBuilder &MIB,
8122 const MachineOperand &Root,
8123 unsigned Width,
8124 bool isReciprocal) const {
8125 // FIXME: This is only needed to satisfy the type checking in tablegen, and
8126 // should be able to reuse the Renderers already calculated by
8127 // selectCVTFixedPointBase.
8128 InstructionSelector::ComplexRendererFns Renderer =
8129 selectCVTFixedPointBase(Root, Width, isReciprocal);
8130 assert((Renderer && Renderer->size() == 1) &&
8131 "Expected selectCVTFixedPointBase to provide a function\n");
8132 (Renderer->front())(MIB);
8133}
8134
8135void AArch64InstructionSelector::renderFixedPointXForm(MachineInstrBuilder &MIB,
8136 const MachineInstr &MI,
8137 int OpIdx) const {
8138 const MachineOperand &Root = MI.getOperand(OpIdx);
8139 renderFixedPointImm(MIB, Root, getFixedPointWidthFromOperand(Root),
8140 /*isReciprocal*/ false);
8141}
8142
8143void AArch64InstructionSelector::renderFixedPointRecipXForm(
8144 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
8145 const MachineOperand &Root = MI.getOperand(OpIdx);
8146 renderFixedPointImm(MIB, Root, getFixedPointWidthFromOperand(Root),
8147 /*isReciprocal*/ true);
8148}
8149
8150void AArch64InstructionSelector::renderTruncImm(MachineInstrBuilder &MIB,
8151 const MachineInstr &MI,
8152 int OpIdx) const {
8153 const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
8154 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
8155 "Expected G_CONSTANT");
8156 std::optional<int64_t> CstVal =
8157 getIConstantVRegSExtVal(MI.getOperand(0).getReg(), MRI);
8158 assert(CstVal && "Expected constant value");
8159 MIB.addImm(*CstVal);
8160}
8161
8162void AArch64InstructionSelector::renderLogicalImm32(
8163 MachineInstrBuilder &MIB, const MachineInstr &I, int OpIdx) const {
8164 assert(I.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
8165 "Expected G_CONSTANT");
8166 uint64_t CstVal = I.getOperand(1).getCImm()->getZExtValue();
8168 MIB.addImm(Enc);
8169}
8170
8171void AArch64InstructionSelector::renderLogicalImm64(
8172 MachineInstrBuilder &MIB, const MachineInstr &I, int OpIdx) const {
8173 assert(I.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
8174 "Expected G_CONSTANT");
8175 uint64_t CstVal = I.getOperand(1).getCImm()->getZExtValue();
8177 MIB.addImm(Enc);
8178}
8179
8180void AArch64InstructionSelector::renderUbsanTrap(MachineInstrBuilder &MIB,
8181 const MachineInstr &MI,
8182 int OpIdx) const {
8183 assert(MI.getOpcode() == TargetOpcode::G_UBSANTRAP && OpIdx == 0 &&
8184 "Expected G_UBSANTRAP");
8185 MIB.addImm(MI.getOperand(0).getImm() | ('U' << 8));
8186}
8187
8188void AArch64InstructionSelector::renderFPImm16(MachineInstrBuilder &MIB,
8189 const MachineInstr &MI,
8190 int OpIdx) const {
8191 assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 &&
8192 "Expected G_FCONSTANT");
8193 MIB.addImm(
8194 AArch64_AM::getFP16Imm(MI.getOperand(1).getFPImm()->getValueAPF()));
8195}
8196
8197void AArch64InstructionSelector::renderFPImm32(MachineInstrBuilder &MIB,
8198 const MachineInstr &MI,
8199 int OpIdx) const {
8200 assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 &&
8201 "Expected G_FCONSTANT");
8202 MIB.addImm(
8203 AArch64_AM::getFP32Imm(MI.getOperand(1).getFPImm()->getValueAPF()));
8204}
8205
8206void AArch64InstructionSelector::renderFPImm64(MachineInstrBuilder &MIB,
8207 const MachineInstr &MI,
8208 int OpIdx) const {
8209 assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 &&
8210 "Expected G_FCONSTANT");
8211 MIB.addImm(
8212 AArch64_AM::getFP64Imm(MI.getOperand(1).getFPImm()->getValueAPF()));
8213}
8214
8215void AArch64InstructionSelector::renderFPImm32SIMDModImmType4(
8216 MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
8217 assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1 &&
8218 "Expected G_FCONSTANT");
8220 .getFPImm()
8221 ->getValueAPF()
8222 .bitcastToAPInt()
8223 .getZExtValue()));
8224}
8225
8226bool AArch64InstructionSelector::isLoadStoreOfNumBytes(
8227 const MachineInstr &MI, unsigned NumBytes) const {
8228 if (!MI.mayLoadOrStore())
8229 return false;
8230 assert(MI.hasOneMemOperand() &&
8231 "Expected load/store to have only one mem op!");
8232 return (*MI.memoperands_begin())->getSize() == NumBytes;
8233}
8234
8235bool AArch64InstructionSelector::isDef32(const MachineInstr &MI) const {
8236 const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
8237 if (MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() != 32)
8238 return false;
8239
8240 // Only return true if we know the operation will zero-out the high half of
8241 // the 64-bit register. Truncates can be subregister copies, which don't
8242 // zero out the high bits. Copies and other copy-like instructions can be
8243 // fed by truncates, or could be lowered as subregister copies.
8244 switch (MI.getOpcode()) {
8245 default:
8246 return true;
8247 case TargetOpcode::COPY:
8248 case TargetOpcode::G_BITCAST:
8249 case TargetOpcode::G_TRUNC:
8250 case TargetOpcode::G_PHI:
8251 return false;
8252 }
8253}
8254
8255
8256// Perform fixups on the given PHI instruction's operands to force them all
8257// to be the same as the destination regbank.
8259 const AArch64RegisterBankInfo &RBI) {
8260 assert(MI.getOpcode() == TargetOpcode::G_PHI && "Expected a G_PHI");
8261 Register DstReg = MI.getOperand(0).getReg();
8262 const RegisterBank *DstRB = MRI.getRegBankOrNull(DstReg);
8263 assert(DstRB && "Expected PHI dst to have regbank assigned");
8264 MachineIRBuilder MIB(MI);
8265
8266 // Go through each operand and ensure it has the same regbank.
8267 for (MachineOperand &MO : llvm::drop_begin(MI.operands())) {
8268 if (!MO.isReg())
8269 continue;
8270 Register OpReg = MO.getReg();
8271 const RegisterBank *RB = MRI.getRegBankOrNull(OpReg);
8272 if (RB != DstRB) {
8273 // Insert a cross-bank copy.
8274 auto *OpDef = MRI.getVRegDef(OpReg);
8275 const LLT &Ty = MRI.getType(OpReg);
8276 MachineBasicBlock &OpDefBB = *OpDef->getParent();
8277
8278 // Any instruction we insert must appear after all PHIs in the block
8279 // for the block to be valid MIR.
8280 MachineBasicBlock::iterator InsertPt = std::next(OpDef->getIterator());
8281 if (InsertPt != OpDefBB.end() && InsertPt->isPHI())
8282 InsertPt = OpDefBB.getFirstNonPHI();
8283 MIB.setInsertPt(*OpDef->getParent(), InsertPt);
8284 auto Copy = MIB.buildCopy(Ty, OpReg);
8285 MRI.setRegBank(Copy.getReg(0), *DstRB);
8286 MO.setReg(Copy.getReg(0));
8287 }
8288 }
8289}
8290
8291void AArch64InstructionSelector::processPHIs(MachineFunction &MF) {
8292 // We're looking for PHIs, build a list so we don't invalidate iterators.
8293 MachineRegisterInfo &MRI = MF.getRegInfo();
8295 for (auto &BB : MF) {
8296 for (auto &MI : BB) {
8297 if (MI.getOpcode() == TargetOpcode::G_PHI)
8298 Phis.emplace_back(&MI);
8299 }
8300 }
8301
8302 for (auto *MI : Phis) {
8303 // We need to do some work here if the operand types are < 16 bit and they
8304 // are split across fpr/gpr banks. Since all types <32b on gpr
8305 // end up being assigned gpr32 regclasses, we can end up with PHIs here
8306 // which try to select between a gpr32 and an fpr16. Ideally RBS shouldn't
8307 // be selecting heterogenous regbanks for operands if possible, but we
8308 // still need to be able to deal with it here.
8309 //
8310 // To fix this, if we have a gpr-bank operand < 32b in size and at least
8311 // one other operand is on the fpr bank, then we add cross-bank copies
8312 // to homogenize the operand banks. For simplicity the bank that we choose
8313 // to settle on is whatever bank the def operand has. For example:
8314 //
8315 // %endbb:
8316 // %dst:gpr(s16) = G_PHI %in1:gpr(s16), %bb1, %in2:fpr(s16), %bb2
8317 // =>
8318 // %bb2:
8319 // ...
8320 // %in2_copy:gpr(s16) = COPY %in2:fpr(s16)
8321 // ...
8322 // %endbb:
8323 // %dst:gpr(s16) = G_PHI %in1:gpr(s16), %bb1, %in2_copy:gpr(s16), %bb2
8324 bool HasGPROp = false, HasFPROp = false;
8325 for (const MachineOperand &MO : llvm::drop_begin(MI->operands())) {
8326 if (!MO.isReg())
8327 continue;
8328 const LLT &Ty = MRI.getType(MO.getReg());
8329 if (!Ty.isValid() || !Ty.isScalar())
8330 break;
8331 if (Ty.getSizeInBits() >= 32)
8332 break;
8333 const RegisterBank *RB = MRI.getRegBankOrNull(MO.getReg());
8334 // If for some reason we don't have a regbank yet. Don't try anything.
8335 if (!RB)
8336 break;
8337
8338 if (RB->getID() == AArch64::GPRRegBankID)
8339 HasGPROp = true;
8340 else
8341 HasFPROp = true;
8342 }
8343 // We have heterogenous regbanks, need to fixup.
8344 if (HasGPROp && HasFPROp)
8345 fixupPHIOpBanks(*MI, MRI, RBI);
8346 }
8347}
8348
8349namespace llvm {
8350InstructionSelector *
8352 const AArch64Subtarget &Subtarget,
8353 const AArch64RegisterBankInfo &RBI) {
8354 return new AArch64InstructionSelector(TM, Subtarget, RBI);
8355}
8356}
#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.
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.
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.
TypeSize getSizeInBits(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
Get the size in bits of Reg.
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 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:986
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)
OneNonDBGUse_match< SubPat > m_OneNonDBGUse(const SubPat &SP)
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)
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:867
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:60
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:675
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:297
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:159
@ 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:516
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:317
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:442
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:436
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:491
LLVM_ABI std::optional< Register > getVectorSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI)
Definition Utils.cpp:1465
LLVM_ABI Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the source register for Reg, folding away any trivial copies.
Definition Utils.cpp:523
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.