//=====-- AMDGPUSubtarget.h - Define Subtarget for AMDGPU ------*- C++ -*-====// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //==-----------------------------------------------------------------------===// // /// \file /// \brief AMDGPU specific subclass of TargetSubtarget. // //===----------------------------------------------------------------------===// #ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUSUBTARGET_H #define LLVM_LIB_TARGET_AMDGPU_AMDGPUSUBTARGET_H #include "AMDGPU.h" #include "R600InstrInfo.h" #include "R600ISelLowering.h" #include "R600FrameLowering.h" #include "SIInstrInfo.h" #include "SIISelLowering.h" #include "SIFrameLowering.h" #include "Utils/AMDGPUBaseInfo.h" #include "llvm/CodeGen/GlobalISel/GISelAccessor.h" #include "llvm/Target/TargetSubtargetInfo.h" #define GET_SUBTARGETINFO_HEADER #include "AMDGPUGenSubtargetInfo.inc" namespace llvm { class SIMachineFunctionInfo; class StringRef; class AMDGPUSubtarget : public AMDGPUGenSubtargetInfo { public: enum Generation { R600 = 0, R700, EVERGREEN, NORTHERN_ISLANDS, SOUTHERN_ISLANDS, SEA_ISLANDS, VOLCANIC_ISLANDS, }; enum { ISAVersion0_0_0, ISAVersion7_0_0, ISAVersion7_0_1, ISAVersion8_0_0, ISAVersion8_0_1, ISAVersion8_0_3 }; protected: // Basic subtarget description. Triple TargetTriple; Generation Gen; unsigned IsaVersion; unsigned WavefrontSize; int LocalMemorySize; int LDSBankCount; unsigned MaxPrivateElementSize; // Possibly statically set by tablegen, but may want to be overridden. bool FastFMAF32; bool HalfRate64Ops; // Dynamially set bits that enable features. bool FP32Denormals; bool FP64Denormals; bool FPExceptions; bool FlatForGlobal; bool UnalignedBufferAccess; bool EnableXNACK; bool DebuggerInsertNops; bool DebuggerReserveRegs; bool DebuggerEmitPrologue; // Used as options. bool EnableVGPRSpilling; bool EnablePromoteAlloca; bool EnableLoadStoreOpt; bool EnableUnsafeDSOffsetFolding; bool EnableSIScheduler; bool DumpCode; // Subtarget statically properties set by tablegen bool FP64; bool IsGCN; bool GCN1Encoding; bool GCN3Encoding; bool CIInsts; bool SGPRInitBug; bool HasSMemRealTime; bool Has16BitInsts; bool FlatAddressSpace; bool R600ALUInst; bool CaymanISA; bool CFALUBug; bool HasVertexCache; short TexVTXClauseSize; // Dummy feature to use for assembler in tablegen. bool FeatureDisable; InstrItineraryData InstrItins; public: AMDGPUSubtarget(const Triple &TT, StringRef GPU, StringRef FS, const TargetMachine &TM); virtual ~AMDGPUSubtarget(); AMDGPUSubtarget &initializeSubtargetDependencies(const Triple &TT, StringRef GPU, StringRef FS); const AMDGPUInstrInfo *getInstrInfo() const override; const AMDGPUFrameLowering *getFrameLowering() const override; const AMDGPUTargetLowering *getTargetLowering() const override; const AMDGPURegisterInfo *getRegisterInfo() const override; const InstrItineraryData *getInstrItineraryData() const override { return &InstrItins; } void ParseSubtargetFeatures(StringRef CPU, StringRef FS); bool isAmdHsaOS() const { return TargetTriple.getOS() == Triple::AMDHSA; } Generation getGeneration() const { return Gen; } unsigned getWavefrontSize() const { return WavefrontSize; } int getLocalMemorySize() const { return LocalMemorySize; } int getLDSBankCount() const { return LDSBankCount; } unsigned getMaxPrivateElementSize() const { return MaxPrivateElementSize; } bool hasHWFP64() const { return FP64; } bool hasFastFMAF32() const { return FastFMAF32; } bool hasHalfRate64Ops() const { return HalfRate64Ops; } bool hasAddr64() const { return (getGeneration() < VOLCANIC_ISLANDS); } bool hasBFE() const { return (getGeneration() >= EVERGREEN); } bool hasBFI() const { return (getGeneration() >= EVERGREEN); } bool hasBFM() const { return hasBFE(); } bool hasBCNT(unsigned Size) const { if (Size == 32) return (getGeneration() >= EVERGREEN); if (Size == 64) return (getGeneration() >= SOUTHERN_ISLANDS); return false; } bool hasMulU24() const { return (getGeneration() >= EVERGREEN); } bool hasMulI24() const { return (getGeneration() >= SOUTHERN_ISLANDS || hasCaymanISA()); } bool hasFFBL() const { return (getGeneration() >= EVERGREEN); } bool hasFFBH() const { return (getGeneration() >= EVERGREEN); } bool hasCARRY() const { return (getGeneration() >= EVERGREEN); } bool hasBORROW() const { return (getGeneration() >= EVERGREEN); } bool hasCaymanISA() const { return CaymanISA; } bool isPromoteAllocaEnabled() const { return EnablePromoteAlloca; } bool unsafeDSOffsetFoldingEnabled() const { return EnableUnsafeDSOffsetFolding; } bool dumpCode() const { return DumpCode; } /// Return the amount of LDS that can be used that will not restrict the /// occupancy lower than WaveCount. unsigned getMaxLocalMemSizeWithWaveCount(unsigned WaveCount) const; /// Inverse of getMaxLocalMemWithWaveCount. Return the maximum wavecount if /// the given LDS memory size is the only constraint. unsigned getOccupancyWithLocalMemSize(uint32_t Bytes) const; bool hasFP32Denormals() const { return FP32Denormals; } bool hasFP64Denormals() const { return FP64Denormals; } bool hasFPExceptions() const { return FPExceptions; } bool useFlatForGlobal() const { return FlatForGlobal; } bool hasUnalignedBufferAccess() const { return UnalignedBufferAccess; } bool isXNACKEnabled() const { return EnableXNACK; } unsigned getMaxWavesPerCU() const { if (getGeneration() >= AMDGPUSubtarget::SOUTHERN_ISLANDS) return 10; // FIXME: Not sure what this is for other subtagets. return 8; } /// \brief Returns the offset in bytes from the start of the input buffer /// of the first explicit kernel argument. unsigned getExplicitKernelArgOffset() const { return isAmdHsaOS() ? 0 : 36; } unsigned getStackAlignment() const { // Scratch is allocated in 256 dword per wave blocks. return 4 * 256 / getWavefrontSize(); } bool enableMachineScheduler() const override { return true; } bool enableSubRegLiveness() const override { return true; } }; class R600Subtarget final : public AMDGPUSubtarget { private: R600InstrInfo InstrInfo; R600FrameLowering FrameLowering; R600TargetLowering TLInfo; public: R600Subtarget(const Triple &TT, StringRef CPU, StringRef FS, const TargetMachine &TM); const R600InstrInfo *getInstrInfo() const override { return &InstrInfo; } const R600FrameLowering *getFrameLowering() const override { return &FrameLowering; } const R600TargetLowering *getTargetLowering() const override { return &TLInfo; } const R600RegisterInfo *getRegisterInfo() const override { return &InstrInfo.getRegisterInfo(); } bool hasCFAluBug() const { return CFALUBug; } bool hasVertexCache() const { return HasVertexCache; } short getTexVTXClauseSize() const { return TexVTXClauseSize; } unsigned getStackEntrySize() const; }; class SISubtarget final : public AMDGPUSubtarget { public: enum { FIXED_SGPR_COUNT_FOR_INIT_BUG = 80 }; private: SIInstrInfo InstrInfo; SIFrameLowering FrameLowering; SITargetLowering TLInfo; std::unique_ptr GISel; public: SISubtarget(const Triple &TT, StringRef CPU, StringRef FS, const TargetMachine &TM); const SIInstrInfo *getInstrInfo() const override { return &InstrInfo; } const SIFrameLowering *getFrameLowering() const override { return &FrameLowering; } const SITargetLowering *getTargetLowering() const override { return &TLInfo; } const CallLowering *getCallLowering() const override { assert(GISel && "Access to GlobalISel APIs not set"); return GISel->getCallLowering(); } const SIRegisterInfo *getRegisterInfo() const override { return &InstrInfo.getRegisterInfo(); } void setGISelAccessor(GISelAccessor &GISel) { this->GISel.reset(&GISel); } void overrideSchedPolicy(MachineSchedPolicy &Policy, unsigned NumRegionInstrs) const override; bool isVGPRSpillingEnabled(const Function& F) const; unsigned getAmdKernelCodeChipID() const; AMDGPU::IsaVersion getIsaVersion() const; unsigned getMaxNumUserSGPRs() const { return 16; } bool hasFlatAddressSpace() const { return FlatAddressSpace; } bool hasSMemRealTime() const { return HasSMemRealTime; } bool has16BitInsts() const { return Has16BitInsts; } bool enableSIScheduler() const { return EnableSIScheduler; } bool debuggerSupported() const { return debuggerInsertNops() && debuggerReserveRegs() && debuggerEmitPrologue(); } bool debuggerInsertNops() const { return DebuggerInsertNops; } bool debuggerReserveRegs() const { return DebuggerReserveRegs; } bool debuggerEmitPrologue() const { return DebuggerEmitPrologue; } bool loadStoreOptEnabled() const { return EnableLoadStoreOpt; } bool hasSGPRInitBug() const { return SGPRInitBug; } }; inline const AMDGPUInstrInfo *AMDGPUSubtarget::getInstrInfo() const { if (getGeneration() >= SOUTHERN_ISLANDS) return static_cast(this)->getInstrInfo(); return static_cast(this)->getInstrInfo(); } inline const AMDGPUFrameLowering *AMDGPUSubtarget::getFrameLowering() const { if (getGeneration() >= SOUTHERN_ISLANDS) return static_cast(this)->getFrameLowering(); return static_cast(this)->getFrameLowering(); } inline const AMDGPUTargetLowering *AMDGPUSubtarget::getTargetLowering() const { if (getGeneration() >= SOUTHERN_ISLANDS) return static_cast(this)->getTargetLowering(); return static_cast(this)->getTargetLowering(); } inline const AMDGPURegisterInfo *AMDGPUSubtarget::getRegisterInfo() const { if (getGeneration() >= SOUTHERN_ISLANDS) return static_cast(this)->getRegisterInfo(); return static_cast(this)->getRegisterInfo(); } } // End namespace llvm #endif