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