LLVM 19.0.0git
Namespaces | Macros | Functions
AArch64InstructionSelector.cpp File Reference

This file implements the targeting of the InstructionSelector class for AArch64. More...

#include "AArch64GlobalISelUtils.h"
#include "AArch64InstrInfo.h"
#include "AArch64MachineFunctionInfo.h"
#include "AArch64RegisterBankInfo.h"
#include "AArch64RegisterInfo.h"
#include "AArch64Subtarget.h"
#include "AArch64TargetMachine.h"
#include "MCTargetDesc/AArch64AddressingModes.h"
#include "MCTargetDesc/AArch64MCTargetDesc.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/GlobalISel/Utils.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicsAArch64.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/Type.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <optional>
#include "AArch64GenGlobalISel.inc"

Go to the source code of this file.

Namespaces

namespace  llvm
 This is an optimization pass for GlobalISel generic memory operations.
 

Macros

#define DEBUG_TYPE   "aarch64-isel"
 
#define GET_GLOBALISEL_PREDICATE_BITSET
 
#define GET_GLOBALISEL_PREDICATES_DECL
 
#define GET_GLOBALISEL_TEMPORARIES_DECL
 
#define GET_GLOBALISEL_IMPL
 
#define GET_GLOBALISEL_PREDICATES_INIT
 
#define GET_GLOBALISEL_TEMPORARIES_INIT
 

Functions

static const TargetRegisterClassgetMinClassForRegBank (const RegisterBank &RB, unsigned SizeInBits, bool GetAllRegSet=false)
 Given a register bank, and size in bits, return the smallest register class that can represent that combination.
 
static bool getSubRegForClass (const TargetRegisterClass *RC, const TargetRegisterInfo &TRI, unsigned &SubReg)
 Returns the correct subregister to use for a given register class.
 
static unsigned getMinSizeForRegBank (const RegisterBank &RB)
 Returns the minimum size the given register bank can hold.
 
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 Register createDTuple (ArrayRef< Register > Regs, MachineIRBuilder &MIB)
 Create a tuple of D-registers using the registers in Regs.
 
static Register createQTuple (ArrayRef< Register > Regs, MachineIRBuilder &MIB)
 Create a tuple of Q-registers using the registers in Regs.
 
static std::optional< uint64_tgetImmedFromMO (const MachineOperand &Root)
 
static bool unsupportedBinOp (const MachineInstr &I, const AArch64RegisterBankInfo &RBI, const MachineRegisterInfo &MRI, const AArch64RegisterInfo &TRI)
 Check whether I is a currently unsupported binary operation:
 
static unsigned selectBinaryOp (unsigned GenericOpc, unsigned RegBankID, unsigned OpSize)
 Select the AArch64 opcode for the basic binary operation GenericOpc (such as G_OR or G_SDIV), appropriate for the register bank RegBankID and of size OpSize.
 
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) register bank RegBankID and of memory access size OpSize.
 
static bool copySubReg (MachineInstr &I, MachineRegisterInfo &MRI, const RegisterBankInfo &RBI, Register SrcReg, const TargetRegisterClass *To, unsigned SubReg)
 Helper function for selectCopy.
 
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.
 
static bool selectDebugInstr (MachineInstr &I, MachineRegisterInfo &MRI, const RegisterBankInfo &RBI)
 
static bool selectCopy (MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
 
static unsigned selectFPConvOpc (unsigned GenericOpc, LLT DstTy, LLT SrcTy)
 
static AArch64CC::CondCode changeICMPPredToAArch64CC (CmpInst::Predicate P)
 
static void changeFPCCToORAArch64CC (CmpInst::Predicate CC, AArch64CC::CondCode &CondCode, AArch64CC::CondCode &CondCode2)
 changeFPCCToORAArch64CC - Convert an IR fp condition code to an AArch64 CC.
 
static void changeFPCCToANDAArch64CC (CmpInst::Predicate CC, AArch64CC::CondCode &CondCode, AArch64CC::CondCode &CondCode2)
 Convert an IR fp condition code to an AArch64 CC.
 
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 std::optional< int64_t > getVectorShiftImm (Register Reg, MachineRegisterInfo &MRI)
 Returns the element immediate value of a vector shift operand if found.
 
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 bool getLaneCopyOpcode (unsigned &CopyOpc, unsigned &ExtractSubReg, const unsigned EltSize)
 
static std::pair< unsigned, unsignedgetInsertVecEltOpInfo (const RegisterBank &RB, unsigned EltSize)
 Return an <Opcode, SubregIndex> pair to do an vector elt insert of a given size and RB.
 
static bool canEmitConjunction (Register Val, bool &CanNegate, bool &MustBeFirst, bool WillNegate, MachineRegisterInfo &MRI, unsigned Depth=0)
 Returns true if Val is a tree of AND/OR/CMP operations that can be expressed as a conjunction.
 
static bool isSignExtendShiftType (AArch64_AM::ShiftExtendType Type)
 
static AArch64_AM::ShiftExtendType getShiftTypeForInst (MachineInstr &MI)
 Given a shift instruction, return the correct shift type for that instruction.
 
static void fixupPHIOpBanks (MachineInstr &MI, MachineRegisterInfo &MRI, const AArch64RegisterBankInfo &RBI)
 
InstructionSelectorllvm::createAArch64InstructionSelector (const AArch64TargetMachine &, AArch64Subtarget &, AArch64RegisterBankInfo &)
 

Detailed Description

This file implements the targeting of the InstructionSelector class for AArch64.

Todo:
This should be generated by TableGen.

Definition in file AArch64InstructionSelector.cpp.

Macro Definition Documentation

◆ DEBUG_TYPE

#define DEBUG_TYPE   "aarch64-isel"

Definition at line 52 of file AArch64InstructionSelector.cpp.

◆ GET_GLOBALISEL_IMPL

#define GET_GLOBALISEL_IMPL

Definition at line 539 of file AArch64InstructionSelector.cpp.

◆ GET_GLOBALISEL_PREDICATE_BITSET

#define GET_GLOBALISEL_PREDICATE_BITSET

Definition at line 65 of file AArch64InstructionSelector.cpp.

◆ GET_GLOBALISEL_PREDICATES_DECL

#define GET_GLOBALISEL_PREDICATES_DECL

Definition at line 526 of file AArch64InstructionSelector.cpp.

◆ GET_GLOBALISEL_PREDICATES_INIT

#define GET_GLOBALISEL_PREDICATES_INIT

◆ GET_GLOBALISEL_TEMPORARIES_DECL

#define GET_GLOBALISEL_TEMPORARIES_DECL

Definition at line 532 of file AArch64InstructionSelector.cpp.

◆ GET_GLOBALISEL_TEMPORARIES_INIT

#define GET_GLOBALISEL_TEMPORARIES_INIT

Function Documentation

◆ canEmitConjunction()

static bool canEmitConjunction ( Register  Val,
bool CanNegate,
bool MustBeFirst,
bool  WillNegate,
MachineRegisterInfo MRI,
unsigned  Depth = 0 
)
static

Returns true if Val is a tree of AND/OR/CMP operations that can be expressed as a conjunction.

Parameters
CanNegateSet to true if we can negate the whole sub-tree just by changing the conditions on the CMP tests. (this means we can call emitConjunctionRec() with Negate==true on this sub-tree)
MustBeFirstSet to true if this subtree needs to be negated and we cannot do the negation naturally. We are required to emit the subtree first in this case.
WillNegateIs true if are called when the result of this subexpression must be negated. This happens when the outer expression is an OR. We can use this fact to know that we have a double negation (or (or ...) ...) that can be implemented for free.

Definition at line 4776 of file AArch64InstructionSelector.cpp.

References assert(), canEmitConjunction(), llvm::Depth, llvm::MachineInstr::getOpcode(), llvm::MachineInstr::getOperand(), llvm::MachineOperand::getReg(), and MRI.

Referenced by canEmitConjunction().

◆ changeFPCCToANDAArch64CC()

static void changeFPCCToANDAArch64CC ( CmpInst::Predicate  CC,
AArch64CC::CondCode CondCode,
AArch64CC::CondCode CondCode2 
)
static

Convert an IR fp condition code to an AArch64 CC.

This differs from changeFPCCToAArch64CC in that it returns cond codes that should be AND'ed instead of OR'ed.

Definition at line 1414 of file AArch64InstructionSelector.cpp.

References llvm::AArch64CC::AL, assert(), CC, changeFPCCToORAArch64CC(), llvm::CmpInst::FCMP_ONE, llvm::CmpInst::FCMP_UEQ, llvm::AArch64CC::LE, llvm::AArch64CC::NE, llvm::AArch64CC::PL, and llvm::AArch64CC::VC.

◆ changeFPCCToORAArch64CC()

static void changeFPCCToORAArch64CC ( CmpInst::Predicate  CC,
AArch64CC::CondCode CondCode,
AArch64CC::CondCode CondCode2 
)
static

◆ changeICMPPredToAArch64CC()

static AArch64CC::CondCode changeICMPPredToAArch64CC ( CmpInst::Predicate  P)
static

◆ copySubReg()

static bool copySubReg ( MachineInstr I,
MachineRegisterInfo MRI,
const RegisterBankInfo RBI,
Register  SrcReg,
const TargetRegisterClass To,
unsigned  SubReg 
)
static

Helper function for selectCopy.

Inserts a subregister copy from SrcReg to *To.

E.g "To = COPY SrcReg:SubReg"

Definition at line 908 of file AArch64InstructionSelector.cpp.

References assert(), llvm::MachineIRBuilder::buildInstr(), llvm::RegisterBankInfo::constrainGenericRegister(), I, llvm::Register::isValid(), MRI, llvm::MachineOperand::setReg(), and SubReg.

Referenced by selectCopy().

◆ createDTuple()

static Register createDTuple ( ArrayRef< Register Regs,
MachineIRBuilder MIB 
)
static

Create a tuple of D-registers using the registers in Regs.

Definition at line 709 of file AArch64InstructionSelector.cpp.

References createTuple().

◆ createQTuple()

static Register createQTuple ( ArrayRef< Register Regs,
MachineIRBuilder MIB 
)
static

Create a tuple of Q-registers using the registers in Regs.

Definition at line 718 of file AArch64InstructionSelector.cpp.

References createTuple().

◆ createTuple()

static Register createTuple ( ArrayRef< Register Regs,
const unsigned  RegClassIDs[],
const unsigned  SubRegs[],
MachineIRBuilder MIB 
)
static

Create a REG_SEQUENCE instruction using the registers in Regs.

Helper function for functions like createDTuple and createQTuple.

RegClassIDs - The list of register class IDs available for some tuple of a scalar class. E.g. QQRegClassID, QQQRegClassID, QQQQRegClassID. This is expected to contain between 2 and 4 tuple classes.

SubRegs - The list of subregister classes associated with each register class ID in RegClassIDs. E.g., QQRegClassID should use the qsub0 subregister class. The index of each subregister class is expected to correspond with the index of each register class.

Returns
Either the destination register of REG_SEQUENCE instruction that was created, or the 0th element of Regs if Regs contains a single element.

Definition at line 689 of file AArch64InstructionSelector.cpp.

References assert(), llvm::MachineIRBuilder::buildInstr(), llvm::MachineIRBuilder::getMF(), llvm::TargetSubtargetInfo::getRegisterInfo(), llvm::MachineFunction::getSubtarget(), I, llvm::ArrayRef< T >::size(), and TRI.

Referenced by createDTuple(), createQTuple(), llvm::RISCVDAGToDAGISel::selectVLSEG(), llvm::RISCVDAGToDAGISel::selectVLSEGFF(), llvm::RISCVDAGToDAGISel::selectVLXSEG(), llvm::RISCVDAGToDAGISel::selectVSSEG(), and llvm::RISCVDAGToDAGISel::selectVSXSEG().

◆ fixupPHIOpBanks()

static void fixupPHIOpBanks ( MachineInstr MI,
MachineRegisterInfo MRI,
const AArch64RegisterBankInfo RBI 
)
static

◆ getImmedFromMO()

static std::optional< uint64_t > getImmedFromMO ( const MachineOperand Root)
static

◆ getInsertVecEltOpInfo()

static std::pair< unsigned, unsigned > getInsertVecEltOpInfo ( const RegisterBank RB,
unsigned  EltSize 
)
static

Return an <Opcode, SubregIndex> pair to do an vector elt insert of a given size and RB.

Definition at line 4307 of file AArch64InstructionSelector.cpp.

References llvm::RegisterBank::getID(), and llvm_unreachable.

◆ getLaneCopyOpcode()

static bool getLaneCopyOpcode ( unsigned CopyOpc,
unsigned ExtractSubReg,
const unsigned  EltSize 
)
static

Definition at line 3949 of file AArch64InstructionSelector.cpp.

References llvm::dbgs(), and LLVM_DEBUG.

◆ getMinClassForRegBank()

static const TargetRegisterClass * getMinClassForRegBank ( const RegisterBank RB,
unsigned  SizeInBits,
bool  GetAllRegSet = false 
)
static

Given a register bank, and size in bits, return the smallest register class that can represent that combination.

Definition at line 599 of file AArch64InstructionSelector.cpp.

References llvm::RegisterBank::getID().

Referenced by getRegClassesForCopy(), and selectCopy().

◆ getMinSizeForRegBank()

static unsigned getMinSizeForRegBank ( const RegisterBank RB)
static

Returns the minimum size the given register bank can hold.

Definition at line 663 of file AArch64InstructionSelector.cpp.

References llvm::RegisterBank::getID(), and llvm_unreachable.

Referenced by selectCopy().

◆ getRegClassesForCopy()

static std::pair< const TargetRegisterClass *, const TargetRegisterClass * > getRegClassesForCopy ( MachineInstr I,
const TargetInstrInfo TII,
MachineRegisterInfo MRI,
const TargetRegisterInfo TRI,
const RegisterBankInfo RBI 
)
static

Helper function to get the source and destination register classes for a copy.

Returns a std::pair containing the source register class for the copy, and the destination register class for the copy. If a register class cannot be determined, then it will be nullptr.

Definition at line 934 of file AArch64InstructionSelector.cpp.

References getMinClassForRegBank(), llvm::RegisterBankInfo::getRegBank(), llvm::RegisterBankInfo::getSizeInBits(), I, MRI, and TRI.

Referenced by selectCopy().

◆ getShiftTypeForInst()

static AArch64_AM::ShiftExtendType getShiftTypeForInst ( MachineInstr MI)
static

Given a shift instruction, return the correct shift type for that instruction.

Definition at line 7331 of file AArch64InstructionSelector.cpp.

References llvm::AArch64_AM::ASR, llvm::AArch64_AM::InvalidShiftExtend, llvm::AArch64_AM::LSL, llvm::AArch64_AM::LSR, MI, and llvm::AArch64_AM::ROR.

◆ getSubRegForClass()

static bool getSubRegForClass ( const TargetRegisterClass RC,
const TargetRegisterInfo TRI,
unsigned SubReg 
)
static

Returns the correct subregister to use for a given register class.

Definition at line 635 of file AArch64InstructionSelector.cpp.

References llvm::dbgs(), LLVM_DEBUG, SubReg, and TRI.

Referenced by selectCopy().

◆ getTestBitReg()

static Register getTestBitReg ( Register  Reg,
uint64_t Bit,
bool Invert,
MachineRegisterInfo MRI 
)
static

Return a register which can be used as a bit to test in a TB(N)Z.

Definition at line 1441 of file AArch64InstructionSelector.cpp.

References assert(), llvm::CallingConv::C, llvm::getDefIgnoringCopies(), llvm::getIConstantVRegValWithLookThrough(), llvm::Register::isValid(), MI, MRI, and std::swap().

◆ getVectorShiftImm()

static std::optional< int64_t > getVectorShiftImm ( Register  Reg,
MachineRegisterInfo MRI 
)
static

Returns the element immediate value of a vector shift operand if found.

This needs to detect a splat-like operation, e.g. a G_BUILD_VECTOR.

Definition at line 1834 of file AArch64InstructionSelector.cpp.

References assert(), llvm::AArch64GISelUtils::getAArch64VectorSplatScalar(), and MRI.

Referenced by getVectorSHLImm().

◆ getVectorSHLImm()

static std::optional< int64_t > getVectorSHLImm ( LLT  SrcTy,
Register  Reg,
MachineRegisterInfo MRI 
)
static

Matches and returns the shift immediate value for a SHL instruction given a shift operand.

Definition at line 1843 of file AArch64InstructionSelector.cpp.

References llvm::dbgs(), llvm::LLT::getElementType(), llvm::LLT::getSizeInBits(), getVectorShiftImm(), LLVM_DEBUG, and MRI.

◆ isSignExtendShiftType()

static bool isSignExtendShiftType ( AArch64_AM::ShiftExtendType  Type)
static

◆ selectBinaryOp()

static unsigned selectBinaryOp ( unsigned  GenericOpc,
unsigned  RegBankID,
unsigned  OpSize 
)
static

Select the AArch64 opcode for the basic binary operation GenericOpc (such as G_OR or G_SDIV), appropriate for the register bank RegBankID and of size OpSize.

Returns
GenericOpc if the combination is unsupported.

Definition at line 799 of file AArch64InstructionSelector.cpp.

◆ selectCopy()

static bool selectCopy ( MachineInstr I,
const TargetInstrInfo TII,
MachineRegisterInfo MRI,
const TargetRegisterInfo TRI,
const RegisterBankInfo RBI 
)
static

◆ selectDebugInstr()

static bool selectDebugInstr ( MachineInstr I,
MachineRegisterInfo MRI,
const RegisterBankInfo RBI 
)
static

◆ selectFPConvOpc()

static unsigned selectFPConvOpc ( unsigned  GenericOpc,
LLT  DstTy,
LLT  SrcTy 
)
static

◆ selectLoadStoreUIOp()

static unsigned selectLoadStoreUIOp ( unsigned  GenericOpc,
unsigned  RegBankID,
unsigned  OpSize 
)
static

Select the AArch64 opcode for the G_LOAD or G_STORE operation GenericOpc, appropriate for the (value) register bank RegBankID and of memory access size OpSize.

This returns the variant with the base+unsigned-immediate addressing mode (e.g., LDRXui).

Returns
GenericOpc if the combination is unsupported.

Definition at line 870 of file AArch64InstructionSelector.cpp.

References isStore().

◆ unsupportedBinOp()

static bool unsupportedBinOp ( const MachineInstr I,
const AArch64RegisterBankInfo RBI,
const MachineRegisterInfo MRI,
const AArch64RegisterInfo TRI 
)
static

Check whether I is a currently unsupported binary operation:

  • it has an unsized type
  • an operand is not a vreg
  • all operands are not in the same bank These are checks that should someday live in the verifier, but right now, these are mostly limitations of the aarch64 selector.

Definition at line 753 of file AArch64InstructionSelector.cpp.

References llvm::dbgs(), llvm::RegisterBankInfo::getRegBank(), I, llvm::LLT::isValid(), LLVM_DEBUG, MRI, and TRI.