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