1 //=- VectorComputeUtil.cpp - vector compute utilities implemetation * C++ -*-=//
2 //
3 // The LLVM/SPIR-V Translator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 // Copyright (c) 2020 Intel Corporation. All rights reserved.
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal with the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
16 //
17 // Redistributions of source code must retain the above copyright notice,
18 // this list of conditions and the following disclaimers.
19 // Redistributions in binary form must reproduce the above copyright notice,
20 // this list of conditions and the following disclaimers in the documentation
21 // and/or other materials provided with the distribution.
22 // Neither the names of Intel Corporation, nor the names of its
23 // contributors may be used to endorse or promote products derived from this
24 // Software without specific prior written permission.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
31 // THE SOFTWARE.
32 //
33 //===----------------------------------------------------------------------===//
34 //
35 // This file implements translation of VC float control bits
36 //
37 //===----------------------------------------------------------------------===//
38
39 #include "VectorComputeUtil.h"
40 #include "SPIRVInternal.h"
41 #include "llvm/IR/Metadata.h"
42 using namespace VectorComputeUtil;
43 using namespace SPIRV;
44
45 enum VCFloatControl {
46 VC_RTE = 0, // Round to nearest or even
47 VC_RTP = 1 << 4, // Round towards +ve inf
48 VC_RTN = 2 << 4, // Round towards -ve inf
49 VC_RTZ = 3 << 4, // Round towards zero
50
51 VC_DENORM_FTZ = 0, // Denorm mode flush to zero
52 VC_DENORM_D_ALLOW = 1 << 6, // Denorm mode double allow
53 VC_DENORM_F_ALLOW = 1 << 7, // Denorm mode float allow
54 VC_DENORM_HF_ALLOW = 1 << 10, // Denorm mode half allow
55
56 VC_FLOAT_MODE_IEEE = 0, // Single precision float IEEE mode
57 VC_FLOAT_MODE_ALT = 1 // Single precision float ALT mode
58 };
59
60 enum VCFloatControlMask {
61 VC_ROUND_MASK = (VC_RTE | VC_RTP | VC_RTN | VC_RTZ),
62 VC_FLOAT_MASK = (VC_FLOAT_MODE_IEEE | VC_FLOAT_MODE_ALT)
63 };
64
65 typedef SPIRVMap<FPRoundingMode, VCFloatControl> FPRoundingModeControlBitMap;
66 typedef SPIRVMap<FPOperationMode, VCFloatControl> FPOperationModeControlBitMap;
67 typedef SPIRVMap<VCFloatType, VCFloatControl> VCFloatTypeDenormMaskMap;
init()68 template <> inline void SPIRVMap<FPRoundingMode, VCFloatControl>::init() {
69 add(spv::FPRoundingModeRTE, VC_RTE);
70 add(spv::FPRoundingModeRTP, VC_RTP);
71 add(spv::FPRoundingModeRTN, VC_RTN);
72 add(spv::FPRoundingModeRTZ, VC_RTZ);
73 }
init()74 template <> inline void SPIRVMap<FPOperationMode, VCFloatControl>::init() {
75 add(spv::FPOperationModeIEEE, VC_FLOAT_MODE_IEEE);
76 add(spv::FPOperationModeALT, VC_FLOAT_MODE_ALT);
77 }
init()78 template <> inline void SPIRVMap<VCFloatType, VCFloatControl>::init() {
79 add(Double, VC_DENORM_D_ALLOW);
80 add(Float, VC_DENORM_F_ALLOW);
81 add(Half, VC_DENORM_HF_ALLOW);
82 }
83
84 namespace VectorComputeUtil {
85
getFPRoundingMode(unsigned FloatControl)86 FPRoundingMode getFPRoundingMode(unsigned FloatControl) noexcept {
87 return FPRoundingModeControlBitMap::rmap(
88 VCFloatControl(VC_ROUND_MASK & FloatControl));
89 }
90
getFPDenormMode(unsigned FloatControl,VCFloatType FloatType)91 FPDenormMode getFPDenormMode(unsigned FloatControl,
92 VCFloatType FloatType) noexcept {
93 VCFloatControl DenormMask =
94 VCFloatTypeDenormMaskMap::map(FloatType); // 1 Bit mask
95 return (DenormMask == (DenormMask & FloatControl))
96 ? spv::FPDenormModePreserve
97 : spv::FPDenormModeFlushToZero;
98 }
99
getFPOperationMode(unsigned FloatControl)100 FPOperationMode getFPOperationMode(unsigned FloatControl) noexcept {
101 return FPOperationModeControlBitMap::rmap(
102 VCFloatControl(VC_FLOAT_MASK & FloatControl));
103 }
104
getVCFloatControl(FPRoundingMode RoundMode)105 unsigned getVCFloatControl(FPRoundingMode RoundMode) noexcept {
106 return FPRoundingModeControlBitMap::map(RoundMode);
107 }
getVCFloatControl(FPOperationMode FloatMode)108 unsigned getVCFloatControl(FPOperationMode FloatMode) noexcept {
109 return FPOperationModeControlBitMap::map(FloatMode);
110 }
getVCFloatControl(FPDenormMode DenormMode,VCFloatType FloatType)111 unsigned getVCFloatControl(FPDenormMode DenormMode,
112 VCFloatType FloatType) noexcept {
113 if (DenormMode == spv::FPDenormModePreserve)
114 return VCFloatTypeDenormMaskMap::map(FloatType);
115 return VC_DENORM_FTZ;
116 }
117
118 SPIRVStorageClassKind
getVCGlobalVarStorageClass(SPIRAddressSpace AddressSpace)119 getVCGlobalVarStorageClass(SPIRAddressSpace AddressSpace) noexcept {
120 switch (AddressSpace) {
121 case SPIRAS_Private:
122 return StorageClassPrivate;
123 case SPIRAS_Local:
124 return StorageClassWorkgroup;
125 case SPIRAS_Global:
126 return StorageClassCrossWorkgroup;
127 case SPIRAS_Constant:
128 return StorageClassUniformConstant;
129 default:
130 assert(false && "Unexpected address space");
131 return StorageClassPrivate;
132 }
133 }
134
135 SPIRAddressSpace
getVCGlobalVarAddressSpace(SPIRVStorageClassKind StorageClass)136 getVCGlobalVarAddressSpace(SPIRVStorageClassKind StorageClass) noexcept {
137 switch (StorageClass) {
138 case StorageClassPrivate:
139 return SPIRAS_Private;
140 case StorageClassWorkgroup:
141 return SPIRAS_Local;
142 case StorageClassCrossWorkgroup:
143 return SPIRAS_Global;
144 case StorageClassUniformConstant:
145 return SPIRAS_Constant;
146 default:
147 assert(false && "Unexpected storage class");
148 return SPIRAS_Private;
149 }
150 }
151
getVCBufferSurfaceName()152 std::string getVCBufferSurfaceName() {
153 return std::string(kVCType::VCBufferSurface) + kAccessQualPostfix::Type;
154 }
155
getVCBufferSurfaceName(SPIRVAccessQualifierKind Access)156 std::string getVCBufferSurfaceName(SPIRVAccessQualifierKind Access) {
157 return std::string(kVCType::VCBufferSurface) +
158 getAccessQualifierPostfix(Access).str() + kAccessQualPostfix::Type;
159 }
160
161 } // namespace VectorComputeUtil
162