1 /*========================== begin_copyright_notice ============================ 2 3 Copyright (C) 2017-2021 Intel Corporation 4 5 SPDX-License-Identifier: MIT 6 7 ============================= end_copyright_notice ===========================*/ 8 9 #pragma once 10 11 #include "Compiler/CodeGenPublic.h" 12 #include "Compiler/MetaDataApi/MetaDataApi.h" 13 #include "Compiler/Optimizer/ValueTracker.h" 14 #include "common/LLVMWarningsPush.hpp" 15 #include <llvm/ADT/MapVector.h> 16 #include <llvm/ADT/StringRef.h> 17 #include <llvmWrapper/IR/Intrinsics.h> 18 #include "common/LLVMWarningsPop.hpp" 19 #include "GenISAIntrinsics/GenIntrinsics.h" 20 #include <map> 21 #include "Probe/Assertion.h" 22 23 namespace llvm 24 { 25 class CallInst; 26 } 27 28 namespace IGC 29 { 30 class CCommand 31 { 32 public: 33 /// @brief gets llvm function declaration for GenISA_ISA Intrinsic 34 /// @param Id the wanted GenISA_ISA intrinsic 35 /// @param ptrTy for intrinsic with overloaded types. 36 /// @returns llvm Function 37 llvm::Function* getFunctionDeclaration(llvm::GenISAIntrinsic::ID id, llvm::ArrayRef<llvm::Type*> Tys = llvm::None); 38 39 /// @brief gets llvm function declaration for LLVM Intrinsic 40 /// @param Id the wanted LLVM intrinsic 41 /// @param ptrTy for intrinsic with overloaded types. 42 /// @returns llvm Function 43 llvm::Function* getFunctionDeclaration(IGCLLVM::Intrinsic id, llvm::ArrayRef<llvm::Type*> Tys = llvm::None); 44 45 /// @brief Creates llvm function call for LLVM Intrinsic and replace the 46 /// current instruction with the new function call. 47 /// @param Id the wanted LLVM intrinsic 48 /// @param ptrTy for intrinsic with overloaded types. 49 void replaceCallInst(IGCLLVM::Intrinsic intrinsicName, llvm::ArrayRef<llvm::Type*> Tys = llvm::None); 50 51 52 /// @brief Creates llvm function call for GenISA_ISA Intrinsic and replace the 53 /// current instruction with the new function call. 54 /// @param Id the wanted GenISA_ISA intrinsic 55 /// @param ptrTy for intrinsic with overloaded types. 56 void replaceGenISACallInst(llvm::GenISAIntrinsic::ID intrinsicName, llvm::ArrayRef<llvm::Type*> Tys = llvm::None); 57 58 /// @brief reap init() and createIntrinsic(). 59 /// @param Inst the call instruction that need to be replaced. 60 /// @param CodeGenContext context to return errors 61 void execute(llvm::CallInst* Inst, IGC::CodeGenContext* CodeGenContext); 62 63 /// @brief replace the old __builtin_IB function call with the match llvm/GenISA_ISA 64 /// instructions. 65 /// @param Inst the call instruction that need to be replaced. 66 virtual void createIntrinsic() = 0; 67 68 /// @brief verify that there are no user errors verifyCommand()69 virtual void verifyCommand() {} 70 71 /// @brief initialize the callInst, function, context, constants and clear the arg list. 72 /// @param Inst the call instruction that need to be replaced. 73 /// @param CodeGenContext context to return errors 74 void init(llvm::CallInst* Inst, IGC::CodeGenContext* CodeGenContext); 75 void clearArgsList(void); 76 77 enum CoordType 78 { 79 FloatType, 80 IntType 81 }; 82 CCommand(void)83 CCommand(void) : 84 m_pFloatZero(nullptr), 85 m_pIntZero(nullptr), 86 m_pIntOne(nullptr), 87 m_pCallInst(nullptr), 88 m_pFunc(nullptr), 89 m_pCtx(nullptr), 90 m_pCodeGenContext(nullptr), 91 m_pFloatType(nullptr), 92 m_pIntType(nullptr) 93 {} ~CCommand(void)94 virtual ~CCommand(void) {}; 95 96 protected: 97 llvm::Value* m_pFloatZero; 98 llvm::Value* m_pIntZero; 99 llvm::Value* m_pIntOne; 100 llvm::CallInst* m_pCallInst; 101 llvm::Function* m_pFunc; 102 llvm::LLVMContext* m_pCtx; 103 IGC::CodeGenContext* m_pCodeGenContext; 104 llvm::SmallVector<llvm::Value*, 10> m_args; 105 llvm::DebugLoc m_DL; 106 llvm::Type* m_pFloatType; 107 llvm::IntegerType* m_pIntType; 108 }; 109 ResourceTypeMap(ResourceTypeEnum type)110 static inline BufferType ResourceTypeMap(ResourceTypeEnum type) 111 { 112 switch (type) 113 { 114 case IGC::UAVResourceType: 115 return UAV; 116 case IGC::BindlessUAVResourceType: 117 return BINDLESS; 118 case IGC::SRVResourceType: 119 return RESOURCE; 120 case IGC::SamplerResourceType: 121 return SAMPLER; 122 case IGC::BindlessSamplerResourceType: 123 return BINDLESS_SAMPLER; 124 case IGC::OtherResourceType: 125 return BUFFER_TYPE_UNKNOWN; 126 default: 127 IGC_ASSERT_MESSAGE(0, "unknown type!"); 128 return BUFFER_TYPE_UNKNOWN; 129 } 130 }; 131 132 class CImagesBI : public CCommand 133 { 134 public: 135 enum Dimension 136 { 137 DIM_1D, 138 DIM_1D_ARRAY, 139 DIM_2D, 140 DIM_2D_ARRAY, 141 DIM_3D 142 }; 143 144 enum CoordComponents 145 { 146 COORD_X, 147 COORD_Y, 148 COORD_Z, 149 COORD_W 150 }; 151 152 struct ParamInfo 153 { ParamInfoParamInfo154 ParamInfo(int i, ResourceTypeEnum t, ResourceExtensionTypeEnum extension) : 155 index(i), type(ResourceTypeMap(t)), extension(extension) {} ParamInfoParamInfo156 ParamInfo() : 157 index(0), type(BUFFER_TYPE_UNKNOWN), extension(NonExtensionType) {} 158 159 int index; 160 BufferType type; 161 ResourceExtensionTypeEnum extension; 162 }; 163 164 typedef llvm::MapVector<llvm::Value*, ParamInfo> ParamMap; 165 typedef std::map<int, int> InlineMap; 166 167 class CImagesUtils 168 { 169 public: 170 /// @brief find the BTI of the image argumant 171 /// @param paramIndex the index of the image paramtere in the call isntruciton 172 /// @returns the image index 173 static llvm::ConstantInt* getImageIndex(ParamMap* pParamMap, llvm::CallInst* pCallInst, unsigned int paramIndex, llvm::Argument*& imageParam); 174 175 /// @brief find the type (UAV/RESOURCE) of the image argumant 176 /// @returns the image type 177 static BufferType getImageType(ParamMap* pParamMap, llvm::CallInst* pCallInst, unsigned int paramIndex); 178 179 /// @brief find the image argument associated with the given bufType and idx 180 /// @returns the image argument 181 static llvm::Argument* findImageFromBufferPtr(const IGC::IGCMD::MetaDataUtils& MdUtils, llvm::Function* F, BufferType bufType, uint64_t idx, const IGC::ModuleMetaData* modMD); 182 }; 183 CImagesBI(ParamMap * paramMap,InlineMap * inlineMap,int * nextSampler,Dimension Dim)184 CImagesBI(ParamMap* paramMap, InlineMap* inlineMap, int* nextSampler, Dimension Dim) : 185 m_pParamMap(paramMap), m_pInlineMap(inlineMap), m_pNextSampler(nextSampler), m_dim(Dim), 186 CoordX(nullptr), CoordY(nullptr), CoordZ(nullptr), m_IncorrectBti(false) {} 187 188 /// @brief push 3 zeros offset to the function argumant list 189 void prepareZeroOffsets(void); 190 191 /// @brief initilaize CoordX/Y/Z with the given coordinates. 192 /// @param Dim the image dimension 193 /// @param Coord the coords from the original intrinsic. 194 /// @param Zero const zero with the correct type (i.e. float or int) 195 /// it been use only for image_1d and image_2d 196 void prepareCoords(Dimension Dim, llvm::Value* Coord, llvm::Value* Zero); 197 198 /// @brief push the colors to the function argument list 199 /// @param Color the Color value 200 void prepareColor(llvm::Value* Color); 201 202 /// @brief set LOD to Zero and push the function argument list 203 /// @param Coord the type of zero (int or float) 204 void prepareLOD(CoordType Coord); 205 206 207 /// @brief push the sampler index into the function argument list 208 void prepareSamplerIndex(void); 209 210 /// @brief create a call to the GetBufferPtr intrinsic pseudo-instruction 211 /// @brief push the image index into the function argument list 212 void createGetBufferPtr(void); 213 214 /// @brief returns "true" if the "val" is integer or float with fractional part = 0. 215 static bool derivedFromInt(const llvm::Value* pVal); 216 217 void verifyCommand(); 218 219 protected: 220 /// @brief push the image index into the function argument list 221 void prepareImageBTI(void); 222 223 // m_pParamMap - maps image and sampler kernel parameters to BTIs 224 // and sampler array indexes, respecitvely 225 ParamMap* m_pParamMap; 226 227 // m_pInlineMap - maps inline sampler values (CLK_...) to sampler 228 // array indexes. 229 InlineMap* m_pInlineMap; 230 231 // The next sampler index to allocate a newly encountered 232 // inline sampler 233 int* m_pNextSampler; 234 235 Dimension m_dim; 236 llvm::Value* CoordX; 237 llvm::Value* CoordY; 238 llvm::Value* CoordZ; 239 bool m_IncorrectBti; 240 }; 241 242 class CBuiltinsResolver 243 { 244 private: 245 std::map<llvm::StringRef, std::unique_ptr<CCommand>> m_CommandMap; 246 247 // the list of known builtins not to be resolved 248 std::vector<llvm::StringRef> m_KnownBuiltins; 249 CodeGenContext* m_CodeGenContext; 250 public: 251 CBuiltinsResolver(CImagesBI::ParamMap* paramMap, CImagesBI::InlineMap* inlineMap, int* nextSampler, CodeGenContext* ctx); ~CBuiltinsResolver(void)252 ~CBuiltinsResolver(void) {} 253 254 // resolve __builtin_IB_* calls. 255 // return values: 256 // true - when CallInst was __builtin_IB_* and successfully repleced 257 // false - when CallInst wasn't __builtin_IB* 258 bool resolveBI(llvm::CallInst* Inst); 259 }; 260 261 union InlineSamplerState 262 { 263 struct _state 264 { 265 uint64_t TCXAddressMode : 3; 266 uint64_t TCYAddressMode : 3; 267 uint64_t TCZAddressMode : 3; 268 uint64_t MagFilterMode : 2; 269 uint64_t MinFilterMode : 2; 270 uint64_t MipFilterMode : 2; 271 uint64_t NormalizedCoords : 1; 272 uint64_t CompareFunction : 4; 273 uint64_t _reserved : 44; 274 } state; 275 uint64_t _Value; 276 InlineSamplerState()277 InlineSamplerState() : _Value(0) {} InlineSamplerState(uint64_t samplerValue)278 InlineSamplerState(uint64_t samplerValue) : _Value(samplerValue) {} 279 280 enum ADDRESS_MODE 281 { 282 ADDRESS_MODE_WRAP, 283 ADDRESS_MODE_CLAMP, 284 ADDRESS_MODE_MIRROR, 285 ADDRESS_MODE_BORDER, 286 ADDRESS_MODE_MIRRORONCE, 287 ADDRESS_MODE_MIRROR101, 288 NUM_ADDRESS_MODE 289 }; 290 291 enum MAP_FILTER_MODE // Applies for MagFilterMode and MinFilterMode 292 { 293 MAP_FILTER_MODE_POINT, 294 MAP_FILTER_MODE_LINEAR, 295 MAP_FILTER_MODE_ANISOTROPIC, 296 MAP_FILTER_MODE_GAUSSIANQUAD, 297 MAP_FILTER_MODE_PYRAMIDALQUAD, 298 MAP_FILTER_MODE_MONO, 299 NUM_MAP_FILTER_MODE 300 }; 301 302 enum MIP_FILTER_MODE 303 { 304 MIP_FILTER_MODE_POINT, 305 MIP_FILTER_MODE_LINEAR, 306 MIP_FILTER_MODE_NONE, 307 NUM_MIP_FILTER_MODE 308 }; 309 310 enum NORMALIZED_MODE 311 { 312 NORMALIZED_MODE_FALSE, 313 NORMALIZED_MODE_TRUE, 314 }; 315 316 enum COMPARE_FUNC 317 { 318 COMPARE_FUNC_NONE, 319 COMPARE_FUNC_LESS, 320 COMPARE_FUNC_LESS_EQUAL = 2, 321 COMPARE_FUNC_GREATER = 3, 322 COMPARE_FUNC_GREATER_EQUAL = 4, 323 COMPARE_FUNC_EQUAL = 5, 324 COMPARE_FUNC_NOT_EQUAL = 6, 325 COMPARE_FUNC_ALWAYS = 7, 326 COMPARE_FUNC_NEVER = 8, 327 NUM_COMPARE_FUNC 328 }; 329 }; 330 331 // Built-in image functions 332 // These values need to match the runtime equivalent 333 #define LEGACY_CLK_ADDRESS_NONE 0x00 334 #define LEGACY_CLK_ADDRESS_CLAMP 0x01 335 #define LEGACY_CLK_ADDRESS_CLAMP_TO_EDGE 0x02 336 #define LEGACY_CLK_ADDRESS_REPEAT 0x03 337 #define LEGACY_CLK_ADDRESS_MIRRORED_REPEAT 0x04 338 #define LEGACY_CLK_ADDRESS_MIRRORED_REPEAT_101_INTEL 0x05 339 340 #define LEGACY_CLK_NORMALIZED_COORDS_FALSE 0x00 341 #define LEGACY_CLK_NORMALIZED_COORDS_TRUE 0x08 342 343 #define LEGACY_CLK_FILTER_NEAREST 0x00 344 #define LEGACY_CLK_FILTER_LINEAR 0x10 345 346 // Mask values for the various components 347 #define LEGACY_SAMPLER_ADDRESS_MASK 0x07 348 #define LEGACY_SAMPLER_NORMALIZED_MASK 0x08 349 #define LEGACY_SAMPLER_FILTER_MASK 0x10 350 351 // These values need to match SPIR sampler enum 352 #define SPIR_CLK_ADDRESS_NONE 0x00 353 #define SPIR_CLK_ADDRESS_CLAMP_TO_EDGE 0x02 354 #define SPIR_CLK_ADDRESS_CLAMP 0x04 355 #define SPIR_CLK_ADDRESS_REPEAT 0x06 356 #define SPIR_CLK_ADDRESS_MIRRORED_REPEAT 0x08 357 #define SPIR_CLK_ADDRESS_MIRRORED_REPEAT_101_INTEL 0x0A 358 359 #define SPIR_CLK_NORMALIZED_COORDS_FALSE 0x00 360 #define SPIR_CLK_NORMALIZED_COORDS_TRUE 0x01 361 362 #define SPIR_CLK_FILTER_NEAREST 0x0010 363 #define SPIR_CLK_FILTER_LINEAR 0x0020 364 365 // Mask values for the various components 366 #define SPIR_SAMPLER_NORMALIZED_MASK 0x01 367 #define SPIR_SAMPLER_ADDRESS_MASK 0x0e 368 #define SPIR_SAMPLER_FILTER_MASK 0x30 369 370 } // namespace IGC 371