[PATCH] R600/SI: Add FP mode bits to binary.
Tom Stellard
tom at stellard.net
Thu Jun 26 06:42:46 PDT 2014
On Thu, Jun 19, 2014 at 06:24:31AM +0000, Matt Arsenault wrote:
> The default rounding mode to initialize the mode register needs
> to be reported to the runtime. Fill in other bits a kernel
> may be interested in setting for future use.
>
LGTM.
> http://reviews.llvm.org/D4205
>
> Files:
> lib/Target/R600/AMDGPUAsmPrinter.cpp
> lib/Target/R600/AMDGPUAsmPrinter.h
> lib/Target/R600/SIDefines.h
> test/CodeGen/R600/default-fp-mode.ll
> Index: lib/Target/R600/AMDGPUAsmPrinter.cpp
> ===================================================================
> --- lib/Target/R600/AMDGPUAsmPrinter.cpp
> +++ lib/Target/R600/AMDGPUAsmPrinter.cpp
> @@ -36,6 +36,22 @@
>
> using namespace llvm;
>
> +// TODO: This should get the default rounding mode from the kernel. We just set
> +// the default here, but this could change if the OpenCL rounding mode pragmas
> +// are used.
> +//
> +// The denormal mode here should match what is reported by the OpenCL runtime
> +// for the CL_FP_DENORM bit from CL_DEVICE_{HALF|SINGLE|DOUBLE}_FP_CONFIG. AMD
> +// OpenCL only sets flush none and reports CL_FP_DENORM for double precision,
> +// and leaves single precision to flush all and does not report CL_FP_DENORM for
> +// CL_DEVICE_SINGLE_FP_CONFIG. Mesa's OpenCL currently reports CL_FP_DENORM for
> +// both.
> +static uint32_t getFPMode(MachineFunction &) {
> + return FP_ROUND_MODE_SP(FP_ROUND_ROUND_TO_NEAREST) |
> + FP_ROUND_MODE_DP(FP_ROUND_ROUND_TO_NEAREST) |
> + FP_DENORM_MODE_SP(FP_DENORM_FLUSH_NONE) |
> + FP_DENORM_MODE_DP(FP_DENORM_FLUSH_NONE);
> +}
>
> static AsmPrinter *createAMDGPUAsmPrinterPass(TargetMachine &tm,
> MCStreamer &Streamer) {
> @@ -93,6 +109,10 @@
> false);
> OutStreamer.emitRawComment(" NumVgprs: " + Twine(KernelInfo.NumVGPR),
> false);
> + OutStreamer.emitRawComment(" FloatMode: " + Twine(KernelInfo.FloatMode),
> + false);
> + OutStreamer.emitRawComment(" IeeeMode: " + Twine(KernelInfo.IEEEMode),
> + false);
> } else {
> R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>();
> OutStreamer.emitRawComment(
> @@ -280,16 +300,27 @@
> if (VCCUsed)
> MaxSGPR += 2;
>
> - ProgInfo.CodeLen = CodeSize;
> - ProgInfo.NumSGPR = MaxSGPR;
> ProgInfo.NumVGPR = MaxVGPR;
> + ProgInfo.NumSGPR = MaxSGPR;
> +
> + // Set the value to initialize FP_ROUND and FP_DENORM parts of the mode
> + // register.
> + ProgInfo.FloatMode = getFPMode(MF);
> +
> + // XXX: Not quite sure what this does, but sc seems to unset this.
> + ProgInfo.IEEEMode = 0;
> +
> + // Do not clamp NAN to 0.
> + ProgInfo.DX10Clamp = 0;
> +
> + ProgInfo.CodeLen = CodeSize;
> }
>
> void AMDGPUAsmPrinter::EmitProgramInfoSI(MachineFunction &MF,
> const SIProgramInfo &KernelInfo) {
> const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();
> -
> SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
> +
> unsigned RsrcReg;
> switch (MFI->ShaderType) {
> default: // Fall through
> @@ -299,25 +330,41 @@
> case ShaderType::VERTEX: RsrcReg = R_00B128_SPI_SHADER_PGM_RSRC1_VS; break;
> }
>
> - OutStreamer.EmitIntValue(RsrcReg, 4);
> - OutStreamer.EmitIntValue(S_00B028_VGPRS(KernelInfo.NumVGPR / 4) |
> - S_00B028_SGPRS(KernelInfo.NumSGPR / 8), 4);
> -
> unsigned LDSAlignShift;
> if (STM.getGeneration() < AMDGPUSubtarget::SEA_ISLANDS) {
> - // LDS is allocated in 64 dword blocks
> + // LDS is allocated in 64 dword blocks.
> LDSAlignShift = 8;
> } else {
> - // LDS is allocated in 128 dword blocks
> + // LDS is allocated in 128 dword blocks.
> LDSAlignShift = 9;
> }
> +
> unsigned LDSBlocks =
> - RoundUpToAlignment(MFI->LDSSize, 1 << LDSAlignShift) >> LDSAlignShift;
> + RoundUpToAlignment(MFI->LDSSize, 1 << LDSAlignShift) >> LDSAlignShift;
>
> if (MFI->ShaderType == ShaderType::COMPUTE) {
> + OutStreamer.EmitIntValue(R_00B848_COMPUTE_PGM_RSRC1, 4);
> +
> + const uint32_t ComputePGMRSrc1 =
> + S_00B848_VGPRS(KernelInfo.NumVGPR / 4) |
> + S_00B848_SGPRS(KernelInfo.NumSGPR / 8) |
> + S_00B848_PRIORITY(KernelInfo.Priority) |
> + S_00B848_FLOAT_MODE(KernelInfo.FloatMode) |
> + S_00B848_PRIV(KernelInfo.Priv) |
> + S_00B848_DX10_CLAMP(KernelInfo.DX10Clamp) |
> + S_00B848_IEEE_MODE(KernelInfo.DebugMode) |
> + S_00B848_IEEE_MODE(KernelInfo.IEEEMode);
> +
> + OutStreamer.EmitIntValue(ComputePGMRSrc1, 4);
> +
> OutStreamer.EmitIntValue(R_00B84C_COMPUTE_PGM_RSRC2, 4);
> OutStreamer.EmitIntValue(S_00B84C_LDS_SIZE(LDSBlocks), 4);
> + } else {
> + OutStreamer.EmitIntValue(RsrcReg, 4);
> + OutStreamer.EmitIntValue(S_00B028_VGPRS(KernelInfo.NumVGPR / 4) |
> + S_00B028_SGPRS(KernelInfo.NumSGPR / 8), 4);
> }
> +
> if (MFI->ShaderType == ShaderType::PIXEL) {
> OutStreamer.EmitIntValue(R_00B02C_SPI_SHADER_PGM_RSRC2_PS, 4);
> OutStreamer.EmitIntValue(S_00B02C_EXTRA_LDS_SIZE(LDSBlocks), 4);
> Index: lib/Target/R600/AMDGPUAsmPrinter.h
> ===================================================================
> --- lib/Target/R600/AMDGPUAsmPrinter.h
> +++ lib/Target/R600/AMDGPUAsmPrinter.h
> @@ -25,13 +25,28 @@
> private:
> struct SIProgramInfo {
> SIProgramInfo() :
> - CodeLen(0),
> + NumVGPR(0),
> NumSGPR(0),
> - NumVGPR(0) {}
> + Priority(0),
> + FloatMode(0),
> + Priv(0),
> + DX10Clamp(0),
> + DebugMode(0),
> + IEEEMode(0),
> + CodeLen(0) {}
>
> + // Fields set in PGM_RSRC1 pm4 packet.
> + uint32_t NumVGPR;
> + uint32_t NumSGPR;
> + uint32_t Priority;
> + uint32_t FloatMode;
> + uint32_t Priv;
> + uint32_t DX10Clamp;
> + uint32_t DebugMode;
> + uint32_t IEEEMode;
> +
> + // Bonus information for debugging.
> uint64_t CodeLen;
> - unsigned NumSGPR;
> - unsigned NumVGPR;
> };
>
> void getSIProgramInfo(SIProgramInfo &Out, MachineFunction &MF) const;
> Index: lib/Target/R600/SIDefines.h
> ===================================================================
> --- lib/Target/R600/SIDefines.h
> +++ lib/Target/R600/SIDefines.h
> @@ -35,4 +35,54 @@
> #define S_00B84C_LDS_SIZE(x) (((x) & 0x1FF) << 15)
> #define R_0286CC_SPI_PS_INPUT_ENA 0x0286CC
>
> +
> +#define R_00B848_COMPUTE_PGM_RSRC1 0x00B848
> +#define S_00B848_VGPRS(x) (((x) & 0x3F) << 0)
> +#define G_00B848_VGPRS(x) (((x) >> 0) & 0x3F)
> +#define C_00B848_VGPRS 0xFFFFFFC0
> +#define S_00B848_SGPRS(x) (((x) & 0x0F) << 6)
> +#define G_00B848_SGPRS(x) (((x) >> 6) & 0x0F)
> +#define C_00B848_SGPRS 0xFFFFFC3F
> +#define S_00B848_PRIORITY(x) (((x) & 0x03) << 10)
> +#define G_00B848_PRIORITY(x) (((x) >> 10) & 0x03)
> +#define C_00B848_PRIORITY 0xFFFFF3FF
> +#define S_00B848_FLOAT_MODE(x) (((x) & 0xFF) << 12)
> +#define G_00B848_FLOAT_MODE(x) (((x) >> 12) & 0xFF)
> +#define C_00B848_FLOAT_MODE 0xFFF00FFF
> +#define S_00B848_PRIV(x) (((x) & 0x1) << 20)
> +#define G_00B848_PRIV(x) (((x) >> 20) & 0x1)
> +#define C_00B848_PRIV 0xFFEFFFFF
> +#define S_00B848_DX10_CLAMP(x) (((x) & 0x1) << 21)
> +#define G_00B848_DX10_CLAMP(x) (((x) >> 21) & 0x1)
> +#define C_00B848_DX10_CLAMP 0xFFDFFFFF
> +#define S_00B848_DEBUG_MODE(x) (((x) & 0x1) << 22)
> +#define G_00B848_DEBUG_MODE(x) (((x) >> 22) & 0x1)
> +#define C_00B848_DEBUG_MODE 0xFFBFFFFF
> +#define S_00B848_IEEE_MODE(x) (((x) & 0x1) << 23)
> +#define G_00B848_IEEE_MODE(x) (((x) >> 23) & 0x1)
> +#define C_00B848_IEEE_MODE 0xFF7FFFFF
> +
> +
> +// Helpers for setting FLOAT_MODE
> +#define FP_ROUND_ROUND_TO_NEAREST 0
> +#define FP_ROUND_ROUND_TO_INF 1
> +#define FP_ROUND_ROUND_TO_NEGINF 2
> +#define FP_ROUND_ROUND_TO_ZERO 3
> +
> +// Bits 3:0 control rounding mode. 1:0 control single precision, 3:2 double
> +// precision.
> +#define FP_ROUND_MODE_SP(x) ((x) & 0x3)
> +#define FP_ROUND_MODE_DP(x) (((x) & 0x3) << 2)
> +
> +#define FP_DENORM_FLUSH_IN_FLUSH_OUT 0
> +#define FP_DENORM_FLUSH_OUT 1
> +#define FP_DENORM_FLUSH_IN 2
> +#define FP_DENORM_FLUSH_NONE 3
> +
> +
> +// Bits 7:4 control denormal handling. 5:4 control single precision, 6:7 double
> +// precision.
> +#define FP_DENORM_MODE_SP(x) (((x) & 0x3) << 4)
> +#define FP_DENORM_MODE_DP(x) (((x) & 0x3) << 6)
> +
> #endif // SIDEFINES_H_
> Index: test/CodeGen/R600/default-fp-mode.ll
> ===================================================================
> --- /dev/null
> +++ test/CodeGen/R600/default-fp-mode.ll
> @@ -0,0 +1,10 @@
> +; RUN: llc -march=r600 -mcpu=SI < %s | FileCheck -check-prefix=SI %s
> +
> +; SI-LABEL: @test_kernel
> +; SI: FloatMode: 240
> +; SI: IeeeMode: 0
> +define void @test_kernel(float addrspace(1)* %out0, double addrspace(1)* %out1) nounwind {
> + store float 0.0, float addrspace(1)* %out0
> + store double 0.0, double addrspace(1)* %out1
> + ret void
> +}
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list