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