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