1 //===-- SIModeRegisterDefaults.cpp ------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "SIModeRegisterDefaults.h" 10 #include "GCNSubtarget.h" 11 12 using namespace llvm; 13 14 SIModeRegisterDefaults::SIModeRegisterDefaults(const Function &F, 15 const GCNSubtarget &ST) { 16 *this = getDefaultForCallingConv(F.getCallingConv()); 17 18 if (ST.hasIEEEMode()) { 19 StringRef IEEEAttr = F.getFnAttribute("amdgpu-ieee").getValueAsString(); 20 if (!IEEEAttr.empty()) 21 IEEE = IEEEAttr == "true"; 22 } 23 24 if (ST.hasDX10ClampMode()) { 25 StringRef DX10ClampAttr = 26 F.getFnAttribute("amdgpu-dx10-clamp").getValueAsString(); 27 if (!DX10ClampAttr.empty()) 28 DX10Clamp = DX10ClampAttr == "true"; 29 } 30 31 StringRef DenormF32Attr = 32 F.getFnAttribute("denormal-fp-math-f32").getValueAsString(); 33 if (!DenormF32Attr.empty()) 34 FP32Denormals = parseDenormalFPAttribute(DenormF32Attr); 35 36 StringRef DenormAttr = 37 F.getFnAttribute("denormal-fp-math").getValueAsString(); 38 if (!DenormAttr.empty()) { 39 DenormalMode DenormMode = parseDenormalFPAttribute(DenormAttr); 40 if (DenormF32Attr.empty()) 41 FP32Denormals = DenormMode; 42 FP64FP16Denormals = DenormMode; 43 } 44 } 45 46 using namespace AMDGPU; 47 48 /// Combine f32 and f64 rounding modes into a combined rounding mode value. 49 static constexpr uint32_t getModeRegisterRoundMode(uint32_t HWFP32Val, 50 uint32_t HWFP64Val) { 51 return HWFP32Val << F32FltRoundOffset | HWFP64Val << F64FltRoundOffset; 52 } 53 54 static constexpr uint64_t encodeFltRoundsTable(uint32_t FltRoundsVal, 55 uint32_t HWF32Val, 56 uint32_t HWF64Val) { 57 uint32_t ModeVal = getModeRegisterRoundMode(HWF32Val, HWF64Val); 58 if (FltRoundsVal > TowardNegative) 59 FltRoundsVal -= ExtendedFltRoundOffset; 60 61 uint32_t BitIndex = ModeVal << 2; 62 return static_cast<uint64_t>(FltRoundsVal) << BitIndex; 63 } 64 65 // Encode FLT_ROUNDS value where the two rounding modes are the same and use a 66 // standard value 67 static constexpr uint64_t 68 encodeFltRoundsTableSame(AMDGPUFltRounds FltRoundsMode, uint32_t HWVal) { 69 return encodeFltRoundsTable(FltRoundsMode, HWVal, HWVal); 70 } 71 72 // Convert mode register encoded rounding mode to AMDGPUFltRounds 73 static constexpr AMDGPUFltRounds 74 decodeIndexFltRoundConversionTable(uint32_t HWMode) { 75 uint32_t TableRead = (FltRoundConversionTable >> (HWMode << 2)) & 0xf; 76 if (TableRead > TowardNegative) 77 TableRead += ExtendedFltRoundOffset; 78 return static_cast<AMDGPUFltRounds>(TableRead); 79 } 80 81 static constexpr uint32_t HWTowardZero = FP_ROUND_ROUND_TO_ZERO; 82 static constexpr uint32_t HWNearestTiesToEven = FP_ROUND_ROUND_TO_NEAREST; 83 static constexpr uint32_t HWTowardPositive = FP_ROUND_ROUND_TO_INF; 84 static constexpr uint32_t HWTowardNegative = FP_ROUND_ROUND_TO_NEGINF; 85 86 const uint64_t AMDGPU::FltRoundConversionTable = 87 encodeFltRoundsTableSame(TowardZeroF32_TowardZeroF64, HWTowardZero) | 88 encodeFltRoundsTableSame(NearestTiesToEvenF32_NearestTiesToEvenF64, 89 HWNearestTiesToEven) | 90 encodeFltRoundsTableSame(TowardPositiveF32_TowardPositiveF64, 91 HWTowardPositive) | 92 encodeFltRoundsTableSame(TowardNegativeF32_TowardNegativeF64, 93 HWTowardNegative) | 94 95 encodeFltRoundsTable(TowardZeroF32_NearestTiesToEvenF64, HWTowardZero, 96 HWNearestTiesToEven) | 97 encodeFltRoundsTable(TowardZeroF32_TowardPositiveF64, HWTowardZero, 98 HWTowardPositive) | 99 encodeFltRoundsTable(TowardZeroF32_TowardNegativeF64, HWTowardZero, 100 HWTowardNegative) | 101 102 encodeFltRoundsTable(NearestTiesToEvenF32_TowardZeroF64, 103 HWNearestTiesToEven, HWTowardZero) | 104 encodeFltRoundsTable(NearestTiesToEvenF32_TowardPositiveF64, 105 HWNearestTiesToEven, HWTowardPositive) | 106 encodeFltRoundsTable(NearestTiesToEvenF32_TowardNegativeF64, 107 HWNearestTiesToEven, HWTowardNegative) | 108 109 encodeFltRoundsTable(TowardPositiveF32_TowardZeroF64, HWTowardPositive, 110 HWTowardZero) | 111 encodeFltRoundsTable(TowardPositiveF32_NearestTiesToEvenF64, 112 HWTowardPositive, HWNearestTiesToEven) | 113 encodeFltRoundsTable(TowardPositiveF32_TowardNegativeF64, HWTowardPositive, 114 HWTowardNegative) | 115 116 encodeFltRoundsTable(TowardNegativeF32_TowardZeroF64, HWTowardNegative, 117 HWTowardZero) | 118 encodeFltRoundsTable(TowardNegativeF32_NearestTiesToEvenF64, 119 HWTowardNegative, HWNearestTiesToEven) | 120 encodeFltRoundsTable(TowardNegativeF32_TowardPositiveF64, HWTowardNegative, 121 HWTowardPositive); 122 123 // Verify evaluation of FltRoundConversionTable 124 125 // If both modes are the same, should return the standard values. 126 static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( 127 HWTowardZero, HWTowardZero)) == AMDGPUFltRounds::TowardZero); 128 static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( 129 HWNearestTiesToEven, HWNearestTiesToEven)) == 130 AMDGPUFltRounds::NearestTiesToEven); 131 static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( 132 HWTowardPositive, HWTowardPositive)) == 133 AMDGPUFltRounds::TowardPositive); 134 static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( 135 HWTowardNegative, HWTowardNegative)) == 136 AMDGPUFltRounds::TowardNegative); 137 138 static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( 139 HWTowardZero, HWNearestTiesToEven)) == 140 TowardZeroF32_NearestTiesToEvenF64); 141 static_assert(decodeIndexFltRoundConversionTable( 142 getModeRegisterRoundMode(HWTowardZero, HWTowardPositive)) == 143 TowardZeroF32_TowardPositiveF64); 144 static_assert(decodeIndexFltRoundConversionTable( 145 getModeRegisterRoundMode(HWTowardZero, HWTowardNegative)) == 146 TowardZeroF32_TowardNegativeF64); 147 148 static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( 149 HWNearestTiesToEven, HWTowardZero)) == 150 NearestTiesToEvenF32_TowardZeroF64); 151 static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( 152 HWNearestTiesToEven, HWTowardPositive)) == 153 NearestTiesToEvenF32_TowardPositiveF64); 154 static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( 155 HWNearestTiesToEven, HWTowardNegative)) == 156 NearestTiesToEvenF32_TowardNegativeF64); 157 158 static_assert(decodeIndexFltRoundConversionTable( 159 getModeRegisterRoundMode(HWTowardPositive, HWTowardZero)) == 160 TowardPositiveF32_TowardZeroF64); 161 static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( 162 HWTowardPositive, HWNearestTiesToEven)) == 163 TowardPositiveF32_NearestTiesToEvenF64); 164 static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( 165 HWTowardPositive, HWTowardNegative)) == 166 TowardPositiveF32_TowardNegativeF64); 167 168 static_assert(decodeIndexFltRoundConversionTable( 169 getModeRegisterRoundMode(HWTowardNegative, HWTowardZero)) == 170 TowardNegativeF32_TowardZeroF64); 171 static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( 172 HWTowardNegative, HWNearestTiesToEven)) == 173 TowardNegativeF32_NearestTiesToEvenF64); 174 static_assert(decodeIndexFltRoundConversionTable(getModeRegisterRoundMode( 175 HWTowardNegative, HWTowardPositive)) == 176 TowardNegativeF32_TowardPositiveF64); 177