#include "AMDGPULegalizerInfo.h"
#include "AMDGPU.h"
#include "AMDGPUGlobalISelUtils.h"
#include "AMDGPUInstrInfo.h"
#include "AMDGPUTargetMachine.h"
#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
#include "SIInstrInfo.h"
#include "SIMachineFunctionInfo.h"
#include "SIRegisterInfo.h"
#include "Utils/AMDGPUBaseInfo.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/GlobalISel/Utils.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/IntrinsicsAMDGPU.h"
#include "llvm/IR/IntrinsicsR600.h"
#define DEBUG_TYPE …
usingnamespacellvm;
usingnamespaceLegalizeActions;
usingnamespaceLegalizeMutations;
usingnamespaceLegalityPredicates;
usingnamespaceMIPatternMatch;
static cl::opt<bool> EnableNewLegality(
"amdgpu-global-isel-new-legality",
cl::desc("Use GlobalISel desired legality, rather than try to use"
"rules compatible with selection patterns"),
cl::init(false),
cl::ReallyHidden);
static constexpr unsigned MaxRegisterSize = …;
static LLT getPow2VectorType(LLT Ty) { … }
static LLT getPow2ScalarType(LLT Ty) { … }
static LegalityPredicate isSmallOddVector(unsigned TypeIdx) { … }
static LegalityPredicate sizeIsMultipleOf32(unsigned TypeIdx) { … }
static LegalityPredicate isWideVec16(unsigned TypeIdx) { … }
static LegalizeMutation oneMoreElement(unsigned TypeIdx) { … }
static LegalizeMutation fewerEltsToSize64Vector(unsigned TypeIdx) { … }
static LegalizeMutation moreEltsToNext32Bit(unsigned TypeIdx) { … }
static LegalizeMutation moreElementsToNextExistingRegClass(unsigned TypeIdx) { … }
static LLT getBufferRsrcScalarType(const LLT Ty) { … }
static LLT getBufferRsrcRegisterType(const LLT Ty) { … }
static LLT getBitcastRegisterType(const LLT Ty) { … }
static LegalizeMutation bitcastToRegisterType(unsigned TypeIdx) { … }
static LegalizeMutation bitcastToVectorElement32(unsigned TypeIdx) { … }
static LegalityPredicate vectorSmallerThan(unsigned TypeIdx, unsigned Size) { … }
static LegalityPredicate vectorWiderThan(unsigned TypeIdx, unsigned Size) { … }
static LegalityPredicate numElementsNotEven(unsigned TypeIdx) { … }
static bool isRegisterSize(unsigned Size) { … }
static bool isRegisterVectorElementType(LLT EltTy) { … }
static bool isRegisterVectorType(LLT Ty) { … }
static bool isRegisterType(LLT Ty) { … }
static LegalityPredicate isRegisterType(unsigned TypeIdx) { … }
static LegalityPredicate isIllegalRegisterType(unsigned TypeIdx) { … }
static LegalityPredicate elementTypeIsLegal(unsigned TypeIdx) { … }
static const LLT S1 = …;
static const LLT S8 = …;
static const LLT S16 = …;
static const LLT S32 = …;
static const LLT F32 = …;
static const LLT S64 = …;
static const LLT F64 = …;
static const LLT S96 = …;
static const LLT S128 = …;
static const LLT S160 = …;
static const LLT S192 = …;
static const LLT S224 = …;
static const LLT S256 = …;
static const LLT S512 = …;
static const LLT S1024 = …;
static const LLT MaxScalar = …;
static const LLT V2S8 = …;
static const LLT V2S16 = …;
static const LLT V4S16 = …;
static const LLT V6S16 = …;
static const LLT V8S16 = …;
static const LLT V10S16 = …;
static const LLT V12S16 = …;
static const LLT V16S16 = …;
static const LLT V2F16 = …;
static const LLT V2BF16 = …;
static const LLT V2S32 = …;
static const LLT V3S32 = …;
static const LLT V4S32 = …;
static const LLT V5S32 = …;
static const LLT V6S32 = …;
static const LLT V7S32 = …;
static const LLT V8S32 = …;
static const LLT V9S32 = …;
static const LLT V10S32 = …;
static const LLT V11S32 = …;
static const LLT V12S32 = …;
static const LLT V16S32 = …;
static const LLT V32S32 = …;
static const LLT V2S64 = …;
static const LLT V3S64 = …;
static const LLT V4S64 = …;
static const LLT V5S64 = …;
static const LLT V6S64 = …;
static const LLT V7S64 = …;
static const LLT V8S64 = …;
static const LLT V16S64 = …;
static const LLT V2S128 = …;
static const LLT V4S128 = …;
static std::initializer_list<LLT> AllScalarTypes = …;
static std::initializer_list<LLT> AllS16Vectors{ … };
static std::initializer_list<LLT> AllS32Vectors = …;
static std::initializer_list<LLT> AllS64Vectors = …;
static bool isRegisterClassType(LLT Ty) { … }
static LegalityPredicate isRegisterClassType(unsigned TypeIdx) { … }
static LegalityPredicate isWideScalarExtLoadTruncStore(unsigned TypeIdx) { … }
static unsigned maxSizeForAddrSpace(const GCNSubtarget &ST, unsigned AS,
bool IsLoad, bool IsAtomic) { … }
static bool isLoadStoreSizeLegal(const GCNSubtarget &ST,
const LegalityQuery &Query) { … }
static bool hasBufferRsrcWorkaround(const LLT Ty) { … }
static bool loadStoreBitcastWorkaround(const LLT Ty) { … }
static bool isLoadStoreLegal(const GCNSubtarget &ST, const LegalityQuery &Query) { … }
static bool shouldBitcastLoadStoreType(const GCNSubtarget &ST, const LLT Ty,
const LLT MemTy) { … }
static bool shouldWidenLoad(const GCNSubtarget &ST, LLT MemoryTy,
uint64_t AlignInBits, unsigned AddrSpace,
unsigned Opcode) { … }
static bool shouldWidenLoad(const GCNSubtarget &ST, const LegalityQuery &Query,
unsigned Opcode) { … }
static LLT castBufferRsrcFromV4I32(MachineInstr &MI, MachineIRBuilder &B,
MachineRegisterInfo &MRI, unsigned Idx) { … }
static Register castBufferRsrcToV4I32(Register Pointer, MachineIRBuilder &B) { … }
static void castBufferRsrcArgToV4I32(MachineInstr &MI, MachineIRBuilder &B,
unsigned Idx) { … }
AMDGPULegalizerInfo::AMDGPULegalizerInfo(const GCNSubtarget &ST_,
const GCNTargetMachine &TM)
: … { … }
bool AMDGPULegalizerInfo::legalizeCustom(
LegalizerHelper &Helper, MachineInstr &MI,
LostDebugLocObserver &LocObserver) const { … }
Register AMDGPULegalizerInfo::getSegmentAperture(
unsigned AS,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
static bool isKnownNonNull(Register Val, MachineRegisterInfo &MRI,
const AMDGPUTargetMachine &TM, unsigned AddrSpace) { … }
bool AMDGPULegalizerInfo::legalizeAddrSpaceCast(
MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeFroundeven(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeFceil(
MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeFrem(
MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
static MachineInstrBuilder extractF64Exponent(Register Hi,
MachineIRBuilder &B) { … }
bool AMDGPULegalizerInfo::legalizeIntrinsicTrunc(
MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeITOFP(
MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &B, bool Signed) const { … }
bool AMDGPULegalizerInfo::legalizeFPTOI(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B,
bool Signed) const { … }
bool AMDGPULegalizerInfo::legalizeMinNumMaxNum(LegalizerHelper &Helper,
MachineInstr &MI) const { … }
bool AMDGPULegalizerInfo::legalizeExtractVectorElt(
MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeInsertVectorElt(
MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeSinCos(
MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::buildPCRelGlobalAddress(Register DstReg, LLT PtrTy,
MachineIRBuilder &B,
const GlobalValue *GV,
int64_t Offset,
unsigned GAFlags) const { … }
void AMDGPULegalizerInfo::buildAbsGlobalAddress(
Register DstReg, LLT PtrTy, MachineIRBuilder &B, const GlobalValue *GV,
MachineRegisterInfo &MRI) const { … }
bool AMDGPULegalizerInfo::legalizeGlobalValue(
MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
static LLT widenToNextPowerOf2(LLT Ty) { … }
bool AMDGPULegalizerInfo::legalizeLoad(LegalizerHelper &Helper,
MachineInstr &MI) const { … }
bool AMDGPULegalizerInfo::legalizeStore(LegalizerHelper &Helper,
MachineInstr &MI) const { … }
bool AMDGPULegalizerInfo::legalizeFMad(
MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeAtomicCmpXChg(
MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const { … }
static bool valueIsKnownNeverF32Denorm(const MachineRegisterInfo &MRI,
Register Src) { … }
static bool allowApproxFunc(const MachineFunction &MF, unsigned Flags) { … }
static bool needsDenormHandlingF32(const MachineFunction &MF, Register Src,
unsigned Flags) { … }
std::pair<Register, Register>
AMDGPULegalizerInfo::getScaledLogInput(MachineIRBuilder &B, Register Src,
unsigned Flags) const { … }
bool AMDGPULegalizerInfo::legalizeFlog2(MachineInstr &MI,
MachineIRBuilder &B) const { … }
static Register getMad(MachineIRBuilder &B, LLT Ty, Register X, Register Y,
Register Z, unsigned Flags) { … }
bool AMDGPULegalizerInfo::legalizeFlogCommon(MachineInstr &MI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeFlogUnsafe(MachineIRBuilder &B, Register Dst,
Register Src, bool IsLog10,
unsigned Flags) const { … }
bool AMDGPULegalizerInfo::legalizeFExp2(MachineInstr &MI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeFExpUnsafe(MachineIRBuilder &B, Register Dst,
Register X, unsigned Flags) const { … }
bool AMDGPULegalizerInfo::legalizeFExp(MachineInstr &MI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeFPow(MachineInstr &MI,
MachineIRBuilder &B) const { … }
static Register stripAnySourceMods(Register OrigSrc, MachineRegisterInfo &MRI) { … }
bool AMDGPULegalizerInfo::legalizeFFloor(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeBuildVector(
MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const { … }
void AMDGPULegalizerInfo::buildMultiply(LegalizerHelper &Helper,
MutableArrayRef<Register> Accum,
ArrayRef<Register> Src0,
ArrayRef<Register> Src1,
bool UsePartialMad64_32,
bool SeparateOddAlignedProducts) const { … }
bool AMDGPULegalizerInfo::legalizeMul(LegalizerHelper &Helper,
MachineInstr &MI) const { … }
bool AMDGPULegalizerInfo::legalizeCTLZ_CTTZ(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeCTLZ_ZERO_UNDEF(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI) { … }
static MachineInstr *
verifyCFIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineInstr *&Br,
MachineBasicBlock *&UncondBrTarget, bool &Negated) { … }
bool AMDGPULegalizerInfo::loadInputValue(Register DstReg, MachineIRBuilder &B,
const ArgDescriptor *Arg,
const TargetRegisterClass *ArgRC,
LLT ArgTy) const { … }
bool AMDGPULegalizerInfo::loadInputValue(
Register DstReg, MachineIRBuilder &B,
AMDGPUFunctionArgInfo::PreloadedValue ArgType) const { … }
bool AMDGPULegalizerInfo::legalizePreloadedArgIntrin(
MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B,
AMDGPUFunctionArgInfo::PreloadedValue ArgType) const { … }
static bool replaceWithConstant(MachineIRBuilder &B, MachineInstr &MI,
int64_t C) { … }
bool AMDGPULegalizerInfo::legalizeWorkitemIDIntrinsic(
MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B,
unsigned Dim, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const { … }
Register AMDGPULegalizerInfo::getKernargParameterPtr(MachineIRBuilder &B,
int64_t Offset) const { … }
bool AMDGPULegalizerInfo::legalizeKernargMemParameter(MachineInstr &MI,
MachineIRBuilder &B,
uint64_t Offset,
Align Alignment) const { … }
bool AMDGPULegalizerInfo::legalizeFDIV(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
void AMDGPULegalizerInfo::legalizeUnsignedDIV_REM32Impl(MachineIRBuilder &B,
Register DstDivReg,
Register DstRemReg,
Register X,
Register Y) const { … }
static std::pair<Register, Register> emitReciprocalU64(MachineIRBuilder &B,
Register Val) { … }
void AMDGPULegalizerInfo::legalizeUnsignedDIV_REM64Impl(MachineIRBuilder &B,
Register DstDivReg,
Register DstRemReg,
Register Numer,
Register Denom) const { … }
bool AMDGPULegalizerInfo::legalizeUnsignedDIV_REM(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeSignedDIV_REM(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeFastUnsafeFDIV(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeFastUnsafeFDIV64(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeFDIV16(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
static constexpr unsigned SPDenormModeBitField = …;
static void toggleSPDenormMode(bool Enable, MachineIRBuilder &B,
const GCNSubtarget &ST,
SIModeRegisterDefaults Mode) { … }
bool AMDGPULegalizerInfo::legalizeFDIV32(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeFDIV64(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeFFREXP(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeFDIVFastIntrin(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeFSQRTF16(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeFSQRTF32(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeFSQRTF64(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeFSQRT(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeRsqClampIntrinsic(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeLaneOp(LegalizerHelper &Helper,
MachineInstr &MI,
Intrinsic::ID IID) const { … }
bool AMDGPULegalizerInfo::getImplicitArgPtr(Register DstReg,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizePointerAsRsrcIntrin(
MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeImplicitArgPtr(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::getLDSKernelId(Register DstReg,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeLDSKernelId(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeIsAddrSpace(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B,
unsigned AddrSpace) const { … }
std::pair<Register, unsigned>
AMDGPULegalizerInfo::splitBufferOffsets(MachineIRBuilder &B,
Register OrigOffset) const { … }
Register AMDGPULegalizerInfo::handleD16VData(MachineIRBuilder &B,
MachineRegisterInfo &MRI,
Register Reg,
bool ImageStore) const { … }
Register AMDGPULegalizerInfo::fixStoreSourceType(MachineIRBuilder &B,
Register VData, LLT MemTy,
bool IsFormat) const { … }
bool AMDGPULegalizerInfo::legalizeBufferStore(MachineInstr &MI,
LegalizerHelper &Helper,
bool IsTyped,
bool IsFormat) const { … }
static void buildBufferLoad(unsigned Opc, Register LoadDstReg, Register RSrc,
Register VIndex, Register VOffset, Register SOffset,
unsigned ImmOffset, unsigned Format,
unsigned AuxiliaryData, MachineMemOperand *MMO,
bool IsTyped, bool HasVIndex, MachineIRBuilder &B) { … }
bool AMDGPULegalizerInfo::legalizeBufferLoad(MachineInstr &MI,
LegalizerHelper &Helper,
bool IsFormat,
bool IsTyped) const { … }
static unsigned getBufferAtomicPseudo(Intrinsic::ID IntrID) { … }
bool AMDGPULegalizerInfo::legalizeBufferAtomic(MachineInstr &MI,
MachineIRBuilder &B,
Intrinsic::ID IID) const { … }
static void packImage16bitOpsToDwords(MachineIRBuilder &B, MachineInstr &MI,
SmallVectorImpl<Register> &PackedAddrs,
unsigned ArgOffset,
const AMDGPU::ImageDimIntrinsicInfo *Intr,
bool IsA16, bool IsG16) { … }
static void convertImageAddrToPacked(MachineIRBuilder &B, MachineInstr &MI,
int DimIdx, int NumVAddrs) { … }
bool AMDGPULegalizerInfo::legalizeImageIntrinsic(
MachineInstr &MI, MachineIRBuilder &B, GISelChangeObserver &Observer,
const AMDGPU::ImageDimIntrinsicInfo *Intr) const { … }
bool AMDGPULegalizerInfo::legalizeSBufferLoad(LegalizerHelper &Helper,
MachineInstr &MI) const { … }
bool AMDGPULegalizerInfo::legalizeSBufferPrefetch(LegalizerHelper &Helper,
MachineInstr &MI) const { … }
bool AMDGPULegalizerInfo::legalizeTrap(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeTrapEndpgm(
MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeTrapHsaQueuePtr(
MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeTrapHsa(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeDebugTrap(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeBVHIntrinsic(MachineInstr &MI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeStackSave(MachineInstr &MI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeWaveID(MachineInstr &MI,
MachineIRBuilder &B) const { … }
static constexpr unsigned FPEnvModeBitField = …;
static constexpr unsigned FPEnvTrapBitField = …;
bool AMDGPULegalizerInfo::legalizeGetFPEnv(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeSetFPEnv(MachineInstr &MI,
MachineRegisterInfo &MRI,
MachineIRBuilder &B) const { … }
bool AMDGPULegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
MachineInstr &MI) const { … }