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