//===-- SIModeRegisterDefaults.cpp ------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "SIModeRegisterDefaults.h" #include "GCNSubtarget.h" using namespace llvm; SIModeRegisterDefaults::SIModeRegisterDefaults(const Function &F, const GCNSubtarget &ST) { *this = getDefaultForCallingConv(F.getCallingConv()); if (ST.hasIEEEMode()) { StringRef IEEEAttr = F.getFnAttribute("amdgpu-ieee").getValueAsString(); if (!IEEEAttr.empty()) IEEE = IEEEAttr == "true"; } if (ST.hasDX10ClampMode()) { StringRef DX10ClampAttr = F.getFnAttribute("amdgpu-dx10-clamp").getValueAsString(); if (!DX10ClampAttr.empty()) DX10Clamp = DX10ClampAttr == "true"; } StringRef DenormF32Attr = F.getFnAttribute("denormal-fp-math-f32").getValueAsString(); if (!DenormF32Attr.empty()) FP32Denormals = parseDenormalFPAttribute(DenormF32Attr); StringRef DenormAttr = F.getFnAttribute("denormal-fp-math").getValueAsString(); if (!DenormAttr.empty()) { DenormalMode DenormMode = parseDenormalFPAttribute(DenormAttr); if (DenormF32Attr.empty()) FP32Denormals = DenormMode; FP64FP16Denormals = DenormMode; } } using namespace AMDGPU; /// Combine f32 and f64 rounding modes into a combined rounding mode value. static constexpr uint32_t getModeRegisterRoundMode(uint32_t HWFP32Val, uint32_t HWFP64Val) { return HWFP32Val << F32FltRoundOffset | HWFP64Val << F64FltRoundOffset; } static constexpr uint64_t encodeFltRoundsTable(uint32_t FltRoundsVal, uint32_t HWF32Val, uint32_t HWF64Val) { uint32_t ModeVal = getModeRegisterRoundMode(HWF32Val, HWF64Val); if (FltRoundsVal > TowardNegative) FltRoundsVal -= ExtendedFltRoundOffset; uint32_t BitIndex = ModeVal << 2; return static_cast(FltRoundsVal) << BitIndex; } // Encode FLT_ROUNDS value where the two rounding modes are the same and use a // standard value static constexpr uint64_t encodeFltRoundsTableSame(AMDGPUFltRounds FltRoundsMode, uint32_t HWVal) { return encodeFltRoundsTable(FltRoundsMode, HWVal, HWVal); } // Convert mode register encoded rounding mode to AMDGPUFltRounds static constexpr AMDGPUFltRounds decodeIndexFltRoundConversionTable(uint32_t HWMode) { uint32_t TableRead = (FltRoundConversionTable >> (HWMode << 2)) & 0xf; if (TableRead > TowardNegative) TableRead += ExtendedFltRoundOffset; return static_cast(TableRead); } static constexpr uint32_t HWTowardZero = FP_ROUND_ROUND_TO_ZERO; static constexpr uint32_t HWNearestTiesToEven = FP_ROUND_ROUND_TO_NEAREST; static constexpr uint32_t HWTowardPositive = FP_ROUND_ROUND_TO_INF; static constexpr uint32_t HWTowardNegative = FP_ROUND_ROUND_TO_NEGINF; const uint64_t AMDGPU::FltRoundConversionTable = encodeFltRoundsTableSame(TowardZeroF32_TowardZeroF64, HWTowardZero) | encodeFltRoundsTableSame(NearestTiesToEvenF32_NearestTiesToEvenF64, HWNearestTiesToEven) | encodeFltRoundsTableSame(TowardPositiveF32_TowardPositiveF64, HWTowardPositive) | encodeFltRoundsTableSame(TowardNegativeF32_TowardNegativeF64, HWTowardNegative) | encodeFltRoundsTable(TowardZeroF32_NearestTiesToEvenF64, HWTowardZero, HWNearestTiesToEven) | encodeFltRoundsTable(TowardZeroF32_TowardPositiveF64, HWTowardZero, HWTowardPositive) | encodeFltRoundsTable(TowardZeroF32_TowardNegativeF64, HWTowardZero, HWTowardNegative) | encodeFltRoundsTable(NearestTiesToEvenF32_TowardZeroF64, HWNearestTiesToEven, HWTowardZero) | encodeFltRoundsTable(NearestTiesToEvenF32_TowardPositiveF64, HWNearestTiesToEven, HWTowardPositive) | encodeFltRoundsTable(NearestTiesToEvenF32_TowardNegativeF64, HWNearestTiesToEven, HWTowardNegative) | encodeFltRoundsTable(TowardPositiveF32_TowardZeroF64, HWTowardPositive, HWTowardZero) | encodeFltRoundsTable(TowardPositiveF32_NearestTiesToEvenF64, HWTowardPositive, HWNearestTiesToEven) | encodeFltRoundsTable(TowardPositiveF32_TowardNegativeF64, HWTowardPositive, HWTowardNegative) | encodeFltRoundsTable(TowardNegativeF32_TowardZeroF64, HWTowardNegative, HWTowardZero) | encodeFltRoundsTable(TowardNegativeF32_NearestTiesToEvenF64, HWTowardNegative, HWNearestTiesToEven) | encodeFltRoundsTable(TowardNegativeF32_TowardPositiveF64, HWTowardNegative, HWTowardPositive); // Verify evaluation of FltRoundConversionTable // If both modes are the same, should return the standard values. static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( HWTowardZero, HWTowardZero)) == AMDGPUFltRounds::TowardZero); static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( HWNearestTiesToEven, HWNearestTiesToEven)) == AMDGPUFltRounds::NearestTiesToEven); static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( HWTowardPositive, HWTowardPositive)) == AMDGPUFltRounds::TowardPositive); static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( HWTowardNegative, HWTowardNegative)) == AMDGPUFltRounds::TowardNegative); static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( HWTowardZero, HWNearestTiesToEven)) == TowardZeroF32_NearestTiesToEvenF64); static_assert(decodeIndexFltRoundConversionTable( getModeRegisterRoundMode(HWTowardZero, HWTowardPositive)) == TowardZeroF32_TowardPositiveF64); static_assert(decodeIndexFltRoundConversionTable( getModeRegisterRoundMode(HWTowardZero, HWTowardNegative)) == TowardZeroF32_TowardNegativeF64); static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( HWNearestTiesToEven, HWTowardZero)) == NearestTiesToEvenF32_TowardZeroF64); static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( HWNearestTiesToEven, HWTowardPositive)) == NearestTiesToEvenF32_TowardPositiveF64); static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( HWNearestTiesToEven, HWTowardNegative)) == NearestTiesToEvenF32_TowardNegativeF64); static_assert(decodeIndexFltRoundConversionTable( getModeRegisterRoundMode(HWTowardPositive, HWTowardZero)) == TowardPositiveF32_TowardZeroF64); static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( HWTowardPositive, HWNearestTiesToEven)) == TowardPositiveF32_NearestTiesToEvenF64); static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( HWTowardPositive, HWTowardNegative)) == TowardPositiveF32_TowardNegativeF64); static_assert(decodeIndexFltRoundConversionTable( getModeRegisterRoundMode(HWTowardNegative, HWTowardZero)) == TowardNegativeF32_TowardZeroF64); static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( HWTowardNegative, HWNearestTiesToEven)) == TowardNegativeF32_NearestTiesToEvenF64); static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( HWTowardNegative, HWTowardPositive)) == TowardNegativeF32_TowardPositiveF64);