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