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