https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/218728
>From a61433a8d490ddc6d02291a40a887b7f30d37357 Mon Sep 17 00:00:00 2001 From: Deric Cheung <[email protected]> Date: Mon, 24 Aug 2026 16:00:32 -0700 Subject: [PATCH 1/5] rwtexture-load --- clang/lib/CodeGen/CGHLSLBuiltins.cpp | 37 +- clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 23 ++ clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h | 2 + clang/lib/Sema/HLSLExternalSemaSource.cpp | 2 +- clang/lib/Sema/SemaHLSL.cpp | 15 +- .../CodeGenHLSL/resources/Textures-Load.hlsl | 383 ++++++++++-------- .../Resources/Textures-Load-errors.hlsl | 56 ++- 7 files changed, 312 insertions(+), 206 deletions(-) diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp index 36f729a98539a..e1999ec36e382 100644 --- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp +++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp @@ -804,22 +804,31 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, case Builtin::BI__builtin_hlsl_resource_load_level: { Value *HandleOp = EmitScalarExpr(E->getArg(0)); Value *CoordLODOp = EmitScalarExpr(E->getArg(1)); - - auto *CoordLODVecTy = cast<llvm::FixedVectorType>(CoordLODOp->getType()); - unsigned NumElts = CoordLODVecTy->getNumElements(); - assert(NumElts >= 2 && "CoordLOD must have at least 2 elements"); - - // Split CoordLOD into Coord and LOD - SmallVector<int, 4> Mask; - for (unsigned I = 0; I < NumElts - 1; ++I) - Mask.push_back(I); - - Value *CoordOp = - Builder.CreateShuffleVector(CoordLODOp, Mask, "hlsl.load.coord"); - Value *LODOp = - Builder.CreateExtractElement(CoordLODOp, NumElts - 1, "hlsl.load.lod"); const HLSLAttributedResourceType *RT = getRequiredHandleType(E, 0); + Value *CoordOp = nullptr; + Value *LODOp = nullptr; + if (RT->getAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV) { + // A UAV descriptor binds a single mip slice, so a RWTexture location is + // all coordinate and there is no mip level to select. + CoordOp = CoordLODOp; + LODOp = llvm::ConstantInt::get(Int32Ty, 0); + } else { + auto *CoordLODVecTy = cast<llvm::FixedVectorType>(CoordLODOp->getType()); + unsigned NumElts = CoordLODVecTy->getNumElements(); + assert(NumElts >= 2 && "CoordLOD must have at least 2 elements"); + + // Split CoordLOD into Coord and LOD + SmallVector<int, 4> Mask; + for (unsigned I = 0; I < NumElts - 1; ++I) + Mask.push_back(I); + + CoordOp = + Builder.CreateShuffleVector(CoordLODOp, Mask, "hlsl.load.coord"); + LODOp = Builder.CreateExtractElement(CoordLODOp, NumElts - 1, + "hlsl.load.lod"); + } + SmallVector<Value *, 4> Args; Args.push_back(HandleOp); Args.push_back(CoordOp); diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp index 06b0a25102ada..34e883264b5b3 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp @@ -1630,6 +1630,29 @@ BuiltinTypeDeclBuilder::addTextureLoadMethods(ResourceDimension Dim, return *this; } +BuiltinTypeDeclBuilder & +BuiltinTypeDeclBuilder::addRWTextureLoadMethods(ResourceDimension Dim, + bool IsArray) { + assert(!Record->isCompleteDefinition() && "record is already complete"); + + ASTContext &AST = Record->getASTContext(); + // A UAV binds a single mip slice: no mip component, no offset overload. + uint32_t CoordSize = getResourceDimensions(Dim) + (IsArray ? 1 : 0); + QualType LocationTy = AST.getExtVectorType(AST.IntTy, CoordSize); + QualType ReturnType = getHandleElementType(); + + using PH = BuiltinTypeMethodBuilder::PlaceHolder; + + // T Load(int2 location) + BuiltinTypeMethodBuilder(*this, "Load", ReturnType) + .addParam("Location", LocationTy) + .callBuiltin("__builtin_hlsl_resource_load_level", ReturnType, PH::Handle, + PH::_0) + .finalize(); + + return *this; +} + BuiltinTypeDeclBuilder & BuiltinTypeDeclBuilder::addTextureLoadMSMethods(ResourceDimension Dim, bool IsArray) { diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h index c9bc92b7d0f15..62dea7fab8064 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h @@ -112,6 +112,8 @@ class BuiltinTypeDeclBuilder { bool IsArray = false); BuiltinTypeDeclBuilder &addTextureLoadMSMethods(ResourceDimension Dim, bool IsArray = false); + BuiltinTypeDeclBuilder &addRWTextureLoadMethods(ResourceDimension Dim, + bool IsArray = false); BuiltinTypeDeclBuilder &addByteAddressBufferLoadMethods(); BuiltinTypeDeclBuilder &addByteAddressBufferStoreMethods(); BuiltinTypeDeclBuilder &addByteAddressBufferInterlockedMethods(); diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index 08e7367766fcb..768155e30f558 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -287,7 +287,7 @@ static BuiltinTypeDeclBuilder setupRWTextureType(CXXRecordDecl *Decl, Sema &S, ResourceDimension Dim) { return BuiltinTypeDeclBuilder(S, Decl) .addTextureHandle(ResourceClass::UAV, /*IsROV=*/false, IsArray, Dim) - .addTextureLoadMethods(Dim, IsArray) + .addRWTextureLoadMethods(Dim, IsArray) .addArraySubscriptOperators(Dim, IsArray) .addGetDimensionsMethods(Dim) .addDefaultHandleConstructor() diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index e08ab96a13773..06828b9ec7fc0 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -4027,12 +4027,23 @@ static bool CheckLoadLevelBuiltin(Sema &S, CallExpr *TheCall) { auto *ResourceTy = TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>(); - // Check the location + lod (int3 for Texture2D, int4 for Texture2DArray). + // A UAV descriptor binds a single mip slice, so a RWTexture location has no + // mip component to select, and TextureLoad on a UAV takes no offset. + bool IsUAV = + ResourceTy->getAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV; + if (IsUAV && S.checkArgCount(TheCall, 2)) + return true; + + // Check the location: int3 for Texture2D and int4 for Texture2DArray, which + // both carry a trailing mip level; int2 and int3 for the RWTexture forms, + // which do not. unsigned ResourceDim = getResourceDimensions(ResourceTy->getAttrs().ResourceDimension); unsigned LocationDim = ResourceDim + (ResourceTy->getAttrs().IsArray ? 1 : 0); + if (!IsUAV) + ++LocationDim; QualType CoordLODTy = TheCall->getArg(1)->getType(); - if (CheckVectorElementCount(&S, CoordLODTy, S.Context.IntTy, LocationDim + 1, + if (CheckVectorElementCount(&S, CoordLODTy, S.Context.IntTy, LocationDim, TheCall->getArg(1)->getBeginLoc())) return true; diff --git a/clang/test/CodeGenHLSL/resources/Textures-Load.hlsl b/clang/test/CodeGenHLSL/resources/Textures-Load.hlsl index fb643ee0533ee..bf53f2ed7370a 100644 --- a/clang/test/CodeGenHLSL/resources/Textures-Load.hlsl +++ b/clang/test/CodeGenHLSL/resources/Textures-Load.hlsl @@ -1,95 +1,93 @@ // Texture2D // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm \ // RUN: -disable-llvm-passes -finclude-default-header -DENTRY_TYPE=int2 \ -// RUN: -DOFFSET_ARG="int2(1, 1)" -DTEXTURE=Texture2D -DLOAD_TYPE=int3 \ -// RUN: -DZEROS=0 -o - %s \ +// RUN: -DHAS_OFFSET -DOFFSET_ARG="int2(1, 1)" -DTEXTURE=Texture2D \ +// RUN: -DLOAD_ARG="int3(loc, 0)" -o - %s \ // RUN: | llvm-cxxfilt \ -// RUN: | FileCheck %s --check-prefixes=CHECK,DXIL -DTEXTURE=Texture2D \ -// RUN: -DLOAD_DIM=3 -DCOORD_DIM=2 -DCOORD_MASK="<i32 0, i32 1>" -DDXIL_TY=2 \ -// RUN: -DRW=0 -DENTRY_DIM=2 -DDIM=2 +// RUN: | FileCheck %s --check-prefixes=CHECK,SRV,WIDE-LOC,DXIL,DXIL-SRV \ +// RUN: -DTEXTURE=Texture2D -D#LOAD_DIM=3 -DCOORD_DIM=2 \ +// RUN: -DCOORD_MASK="<i32 0, i32 1>" -DDXIL_TY=2 -DRW=0 -DENTRY_DIM=2 -DDIM=2 // RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm \ // RUN: -disable-llvm-passes -finclude-default-header -DENTRY_TYPE=int2 \ -// RUN: -DOFFSET_ARG="int2(1, 1)" -DTEXTURE=Texture2D -DLOAD_TYPE=int3 \ -// RUN: -DZEROS=0 -o - %s \ +// RUN: -DHAS_OFFSET -DOFFSET_ARG="int2(1, 1)" -DTEXTURE=Texture2D \ +// RUN: -DLOAD_ARG="int3(loc, 0)" -o - %s \ // RUN: | llvm-cxxfilt \ -// RUN: | FileCheck %s --check-prefixes=CHECK,SPIRV -DTEXTURE=Texture2D \ -// RUN: -DLOAD_DIM=3 -DCOORD_DIM=2 -DCOORD_MASK="<i32 0, i32 1>" -DARRAYED=0 \ -// RUN: -DSAMPLED=1 -DFORMAT1=0 -DFORMAT3=0 -DFORMAT6=0 -DFORMAT21=0 \ -// RUN: -DFORMAT24=0 -DFORMAT25=0 -DSPV_DIM=1 -DENTRY_DIM=2 -DDIM=2 +// RUN: | FileCheck %s --check-prefixes=CHECK,SRV,WIDE-LOC,SPIRV,SPIRV-SRV \ +// RUN: -DTEXTURE=Texture2D -D#LOAD_DIM=3 -DCOORD_DIM=2 \ +// RUN: -DCOORD_MASK="<i32 0, i32 1>" -DARRAYED=0 -DSAMPLED=1 -DFORMAT1=0 \ +// RUN: -DFORMAT3=0 -DFORMAT6=0 -DFORMAT21=0 -DFORMAT24=0 -DFORMAT25=0 \ +// RUN: -DSPV_DIM=1 -DENTRY_DIM=2 -DDIM=2 // Texture2DArray // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm \ // RUN: -disable-llvm-passes -finclude-default-header -DENTRY_TYPE=int2 \ -// RUN: -DOFFSET_ARG="int2(1, 1)" -DTEXTURE=Texture2DArray -DLOAD_TYPE=int4 \ -// RUN: -DZEROS=" 0, 0" -o - %s \ +// RUN: -DHAS_OFFSET -DOFFSET_ARG="int2(1, 1)" -DTEXTURE=Texture2DArray \ +// RUN: -DLOAD_ARG="int4(loc, 0, 0)" -o - %s \ // RUN: | llvm-cxxfilt \ -// RUN: | FileCheck %s --check-prefixes=CHECK,DXIL -DTEXTURE=Texture2DArray \ -// RUN: -DLOAD_DIM=4 -DCOORD_DIM=3 -DCOORD_MASK="<i32 0, i32 1, i32 2>" \ -// RUN: -DDXIL_TY=7 -DRW=0 -DENTRY_DIM=2 -DDIM=2 +// RUN: | FileCheck %s --check-prefixes=CHECK,SRV,WIDE-LOC,DXIL,DXIL-SRV \ +// RUN: -DTEXTURE=Texture2DArray -D#LOAD_DIM=4 -DCOORD_DIM=3 \ +// RUN: -DCOORD_MASK="<i32 0, i32 1, i32 2>" -DDXIL_TY=7 -DRW=0 -DENTRY_DIM=2 \ +// RUN: -DDIM=2 // RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm \ // RUN: -disable-llvm-passes -finclude-default-header -DENTRY_TYPE=int2 \ -// RUN: -DOFFSET_ARG="int2(1, 1)" -DTEXTURE=Texture2DArray -DLOAD_TYPE=int4 \ -// RUN: -DZEROS=" 0, 0" -o - %s \ +// RUN: -DHAS_OFFSET -DOFFSET_ARG="int2(1, 1)" -DTEXTURE=Texture2DArray \ +// RUN: -DLOAD_ARG="int4(loc, 0, 0)" -o - %s \ // RUN: | llvm-cxxfilt \ -// RUN: | FileCheck %s --check-prefixes=CHECK,SPIRV -DTEXTURE=Texture2DArray \ -// RUN: -DLOAD_DIM=4 -DCOORD_DIM=3 -DCOORD_MASK="<i32 0, i32 1, i32 2>" \ -// RUN: -DARRAYED=1 -DSAMPLED=1 -DFORMAT1=0 -DFORMAT3=0 -DFORMAT6=0 \ -// RUN: -DFORMAT21=0 -DFORMAT24=0 -DFORMAT25=0 -DSPV_DIM=1 -DENTRY_DIM=2 \ -// RUN: -DDIM=2 +// RUN: | FileCheck %s --check-prefixes=CHECK,SRV,WIDE-LOC,SPIRV,SPIRV-SRV \ +// RUN: -DTEXTURE=Texture2DArray -D#LOAD_DIM=4 -DCOORD_DIM=3 \ +// RUN: -DCOORD_MASK="<i32 0, i32 1, i32 2>" -DARRAYED=1 -DSAMPLED=1 \ +// RUN: -DFORMAT1=0 -DFORMAT3=0 -DFORMAT6=0 -DFORMAT21=0 -DFORMAT24=0 \ +// RUN: -DFORMAT25=0 -DSPV_DIM=1 -DENTRY_DIM=2 -DDIM=2 -// RWTexture2D +// RWTexture2D. // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm \ // RUN: -disable-llvm-passes -finclude-default-header -DENTRY_TYPE=int2 \ -// RUN: -DOFFSET_ARG="int2(1, 1)" -DTEXTURE=RWTexture2D -DLOAD_TYPE=int3 \ -// RUN: -DZEROS=0 -o - %s \ +// RUN: -DTEXTURE=RWTexture2D -DLOAD_ARG="loc" -o - %s \ // RUN: | llvm-cxxfilt \ -// RUN: | FileCheck %s --check-prefixes=CHECK,DXIL -DTEXTURE=RWTexture2D \ -// RUN: -DLOAD_DIM=3 -DCOORD_DIM=2 -DCOORD_MASK="<i32 0, i32 1>" -DDXIL_TY=2 \ -// RUN: -DRW=1 -DENTRY_DIM=2 -DDIM=2 +// RUN: | FileCheck %s --check-prefixes=CHECK,UAV,EXACT-LOC,DXIL,DXIL-UAV \ +// RUN: -DTEXTURE=RWTexture2D -D#LOAD_DIM=2 -DCOORD_DIM=2 -DDXIL_TY=2 -DRW=1 \ +// RUN: -DENTRY_DIM=2 -DDIM=2 // RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm \ // RUN: -disable-llvm-passes -finclude-default-header -DENTRY_TYPE=int2 \ -// RUN: -DOFFSET_ARG="int2(1, 1)" -DTEXTURE=RWTexture2D -DLOAD_TYPE=int3 \ -// RUN: -DZEROS=0 -o - %s \ +// RUN: -DTEXTURE=RWTexture2D -DLOAD_ARG="loc" -o - %s \ // RUN: | llvm-cxxfilt \ -// RUN: | FileCheck %s --check-prefixes=CHECK,SPIRV -DTEXTURE=RWTexture2D \ -// RUN: -DLOAD_DIM=3 -DCOORD_DIM=2 -DCOORD_MASK="<i32 0, i32 1>" -DARRAYED=0 \ +// RUN: | FileCheck %s --check-prefixes=CHECK,UAV,EXACT-LOC,SPIRV,SPIRV-UAV \ +// RUN: -DTEXTURE=RWTexture2D -D#LOAD_DIM=2 -DCOORD_DIM=2 -DARRAYED=0 \ // RUN: -DSAMPLED=2 -DFORMAT1=1 -DFORMAT3=3 -DFORMAT6=6 -DFORMAT21=21 \ // RUN: -DFORMAT24=24 -DFORMAT25=25 -DSPV_DIM=1 -DENTRY_DIM=2 -DDIM=2 -// RWTexture2DArray +// RWTexture2DArray. // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm \ // RUN: -disable-llvm-passes -finclude-default-header -DENTRY_TYPE=int2 \ -// RUN: -DOFFSET_ARG="int2(1, 1)" -DTEXTURE=RWTexture2DArray \ -// RUN: -DLOAD_TYPE=int4 -DZEROS=" 0, 0" -o - %s \ +// RUN: -DTEXTURE=RWTexture2DArray -DLOAD_ARG="int3(loc, 0)" -o - %s \ // RUN: | llvm-cxxfilt \ -// RUN: | FileCheck %s --check-prefixes=CHECK,DXIL \ -// RUN: -DTEXTURE=RWTexture2DArray -DLOAD_DIM=4 -DCOORD_DIM=3 \ -// RUN: -DCOORD_MASK="<i32 0, i32 1, i32 2>" -DDXIL_TY=7 -DRW=1 \ -// RUN: -DENTRY_DIM=2 -DDIM=2 +// RUN: | FileCheck %s --check-prefixes=CHECK,UAV,WIDE-LOC,DXIL,DXIL-UAV \ +// RUN: -DTEXTURE=RWTexture2DArray -D#LOAD_DIM=3 -DCOORD_DIM=3 \ +// RUN: -DDXIL_TY=7 -DRW=1 -DENTRY_DIM=2 -DDIM=2 // RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm \ // RUN: -disable-llvm-passes -finclude-default-header -DENTRY_TYPE=int2 \ -// RUN: -DOFFSET_ARG="int2(1, 1)" -DTEXTURE=RWTexture2DArray \ -// RUN: -DLOAD_TYPE=int4 -DZEROS=" 0, 0" -o - %s \ +// RUN: -DTEXTURE=RWTexture2DArray -DLOAD_ARG="int3(loc, 0)" -o - %s \ // RUN: | llvm-cxxfilt \ -// RUN: | FileCheck %s --check-prefixes=CHECK,SPIRV \ -// RUN: -DTEXTURE=RWTexture2DArray -DLOAD_DIM=4 -DCOORD_DIM=3 \ -// RUN: -DCOORD_MASK="<i32 0, i32 1, i32 2>" -DARRAYED=1 -DSAMPLED=2 \ -// RUN: -DFORMAT1=1 -DFORMAT3=3 -DFORMAT6=6 -DFORMAT21=21 -DFORMAT24=24 \ -// RUN: -DFORMAT25=25 -DSPV_DIM=1 -DENTRY_DIM=2 -DDIM=2 +// RUN: | FileCheck %s --check-prefixes=CHECK,UAV,WIDE-LOC,SPIRV,SPIRV-UAV \ +// RUN: -DTEXTURE=RWTexture2DArray -D#LOAD_DIM=3 -DCOORD_DIM=3 \ +// RUN: -DARRAYED=1 -DSAMPLED=2 -DFORMAT1=1 -DFORMAT3=3 -DFORMAT6=6 \ +// RUN: -DFORMAT21=21 -DFORMAT24=24 -DFORMAT25=25 -DSPV_DIM=1 -DENTRY_DIM=2 \ +// RUN: -DDIM=2 // Parameterized over the texture types in the RUN lines above; adding a texture // of another dimension only requires new RUN lines. // // ENTRY_TYPE the entry point's own coordinate type +// HAS_OFFSET defined for read-only (SRV) textures, which have a +// second Load overload taking an offset // OFFSET_ARG a literal offset argument // TEXTURE resource type name -// LOAD_TYPE Load location type -// ZEROS the trailing components padding ENTRY_TYPE out to -// LOAD_TYPE -// LOAD_DIM Load location components (COORD_DIM plus the mip level) +// LOAD_ARG the Load location, built from the entry point's `loc` +// LOAD_DIM Load location components; a FileCheck numeric variable, +// so the last component's index is [[#LOAD_DIM-1]] // COORD_DIM sample location components (DIM plus the array slice) // COORD_MASK shufflevector mask extracting the coordinate from a -// location +// location; only needed where LOAD_DIM > COORD_DIM // DXIL_TY dx.Texture resource-kind operand // RW dx.Texture UAV operand // ENTRY_DIM the entry point's own coordinate components @@ -100,59 +98,78 @@ // SPV_DIM spirv.Image Dim operand // FORMAT<n> spirv.Image Image Format operand for the element // type of the texture declared on line <n> +// +// Check prefixes: +// SRV read-only textures. Their location carries a trailing +// mip level, which is split back out of the location, and +// they have the offset overload. +// UAV writable textures. A UAV descriptor binds a single mip +// slice, so the location is all coordinate and the level +// operand is a placeholder that the backends discard. +// WIDE-LOC types whose Load location is wider than the entry +// point's coordinate, so LOAD_ARG appends the array slice +// and/or the mip level to `loc` +// EXACT-LOC types whose Load location is exactly `loc` TEXTURE<float4> t; // CHECK: define hidden {{.*}} <4 x float> @test_load(int vector[[[ENTRY_DIM]]]) -// CHECK: %[[COORD:.*]] = insertelement <[[LOAD_DIM]] x i32> {{.*}}, i32 0, i32 [[COORD_DIM]] -// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::[[TEXTURE]]<float vector[4]>::Load(int vector[[[LOAD_DIM]]])(ptr {{.*}} @t, <[[LOAD_DIM]] x i32> noundef %[[COORD]]) +// WIDE-LOC: %[[COORD:.*]] = insertelement <[[#LOAD_DIM]] x i32> {{.*}}, i32 0, i32 [[#LOAD_DIM-1]] +// WIDE-LOC: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::[[TEXTURE]]<float vector[4]>::Load(int vector[[[#LOAD_DIM]]])(ptr {{.*}} @t, <[[#LOAD_DIM]] x i32> noundef %[[COORD]]) +// EXACT-LOC: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::[[TEXTURE]]<float vector[4]>::Load(int vector[[[#LOAD_DIM]]])(ptr {{.*}} @t, <[[#LOAD_DIM]] x i32> noundef %{{.*}}) // CHECK: ret <4 x float> %[[CALL]] float4 test_load(ENTRY_TYPE loc : LOC) : SV_Target { - return t.Load(LOAD_TYPE(loc, ZEROS)); + return t.Load(LOAD_ARG); } -// CHECK: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::[[TEXTURE]]<float vector[4]>::Load(int vector[[[LOAD_DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]]) +// CHECK: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::[[TEXTURE]]<float vector[4]>::Load(int vector[[[#LOAD_DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[#LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]]) // CHECK: %[[THIS_ADDR:.*]] = alloca ptr -// CHECK: %[[LOAD_ADDR:.*]] = alloca <[[LOAD_DIM]] x i32> +// CHECK: %[[LOAD_ADDR:.*]] = alloca <[[#LOAD_DIM]] x i32> // CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]] -// CHECK: store <[[LOAD_DIM]] x i32> %[[LOAD]], ptr %[[LOAD_ADDR]] +// CHECK: store <[[#LOAD_DIM]] x i32> %[[LOAD]], ptr %[[LOAD_ADDR]] // CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS_ADDR]] // CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::[[TEXTURE]]", ptr %[[THIS_VAL]], i32 0, i32 0 // CHECK: %[[HANDLE:.*]] = load target("{{(dx.Texture|spirv.Image)}}", {{.*}}), ptr %[[HANDLE_GEP]] -// CHECK: %[[LOAD_VAL:.*]] = load <[[LOAD_DIM]] x i32>, ptr %[[LOAD_ADDR]] -// CHECK: %[[COORD:.*]] = shufflevector <[[LOAD_DIM]] x i32> %[[LOAD_VAL]], <[[LOAD_DIM]] x i32> poison, <[[COORD_DIM]] x i32> [[COORD_MASK]] -// CHECK: %[[LOD:.*]] = extractelement <[[LOAD_DIM]] x i32> %[[LOAD_VAL]], i64 [[COORD_DIM]] -// DXIL: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_{{.*}}(target("dx.Texture", <4 x float>, [[RW]], 0, 0, [[DXIL_TY]]) %[[HANDLE]], <[[COORD_DIM]] x i32> %[[COORD]], i32 %[[LOD]], <[[DIM]] x i32> zeroinitializer) -// SPIRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.spv.resource.load.level.v4f32.tspirv.Image_f32_{{.*}}(target("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT1]]) %[[HANDLE]], <[[COORD_DIM]] x i32> %[[COORD]], i32 %[[LOD]], <[[DIM]] x i32> zeroinitializer) +// CHECK: %[[LOAD_VAL:.*]] = load <[[#LOAD_DIM]] x i32>, ptr %[[LOAD_ADDR]] +// UAV-NOT: shufflevector +// UAV-NOT: extractelement +// SRV: %[[COORD:.*]] = shufflevector <[[#LOAD_DIM]] x i32> %[[LOAD_VAL]], <[[#LOAD_DIM]] x i32> poison, <[[COORD_DIM]] x i32> [[COORD_MASK]] +// SRV: %[[LOD:.*]] = extractelement <[[#LOAD_DIM]] x i32> %[[LOAD_VAL]], i64 [[COORD_DIM]] +// DXIL-SRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_{{.*}}(target("dx.Texture", <4 x float>, [[RW]], 0, 0, [[DXIL_TY]]) %[[HANDLE]], <[[COORD_DIM]] x i32> %[[COORD]], i32 %[[LOD]], <[[DIM]] x i32> zeroinitializer) +// DXIL-UAV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_{{.*}}(target("dx.Texture", <4 x float>, [[RW]], 0, 0, [[DXIL_TY]]) %[[HANDLE]], <[[COORD_DIM]] x i32> %[[LOAD_VAL]], i32 0, <[[DIM]] x i32> zeroinitializer) +// SPIRV-SRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.spv.resource.load.level.v4f32.tspirv.Image_f32_{{.*}}(target("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT1]]) %[[HANDLE]], <[[COORD_DIM]] x i32> %[[COORD]], i32 %[[LOD]], <[[DIM]] x i32> zeroinitializer) +// SPIRV-UAV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.spv.resource.load.level.v4f32.tspirv.Image_f32_{{.*}}(target("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT1]]) %[[HANDLE]], <[[COORD_DIM]] x i32> %[[LOAD_VAL]], i32 0, <[[DIM]] x i32> zeroinitializer) // CHECK: ret <4 x float> %[[RES]] -// CHECK: define hidden {{.*}} <4 x float> @test_load_offset(int vector[[[ENTRY_DIM]]]) -// CHECK: %[[COORD:.*]] = insertelement <[[LOAD_DIM]] x i32> {{.*}}, i32 0, i32 [[COORD_DIM]] -// CHECK: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::[[TEXTURE]]<float vector[4]>::Load(int vector[[[LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} @t, <[[LOAD_DIM]] x i32> noundef %[[COORD]], <[[DIM]] x i32> noundef splat (i32 1)) -// CHECK: ret <4 x float> %[[CALL]] +// SRV: define hidden {{.*}} <4 x float> @test_load_offset(int vector[[[ENTRY_DIM]]]) +// SRV: %[[COORD:.*]] = insertelement <[[#LOAD_DIM]] x i32> {{.*}}, i32 0, i32 [[#LOAD_DIM-1]] +// SRV: %[[CALL:.*]] = call {{.*}} <4 x float> @hlsl::[[TEXTURE]]<float vector[4]>::Load(int vector[[[#LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} @t, <[[#LOAD_DIM]] x i32> noundef %[[COORD]], <[[DIM]] x i32> noundef splat (i32 1)) +// SRV: ret <4 x float> %[[CALL]] +#ifdef HAS_OFFSET float4 test_load_offset(ENTRY_TYPE loc : LOC) : SV_Target { - return t.Load(LOAD_TYPE(loc, ZEROS), OFFSET_ARG); + return t.Load(LOAD_ARG, OFFSET_ARG); } - -// CHECK: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::[[TEXTURE]]<float vector[4]>::Load(int vector[[[LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]], <[[DIM]] x i32> {{.*}} %[[OFFSET:.*]]) -// CHECK: %[[THIS_ADDR:.*]] = alloca ptr -// CHECK: %[[LOAD_ADDR:.*]] = alloca <[[LOAD_DIM]] x i32> -// CHECK: %[[OFFSET_ADDR:.*]] = alloca <[[DIM]] x i32> -// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]] -// CHECK: store <[[LOAD_DIM]] x i32> %[[LOAD]], ptr %[[LOAD_ADDR]] -// CHECK: store <[[DIM]] x i32> %[[OFFSET]], ptr %[[OFFSET_ADDR]] -// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS_ADDR]] -// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::[[TEXTURE]]", ptr %[[THIS_VAL]], i32 0, i32 0 -// CHECK: %[[HANDLE:.*]] = load target("{{(dx.Texture|spirv.Image)}}", {{.*}}), ptr %[[HANDLE_GEP]] -// CHECK: %[[LOAD_VAL:.*]] = load <[[LOAD_DIM]] x i32>, ptr %[[LOAD_ADDR]] -// CHECK: %[[COORD:.*]] = shufflevector <[[LOAD_DIM]] x i32> %[[LOAD_VAL]], <[[LOAD_DIM]] x i32> poison, <[[COORD_DIM]] x i32> [[COORD_MASK]] -// CHECK: %[[LOD:.*]] = extractelement <[[LOAD_DIM]] x i32> %[[LOAD_VAL]], i64 [[COORD_DIM]] -// CHECK: %[[OFFSET_VAL:.*]] = load <[[DIM]] x i32>, ptr %[[OFFSET_ADDR]] -// DXIL: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_{{.*}}("dx.Texture", <4 x float>, [[RW]], 0, 0, [[DXIL_TY]]) %[[HANDLE]], <[[COORD_DIM]] x i32> %[[COORD]], i32 %[[LOD]], <[[DIM]] x i32> %[[OFFSET_VAL]]) -// SPIRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.spv.resource.load.level.v4f32.tspirv.Image_f32_{{.*}}("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT1]]) %[[HANDLE]], <[[COORD_DIM]] x i32> %[[COORD]], i32 %[[LOD]], <[[DIM]] x i32> %[[OFFSET_VAL]]) -// CHECK: ret <4 x float> %[[RES]] +#endif + +// SRV: define linkonce_odr hidden {{.*}} <4 x float> @hlsl::[[TEXTURE]]<float vector[4]>::Load(int vector[[[#LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[#LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]], <[[DIM]] x i32> {{.*}} %[[OFFSET:.*]]) +// SRV: %[[THIS_ADDR:.*]] = alloca ptr +// SRV: %[[LOAD_ADDR:.*]] = alloca <[[#LOAD_DIM]] x i32> +// SRV: %[[OFFSET_ADDR:.*]] = alloca <[[DIM]] x i32> +// SRV: store ptr %[[THIS]], ptr %[[THIS_ADDR]] +// SRV: store <[[#LOAD_DIM]] x i32> %[[LOAD]], ptr %[[LOAD_ADDR]] +// SRV: store <[[DIM]] x i32> %[[OFFSET]], ptr %[[OFFSET_ADDR]] +// SRV: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS_ADDR]] +// SRV: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::[[TEXTURE]]", ptr %[[THIS_VAL]], i32 0, i32 0 +// SRV: %[[HANDLE:.*]] = load target("{{(dx.Texture|spirv.Image)}}", {{.*}}), ptr %[[HANDLE_GEP]] +// SRV: %[[LOAD_VAL:.*]] = load <[[#LOAD_DIM]] x i32>, ptr %[[LOAD_ADDR]] +// SRV: %[[COORD:.*]] = shufflevector <[[#LOAD_DIM]] x i32> %[[LOAD_VAL]], <[[#LOAD_DIM]] x i32> poison, <[[COORD_DIM]] x i32> [[COORD_MASK]] +// SRV: %[[LOD:.*]] = extractelement <[[#LOAD_DIM]] x i32> %[[LOAD_VAL]], i64 [[COORD_DIM]] +// SRV: %[[OFFSET_VAL:.*]] = load <[[DIM]] x i32>, ptr %[[OFFSET_ADDR]] +// DXIL-SRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_{{.*}}("dx.Texture", <4 x float>, [[RW]], 0, 0, [[DXIL_TY]]) %[[HANDLE]], <[[COORD_DIM]] x i32> %[[COORD]], i32 %[[LOD]], <[[DIM]] x i32> %[[OFFSET_VAL]]) +// SPIRV-SRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.spv.resource.load.level.v4f32.tspirv.Image_f32_{{.*}}("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT1]]) %[[HANDLE]], <[[COORD_DIM]] x i32> %[[COORD]], i32 %[[LOD]], <[[DIM]] x i32> %[[OFFSET_VAL]]) +// SRV: ret <4 x float> %[[RES]] // For the rest of the types, we just check that the call to the member @@ -161,178 +178,192 @@ float4 test_load_offset(ENTRY_TYPE loc : LOC) : SV_Target { TEXTURE<float> t_float; // CHECK: define hidden {{.*}} float @test_load_float(int vector[[[ENTRY_DIM]]]) -// CHECK: define linkonce_odr hidden {{.*}} float @hlsl::[[TEXTURE]]<float>::Load(int vector[[[LOAD_DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]]) -// DXIL: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.dx.resource.load.level.f32.tdx.Texture_f32_{{.*}}("dx.Texture", float, [[RW]], 0, 0, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> zeroinitializer) -// SPIRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.spv.resource.load.level.f32.tspirv.Image_f32_{{.*}}("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT3]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> zeroinitializer) +// CHECK: define linkonce_odr hidden {{.*}} float @hlsl::[[TEXTURE]]<float>::Load(int vector[[[#LOAD_DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[#LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]]) +// DXIL: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.dx.resource.load.level.f32.tdx.Texture_f32_{{.*}}("dx.Texture", float, [[RW]], 0, 0, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 {{[^,]*}}, <[[DIM]] x i32> zeroinitializer) +// SPIRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.spv.resource.load.level.f32.tspirv.Image_f32_{{.*}}("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT3]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 {{[^,]*}}, <[[DIM]] x i32> zeroinitializer) // CHECK: ret float %[[RES]] float test_load_float(ENTRY_TYPE loc : LOC) { - return t_float.Load(LOAD_TYPE(loc, ZEROS)); + return t_float.Load(LOAD_ARG); } -// CHECK: define hidden {{.*}} float @test_load_offset_float(int vector[[[ENTRY_DIM]]]) -// CHECK: %[[CALL:.*]] = call {{.*}} float @hlsl::[[TEXTURE]]<float>::Load(int vector[[[LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} @t_float, <[[LOAD_DIM]] x i32> noundef %{{.*}}, <[[DIM]] x i32> noundef splat (i32 1)) -// CHECK: ret float %[[CALL]] +#ifdef HAS_OFFSET +// SRV: define hidden {{.*}} float @test_load_offset_float(int vector[[[ENTRY_DIM]]]) +// SRV: %[[CALL:.*]] = call {{.*}} float @hlsl::[[TEXTURE]]<float>::Load(int vector[[[#LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} @t_float, <[[#LOAD_DIM]] x i32> noundef %{{.*}}, <[[DIM]] x i32> noundef splat (i32 1)) +// SRV: ret float %[[CALL]] float test_load_offset_float(ENTRY_TYPE loc : LOC) { - return t_float.Load(LOAD_TYPE(loc, ZEROS), OFFSET_ARG); + return t_float.Load(LOAD_ARG, OFFSET_ARG); } +#endif -// CHECK: define linkonce_odr hidden {{.*}} float @hlsl::[[TEXTURE]]<float>::Load(int vector[[[LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]], <[[DIM]] x i32> {{.*}} %[[OFFSET:.*]]) -// DXIL: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.dx.resource.load.level.f32.tdx.Texture_f32_{{.*}}("dx.Texture", float, [[RW]], 0, 0, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) -// SPIRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.spv.resource.load.level.f32.tspirv.Image_f32_{{.*}}("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT3]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) -// CHECK: ret float %[[RES]] +// SRV: define linkonce_odr hidden {{.*}} float @hlsl::[[TEXTURE]]<float>::Load(int vector[[[#LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[#LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]], <[[DIM]] x i32> {{.*}} %[[OFFSET:.*]]) +// DXIL-SRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.dx.resource.load.level.f32.tdx.Texture_f32_{{.*}}("dx.Texture", float, [[RW]], 0, 0, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) +// SPIRV-SRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.spv.resource.load.level.f32.tspirv.Image_f32_{{.*}}("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT3]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) +// SRV: ret float %[[RES]] TEXTURE<float2> t_float2; // CHECK: define hidden {{.*}} <2 x float> @test_load_float2(int vector[[[ENTRY_DIM]]]) -// CHECK: %[[CALL:.*]] = call {{.*}} <2 x float> @hlsl::[[TEXTURE]]<float vector[2]>::Load(int vector[[[LOAD_DIM]]])(ptr {{.*}} @t_float2, <[[LOAD_DIM]] x i32> noundef %{{.*}}) +// CHECK: %[[CALL:.*]] = call {{.*}} <2 x float> @hlsl::[[TEXTURE]]<float vector[2]>::Load(int vector[[[#LOAD_DIM]]])(ptr {{.*}} @t_float2, <[[#LOAD_DIM]] x i32> noundef %{{.*}}) // CHECK: ret <2 x float> %[[CALL]] float2 test_load_float2(ENTRY_TYPE loc : LOC) { - return t_float2.Load(LOAD_TYPE(loc, ZEROS)); + return t_float2.Load(LOAD_ARG); } -// CHECK: define linkonce_odr hidden {{.*}} <2 x float> @hlsl::[[TEXTURE]]<float vector[2]>::Load(int vector[[[LOAD_DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]]) -// DXIL: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.dx.resource.load.level.v2f32.tdx.Texture_v2f32_{{.*}}("dx.Texture", <2 x float>, [[RW]], 0, 0, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> zeroinitializer) -// SPIRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.spv.resource.load.level.v2f32.tspirv.Image_f32_{{.*}}("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT6]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> zeroinitializer) +// CHECK: define linkonce_odr hidden {{.*}} <2 x float> @hlsl::[[TEXTURE]]<float vector[2]>::Load(int vector[[[#LOAD_DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[#LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]]) +// DXIL: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.dx.resource.load.level.v2f32.tdx.Texture_v2f32_{{.*}}("dx.Texture", <2 x float>, [[RW]], 0, 0, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 {{[^,]*}}, <[[DIM]] x i32> zeroinitializer) +// SPIRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.spv.resource.load.level.v2f32.tspirv.Image_f32_{{.*}}("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT6]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 {{[^,]*}}, <[[DIM]] x i32> zeroinitializer) // CHECK: ret <2 x float> %[[RES]] -// CHECK: define hidden {{.*}} <2 x float> @test_load_offset_float2(int vector[[[ENTRY_DIM]]]) -// CHECK: %[[CALL:.*]] = call {{.*}} <2 x float> @hlsl::[[TEXTURE]]<float vector[2]>::Load(int vector[[[LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} @t_float2, <[[LOAD_DIM]] x i32> noundef %{{.*}}, <[[DIM]] x i32> noundef splat (i32 1)) -// CHECK: ret <2 x float> %[[CALL]] +#ifdef HAS_OFFSET +// SRV: define hidden {{.*}} <2 x float> @test_load_offset_float2(int vector[[[ENTRY_DIM]]]) +// SRV: %[[CALL:.*]] = call {{.*}} <2 x float> @hlsl::[[TEXTURE]]<float vector[2]>::Load(int vector[[[#LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} @t_float2, <[[#LOAD_DIM]] x i32> noundef %{{.*}}, <[[DIM]] x i32> noundef splat (i32 1)) +// SRV: ret <2 x float> %[[CALL]] float2 test_load_offset_float2(ENTRY_TYPE loc : LOC) { - return t_float2.Load(LOAD_TYPE(loc, ZEROS), OFFSET_ARG); + return t_float2.Load(LOAD_ARG, OFFSET_ARG); } +#endif -// CHECK: define linkonce_odr hidden {{.*}} <2 x float> @hlsl::[[TEXTURE]]<float vector[2]>::Load(int vector[[[LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]], <[[DIM]] x i32> {{.*}} %[[OFFSET:.*]]) -// DXIL: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.dx.resource.load.level.v2f32.tdx.Texture_v2f32_{{.*}}("dx.Texture", <2 x float>, [[RW]], 0, 0, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) -// SPIRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.spv.resource.load.level.v2f32.tspirv.Image_f32_{{.*}}("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT6]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) -// CHECK: ret <2 x float> %[[RES]] +// SRV: define linkonce_odr hidden {{.*}} <2 x float> @hlsl::[[TEXTURE]]<float vector[2]>::Load(int vector[[[#LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[#LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]], <[[DIM]] x i32> {{.*}} %[[OFFSET:.*]]) +// DXIL-SRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.dx.resource.load.level.v2f32.tdx.Texture_v2f32_{{.*}}("dx.Texture", <2 x float>, [[RW]], 0, 0, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) +// SPIRV-SRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.spv.resource.load.level.v2f32.tspirv.Image_f32_{{.*}}("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT6]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) +// SRV: ret <2 x float> %[[RES]] TEXTURE<float3> t_float3; // CHECK: define hidden {{.*}} <3 x float> @test_load_float3(int vector[[[ENTRY_DIM]]]) -// CHECK: %[[CALL:.*]] = call {{.*}} <3 x float> @hlsl::[[TEXTURE]]<float vector[3]>::Load(int vector[[[LOAD_DIM]]])(ptr {{.*}} @t_float3, <[[LOAD_DIM]] x i32> noundef %{{.*}}) +// CHECK: %[[CALL:.*]] = call {{.*}} <3 x float> @hlsl::[[TEXTURE]]<float vector[3]>::Load(int vector[[[#LOAD_DIM]]])(ptr {{.*}} @t_float3, <[[#LOAD_DIM]] x i32> noundef %{{.*}}) // CHECK: ret <3 x float> %[[CALL]] float3 test_load_float3(ENTRY_TYPE loc : LOC) { - return t_float3.Load(LOAD_TYPE(loc, ZEROS)); + return t_float3.Load(LOAD_ARG); } -// CHECK: define linkonce_odr hidden {{.*}} <3 x float> @hlsl::[[TEXTURE]]<float vector[3]>::Load(int vector[[[LOAD_DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]]) -// DXIL: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.dx.resource.load.level.v3f32.tdx.Texture_v3f32_{{.*}}("dx.Texture", <3 x float>, [[RW]], 0, 0, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> zeroinitializer) -// SPIRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.spv.resource.load.level.v3f32.tspirv.Image_f32_{{.*}}("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], 0) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> zeroinitializer) +// CHECK: define linkonce_odr hidden {{.*}} <3 x float> @hlsl::[[TEXTURE]]<float vector[3]>::Load(int vector[[[#LOAD_DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[#LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]]) +// DXIL: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.dx.resource.load.level.v3f32.tdx.Texture_v3f32_{{.*}}("dx.Texture", <3 x float>, [[RW]], 0, 0, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 {{[^,]*}}, <[[DIM]] x i32> zeroinitializer) +// SPIRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.spv.resource.load.level.v3f32.tspirv.Image_f32_{{.*}}("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], 0) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 {{[^,]*}}, <[[DIM]] x i32> zeroinitializer) // CHECK: ret <3 x float> %[[RES]] -// CHECK: define hidden {{.*}} <3 x float> @test_load_offset_float3(int vector[[[ENTRY_DIM]]]) -// CHECK: %[[CALL:.*]] = call {{.*}} <3 x float> @hlsl::[[TEXTURE]]<float vector[3]>::Load(int vector[[[LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} @t_float3, <[[LOAD_DIM]] x i32> noundef %{{.*}}, <[[DIM]] x i32> noundef splat (i32 1)) -// CHECK: ret <3 x float> %[[CALL]] +#ifdef HAS_OFFSET +// SRV: define hidden {{.*}} <3 x float> @test_load_offset_float3(int vector[[[ENTRY_DIM]]]) +// SRV: %[[CALL:.*]] = call {{.*}} <3 x float> @hlsl::[[TEXTURE]]<float vector[3]>::Load(int vector[[[#LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} @t_float3, <[[#LOAD_DIM]] x i32> noundef %{{.*}}, <[[DIM]] x i32> noundef splat (i32 1)) +// SRV: ret <3 x float> %[[CALL]] float3 test_load_offset_float3(ENTRY_TYPE loc : LOC) { - return t_float3.Load(LOAD_TYPE(loc, ZEROS), OFFSET_ARG); + return t_float3.Load(LOAD_ARG, OFFSET_ARG); } +#endif -// CHECK: define linkonce_odr hidden {{.*}} <3 x float> @hlsl::[[TEXTURE]]<float vector[3]>::Load(int vector[[[LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]], <[[DIM]] x i32> {{.*}} %[[OFFSET:.*]]) -// DXIL: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.dx.resource.load.level.v3f32.tdx.Texture_v3f32_{{.*}}("dx.Texture", <3 x float>, [[RW]], 0, 0, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) -// SPIRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.spv.resource.load.level.v3f32.tspirv.Image_f32_{{.*}}("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], 0) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) -// CHECK: ret <3 x float> %[[RES]] +// SRV: define linkonce_odr hidden {{.*}} <3 x float> @hlsl::[[TEXTURE]]<float vector[3]>::Load(int vector[[[#LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[#LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]], <[[DIM]] x i32> {{.*}} %[[OFFSET:.*]]) +// DXIL-SRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.dx.resource.load.level.v3f32.tdx.Texture_v3f32_{{.*}}("dx.Texture", <3 x float>, [[RW]], 0, 0, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) +// SPIRV-SRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.spv.resource.load.level.v3f32.tspirv.Image_f32_{{.*}}("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], 0) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) +// SRV: ret <3 x float> %[[RES]] TEXTURE<int> t_int; // CHECK: define hidden {{.*}} i32 @test_load_int(int vector[[[ENTRY_DIM]]]) -// CHECK: %[[CALL:.*]] = call {{.*}} i32 @hlsl::[[TEXTURE]]<int>::Load(int vector[[[LOAD_DIM]]])(ptr {{.*}} @t_int, <[[LOAD_DIM]] x i32> noundef %{{.*}}) +// CHECK: %[[CALL:.*]] = call {{.*}} i32 @hlsl::[[TEXTURE]]<int>::Load(int vector[[[#LOAD_DIM]]])(ptr {{.*}} @t_int, <[[#LOAD_DIM]] x i32> noundef %{{.*}}) // CHECK: ret i32 %[[CALL]] int test_load_int(ENTRY_TYPE loc : LOC) { - return t_int.Load(LOAD_TYPE(loc, ZEROS)); + return t_int.Load(LOAD_ARG); } -// CHECK: define linkonce_odr hidden {{.*}} i32 @hlsl::[[TEXTURE]]<int>::Load(int vector[[[LOAD_DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]]) -// DXIL: %[[RES:.*]] = call i32 @llvm.dx.resource.load.level.i32.tdx.Texture_i32_{{.*}}("dx.Texture", i32, [[RW]], 0, 1, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> zeroinitializer) -// SPIRV: %[[RES:.*]] = call i32 @llvm.spv.resource.load.level.i32.tspirv.SignedImage_i32_{{.*}}("spirv.SignedImage", i32, 1, 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT24]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> zeroinitializer) +// CHECK: define linkonce_odr hidden {{.*}} i32 @hlsl::[[TEXTURE]]<int>::Load(int vector[[[#LOAD_DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[#LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]]) +// DXIL: %[[RES:.*]] = call i32 @llvm.dx.resource.load.level.i32.tdx.Texture_i32_{{.*}}("dx.Texture", i32, [[RW]], 0, 1, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 {{[^,]*}}, <[[DIM]] x i32> zeroinitializer) +// SPIRV: %[[RES:.*]] = call i32 @llvm.spv.resource.load.level.i32.tspirv.SignedImage_i32_{{.*}}("spirv.SignedImage", i32, 1, 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT24]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 {{[^,]*}}, <[[DIM]] x i32> zeroinitializer) // CHECK: ret i32 %[[RES]] -// CHECK: define hidden {{.*}} i32 @test_load_offset_int(int vector[[[ENTRY_DIM]]]) -// CHECK: %[[CALL:.*]] = call {{.*}} i32 @hlsl::[[TEXTURE]]<int>::Load(int vector[[[LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} @t_int, <[[LOAD_DIM]] x i32> noundef %{{.*}}, <[[DIM]] x i32> noundef splat (i32 1)) -// CHECK: ret i32 %[[CALL]] +#ifdef HAS_OFFSET +// SRV: define hidden {{.*}} i32 @test_load_offset_int(int vector[[[ENTRY_DIM]]]) +// SRV: %[[CALL:.*]] = call {{.*}} i32 @hlsl::[[TEXTURE]]<int>::Load(int vector[[[#LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} @t_int, <[[#LOAD_DIM]] x i32> noundef %{{.*}}, <[[DIM]] x i32> noundef splat (i32 1)) +// SRV: ret i32 %[[CALL]] int test_load_offset_int(ENTRY_TYPE loc : LOC) { - return t_int.Load(LOAD_TYPE(loc, ZEROS), OFFSET_ARG); + return t_int.Load(LOAD_ARG, OFFSET_ARG); } +#endif -// CHECK: define linkonce_odr hidden {{.*}} i32 @hlsl::[[TEXTURE]]<int>::Load(int vector[[[LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]], <[[DIM]] x i32> {{.*}} %[[OFFSET:.*]]) -// DXIL: %[[RES:.*]] = call i32 @llvm.dx.resource.load.level.i32.tdx.Texture_i32_{{.*}}("dx.Texture", i32, [[RW]], 0, 1, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) -// SPIRV: %[[RES:.*]] = call i32 @llvm.spv.resource.load.level.i32.tspirv.SignedImage_i32_{{.*}}("spirv.SignedImage", i32, 1, 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT24]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) -// CHECK: ret i32 %[[RES]] +// SRV: define linkonce_odr hidden {{.*}} i32 @hlsl::[[TEXTURE]]<int>::Load(int vector[[[#LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[#LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]], <[[DIM]] x i32> {{.*}} %[[OFFSET:.*]]) +// DXIL-SRV: %[[RES:.*]] = call i32 @llvm.dx.resource.load.level.i32.tdx.Texture_i32_{{.*}}("dx.Texture", i32, [[RW]], 0, 1, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) +// SPIRV-SRV: %[[RES:.*]] = call i32 @llvm.spv.resource.load.level.i32.tspirv.SignedImage_i32_{{.*}}("spirv.SignedImage", i32, 1, 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT24]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) +// SRV: ret i32 %[[RES]] TEXTURE<int2> t_int2; // CHECK: define hidden {{.*}} <[[DIM]] x i32> @test_load_int2(int vector[[[ENTRY_DIM]]]) -// CHECK: %[[CALL:.*]] = call {{.*}} <[[DIM]] x i32> @hlsl::[[TEXTURE]]<int vector[[[DIM]]]>::Load(int vector[[[LOAD_DIM]]])(ptr {{.*}} @t_int2, <[[LOAD_DIM]] x i32> noundef %{{.*}}) +// CHECK: %[[CALL:.*]] = call {{.*}} <[[DIM]] x i32> @hlsl::[[TEXTURE]]<int vector[[[DIM]]]>::Load(int vector[[[#LOAD_DIM]]])(ptr {{.*}} @t_int2, <[[#LOAD_DIM]] x i32> noundef %{{.*}}) // CHECK: ret <[[DIM]] x i32> %[[CALL]] int2 test_load_int2(ENTRY_TYPE loc : LOC) { - return t_int2.Load(LOAD_TYPE(loc, ZEROS)); + return t_int2.Load(LOAD_ARG); } -// CHECK: define linkonce_odr hidden {{.*}} <[[DIM]] x i32> @hlsl::[[TEXTURE]]<int vector[[[DIM]]]>::Load(int vector[[[LOAD_DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]]) -// DXIL: %[[RES:.*]] = call <[[DIM]] x i32> @llvm.dx.resource.load.level.v2i32.tdx.Texture_v2i32_{{.*}}("dx.Texture", <[[DIM]] x i32>, [[RW]], 0, 1, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> zeroinitializer) -// SPIRV: %[[RES:.*]] = call <[[DIM]] x i32> @llvm.spv.resource.load.level.v2i32.tspirv.SignedImage_i32_{{.*}}("spirv.SignedImage", i32, 1, 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT25]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> zeroinitializer) +// CHECK: define linkonce_odr hidden {{.*}} <[[DIM]] x i32> @hlsl::[[TEXTURE]]<int vector[[[DIM]]]>::Load(int vector[[[#LOAD_DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[#LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]]) +// DXIL: %[[RES:.*]] = call <[[DIM]] x i32> @llvm.dx.resource.load.level.v2i32.tdx.Texture_v2i32_{{.*}}("dx.Texture", <[[DIM]] x i32>, [[RW]], 0, 1, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 {{[^,]*}}, <[[DIM]] x i32> zeroinitializer) +// SPIRV: %[[RES:.*]] = call <[[DIM]] x i32> @llvm.spv.resource.load.level.v2i32.tspirv.SignedImage_i32_{{.*}}("spirv.SignedImage", i32, 1, 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT25]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 {{[^,]*}}, <[[DIM]] x i32> zeroinitializer) // CHECK: ret <[[DIM]] x i32> %[[RES]] -// CHECK: define hidden {{.*}} <[[DIM]] x i32> @test_load_offset_int2(int vector[[[ENTRY_DIM]]]) -// CHECK: %[[CALL:.*]] = call {{.*}} <[[DIM]] x i32> @hlsl::[[TEXTURE]]<int vector[[[DIM]]]>::Load(int vector[[[LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} @t_int2, <[[LOAD_DIM]] x i32> noundef %{{.*}}, <[[DIM]] x i32> noundef splat (i32 1)) -// CHECK: ret <[[DIM]] x i32> %[[CALL]] +#ifdef HAS_OFFSET +// SRV: define hidden {{.*}} <[[DIM]] x i32> @test_load_offset_int2(int vector[[[ENTRY_DIM]]]) +// SRV: %[[CALL:.*]] = call {{.*}} <[[DIM]] x i32> @hlsl::[[TEXTURE]]<int vector[[[DIM]]]>::Load(int vector[[[#LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} @t_int2, <[[#LOAD_DIM]] x i32> noundef %{{.*}}, <[[DIM]] x i32> noundef splat (i32 1)) +// SRV: ret <[[DIM]] x i32> %[[CALL]] int2 test_load_offset_int2(ENTRY_TYPE loc : LOC) { - return t_int2.Load(LOAD_TYPE(loc, ZEROS), OFFSET_ARG); + return t_int2.Load(LOAD_ARG, OFFSET_ARG); } +#endif -// CHECK: define linkonce_odr hidden {{.*}} <[[DIM]] x i32> @hlsl::[[TEXTURE]]<int vector[[[DIM]]]>::Load(int vector[[[LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]], <[[DIM]] x i32> {{.*}} %[[OFFSET:.*]]) -// DXIL: %[[RES:.*]] = call <[[DIM]] x i32> @llvm.dx.resource.load.level.v2i32.tdx.Texture_v2i32_{{.*}}("dx.Texture", <[[DIM]] x i32>, [[RW]], 0, 1, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) -// SPIRV: %[[RES:.*]] = call <[[DIM]] x i32> @llvm.spv.resource.load.level.v2i32.tspirv.SignedImage_i32_{{.*}}("spirv.SignedImage", i32, 1, 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT25]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) -// CHECK: ret <[[DIM]] x i32> %[[RES]] +// SRV: define linkonce_odr hidden {{.*}} <[[DIM]] x i32> @hlsl::[[TEXTURE]]<int vector[[[DIM]]]>::Load(int vector[[[#LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[#LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]], <[[DIM]] x i32> {{.*}} %[[OFFSET:.*]]) +// DXIL-SRV: %[[RES:.*]] = call <[[DIM]] x i32> @llvm.dx.resource.load.level.v2i32.tdx.Texture_v2i32_{{.*}}("dx.Texture", <[[DIM]] x i32>, [[RW]], 0, 1, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) +// SPIRV-SRV: %[[RES:.*]] = call <[[DIM]] x i32> @llvm.spv.resource.load.level.v2i32.tspirv.SignedImage_i32_{{.*}}("spirv.SignedImage", i32, 1, 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT25]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) +// SRV: ret <[[DIM]] x i32> %[[RES]] TEXTURE<int3> t_int3; // CHECK: define hidden {{.*}} <3 x i32> @test_load_int3(int vector[[[ENTRY_DIM]]]) -// CHECK: %[[CALL:.*]] = call {{.*}} <3 x i32> @hlsl::[[TEXTURE]]<int vector[3]>::Load(int vector[[[LOAD_DIM]]])(ptr {{.*}} @t_int3, <[[LOAD_DIM]] x i32> noundef %{{.*}}) +// CHECK: %[[CALL:.*]] = call {{.*}} <3 x i32> @hlsl::[[TEXTURE]]<int vector[3]>::Load(int vector[[[#LOAD_DIM]]])(ptr {{.*}} @t_int3, <[[#LOAD_DIM]] x i32> noundef %{{.*}}) // CHECK: ret <3 x i32> %[[CALL]] int3 test_load_int3(ENTRY_TYPE loc : LOC) { - return t_int3.Load(LOAD_TYPE(loc, ZEROS)); + return t_int3.Load(LOAD_ARG); } -// CHECK: define linkonce_odr hidden {{.*}} <3 x i32> @hlsl::[[TEXTURE]]<int vector[3]>::Load(int vector[[[LOAD_DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]]) -// DXIL: %[[RES:.*]] = call <3 x i32> @llvm.dx.resource.load.level.v3i32.tdx.Texture_v3i32_{{.*}}("dx.Texture", <3 x i32>, [[RW]], 0, 1, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> zeroinitializer) -// SPIRV: %[[RES:.*]] = call <3 x i32> @llvm.spv.resource.load.level.v3i32.tspirv.SignedImage_i32_{{.*}}("spirv.SignedImage", i32, 1, 2, [[ARRAYED]], 0, [[SAMPLED]], 0) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> zeroinitializer) +// CHECK: define linkonce_odr hidden {{.*}} <3 x i32> @hlsl::[[TEXTURE]]<int vector[3]>::Load(int vector[[[#LOAD_DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[#LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]]) +// DXIL: %[[RES:.*]] = call <3 x i32> @llvm.dx.resource.load.level.v3i32.tdx.Texture_v3i32_{{.*}}("dx.Texture", <3 x i32>, [[RW]], 0, 1, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 {{[^,]*}}, <[[DIM]] x i32> zeroinitializer) +// SPIRV: %[[RES:.*]] = call <3 x i32> @llvm.spv.resource.load.level.v3i32.tspirv.SignedImage_i32_{{.*}}("spirv.SignedImage", i32, 1, 2, [[ARRAYED]], 0, [[SAMPLED]], 0) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 {{[^,]*}}, <[[DIM]] x i32> zeroinitializer) // CHECK: ret <3 x i32> %[[RES]] -// CHECK: define hidden {{.*}} <3 x i32> @test_load_offset_int3(int vector[[[ENTRY_DIM]]]) -// CHECK: %[[CALL:.*]] = call {{.*}} <3 x i32> @hlsl::[[TEXTURE]]<int vector[3]>::Load(int vector[[[LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} @t_int3, <[[LOAD_DIM]] x i32> noundef %{{.*}}, <[[DIM]] x i32> noundef splat (i32 1)) -// CHECK: ret <3 x i32> %[[CALL]] +#ifdef HAS_OFFSET +// SRV: define hidden {{.*}} <3 x i32> @test_load_offset_int3(int vector[[[ENTRY_DIM]]]) +// SRV: %[[CALL:.*]] = call {{.*}} <3 x i32> @hlsl::[[TEXTURE]]<int vector[3]>::Load(int vector[[[#LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} @t_int3, <[[#LOAD_DIM]] x i32> noundef %{{.*}}, <[[DIM]] x i32> noundef splat (i32 1)) +// SRV: ret <3 x i32> %[[CALL]] int3 test_load_offset_int3(ENTRY_TYPE loc : LOC) { - return t_int3.Load(LOAD_TYPE(loc, ZEROS), OFFSET_ARG); + return t_int3.Load(LOAD_ARG, OFFSET_ARG); } +#endif -// CHECK: define linkonce_odr hidden {{.*}} <3 x i32> @hlsl::[[TEXTURE]]<int vector[3]>::Load(int vector[[[LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]], <[[DIM]] x i32> {{.*}} %[[OFFSET:.*]]) -// DXIL: %[[RES:.*]] = call <3 x i32> @llvm.dx.resource.load.level.v3i32.tdx.Texture_v3i32_{{.*}}("dx.Texture", <3 x i32>, [[RW]], 0, 1, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) -// SPIRV: %[[RES:.*]] = call <3 x i32> @llvm.spv.resource.load.level.v3i32.tspirv.SignedImage_i32_{{.*}}("spirv.SignedImage", i32, 1, 2, [[ARRAYED]], 0, [[SAMPLED]], 0) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) -// CHECK: ret <3 x i32> %[[RES]] +// SRV: define linkonce_odr hidden {{.*}} <3 x i32> @hlsl::[[TEXTURE]]<int vector[3]>::Load(int vector[[[#LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[#LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]], <[[DIM]] x i32> {{.*}} %[[OFFSET:.*]]) +// DXIL-SRV: %[[RES:.*]] = call <3 x i32> @llvm.dx.resource.load.level.v3i32.tdx.Texture_v3i32_{{.*}}("dx.Texture", <3 x i32>, [[RW]], 0, 1, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) +// SPIRV-SRV: %[[RES:.*]] = call <3 x i32> @llvm.spv.resource.load.level.v3i32.tspirv.SignedImage_i32_{{.*}}("spirv.SignedImage", i32, 1, 2, [[ARRAYED]], 0, [[SAMPLED]], 0) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) +// SRV: ret <3 x i32> %[[RES]] TEXTURE<int4> t_int4; // CHECK: define hidden {{.*}} <4 x i32> @test_load_int4(int vector[[[ENTRY_DIM]]]) -// CHECK: %[[CALL:.*]] = call {{.*}} <4 x i32> @hlsl::[[TEXTURE]]<int vector[4]>::Load(int vector[[[LOAD_DIM]]])(ptr {{.*}} @t_int4, <[[LOAD_DIM]] x i32> noundef %{{.*}}) +// CHECK: %[[CALL:.*]] = call {{.*}} <4 x i32> @hlsl::[[TEXTURE]]<int vector[4]>::Load(int vector[[[#LOAD_DIM]]])(ptr {{.*}} @t_int4, <[[#LOAD_DIM]] x i32> noundef %{{.*}}) // CHECK: ret <4 x i32> %[[CALL]] int4 test_load_int4(ENTRY_TYPE loc : LOC) { - return t_int4.Load(LOAD_TYPE(loc, ZEROS)); + return t_int4.Load(LOAD_ARG); } -// CHECK: define linkonce_odr hidden {{.*}} <4 x i32> @hlsl::[[TEXTURE]]<int vector[4]>::Load(int vector[[[LOAD_DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]]) -// DXIL: %[[RES:.*]] = call <4 x i32> @llvm.dx.resource.load.level.v4i32.tdx.Texture_v4i32_{{.*}}("dx.Texture", <4 x i32>, [[RW]], 0, 1, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> zeroinitializer) -// SPIRV: %[[RES:.*]] = call <4 x i32> @llvm.spv.resource.load.level.v4i32.tspirv.SignedImage_i32_{{.*}}("spirv.SignedImage", i32, 1, 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT21]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> zeroinitializer) +// CHECK: define linkonce_odr hidden {{.*}} <4 x i32> @hlsl::[[TEXTURE]]<int vector[4]>::Load(int vector[[[#LOAD_DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[#LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]]) +// DXIL: %[[RES:.*]] = call <4 x i32> @llvm.dx.resource.load.level.v4i32.tdx.Texture_v4i32_{{.*}}("dx.Texture", <4 x i32>, [[RW]], 0, 1, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 {{[^,]*}}, <[[DIM]] x i32> zeroinitializer) +// SPIRV: %[[RES:.*]] = call <4 x i32> @llvm.spv.resource.load.level.v4i32.tspirv.SignedImage_i32_{{.*}}("spirv.SignedImage", i32, 1, 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT21]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 {{[^,]*}}, <[[DIM]] x i32> zeroinitializer) // CHECK: ret <4 x i32> %[[RES]] -// CHECK: define hidden {{.*}} <4 x i32> @test_load_offset_int4(int vector[[[ENTRY_DIM]]]) -// CHECK: %[[CALL:.*]] = call {{.*}} <4 x i32> @hlsl::[[TEXTURE]]<int vector[4]>::Load(int vector[[[LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} @t_int4, <[[LOAD_DIM]] x i32> noundef %{{.*}}, <[[DIM]] x i32> noundef splat (i32 1)) -// CHECK: ret <4 x i32> %[[CALL]] +#ifdef HAS_OFFSET +// SRV: define hidden {{.*}} <4 x i32> @test_load_offset_int4(int vector[[[ENTRY_DIM]]]) +// SRV: %[[CALL:.*]] = call {{.*}} <4 x i32> @hlsl::[[TEXTURE]]<int vector[4]>::Load(int vector[[[#LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} @t_int4, <[[#LOAD_DIM]] x i32> noundef %{{.*}}, <[[DIM]] x i32> noundef splat (i32 1)) +// SRV: ret <4 x i32> %[[CALL]] int4 test_load_offset_int4(ENTRY_TYPE loc : LOC) { - return t_int4.Load(LOAD_TYPE(loc, ZEROS), OFFSET_ARG); + return t_int4.Load(LOAD_ARG, OFFSET_ARG); } +#endif -// CHECK: define linkonce_odr hidden {{.*}} <4 x i32> @hlsl::[[TEXTURE]]<int vector[4]>::Load(int vector[[[LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]], <[[DIM]] x i32> {{.*}} %[[OFFSET:.*]]) -// DXIL: %[[RES:.*]] = call <4 x i32> @llvm.dx.resource.load.level.v4i32.tdx.Texture_v4i32_{{.*}}("dx.Texture", <4 x i32>, [[RW]], 0, 1, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) -// SPIRV: %[[RES:.*]] = call <4 x i32> @llvm.spv.resource.load.level.v4i32.tspirv.SignedImage_i32_{{.*}}("spirv.SignedImage", i32, 1, 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT21]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) -// CHECK: ret <4 x i32> %[[RES]] +// SRV: define linkonce_odr hidden {{.*}} <4 x i32> @hlsl::[[TEXTURE]]<int vector[4]>::Load(int vector[[[#LOAD_DIM]]], int vector[[[DIM]]])(ptr {{.*}} %[[THIS:.*]], <[[#LOAD_DIM]] x i32> {{.*}} %[[LOAD:.*]], <[[DIM]] x i32> {{.*}} %[[OFFSET:.*]]) +// DXIL-SRV: %[[RES:.*]] = call <4 x i32> @llvm.dx.resource.load.level.v4i32.tdx.Texture_v4i32_{{.*}}("dx.Texture", <4 x i32>, [[RW]], 0, 1, [[DXIL_TY]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) +// SPIRV-SRV: %[[RES:.*]] = call <4 x i32> @llvm.spv.resource.load.level.v4i32.tspirv.SignedImage_i32_{{.*}}("spirv.SignedImage", i32, 1, 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT21]]) %{{.*}}, <[[COORD_DIM]] x i32> %{{.*}}, i32 %{{.*}}, <[[DIM]] x i32> %{{.*}}) +// SRV: ret <4 x i32> %[[RES]] diff --git a/clang/test/SemaHLSL/Resources/Textures-Load-errors.hlsl b/clang/test/SemaHLSL/Resources/Textures-Load-errors.hlsl index c2f9f9999db9f..3a13b1d1e13ff 100644 --- a/clang/test/SemaHLSL/Resources/Textures-Load-errors.hlsl +++ b/clang/test/SemaHLSL/Resources/Textures-Load-errors.hlsl @@ -1,21 +1,21 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl \ -// RUN: -finclude-default-header -DTEXTURE=Texture2D -DLOAD_TYPE=int3 \ -// RUN: -DLOAD_FLOAT_TYPE=float3 -DNARROW_LOAD_TYPE=int2 \ +// RUN: -finclude-default-header -DTEXTURE=Texture2D -DHAS_OFFSET \ +// RUN: -DLOAD_TYPE=int3 -DLOAD_FLOAT_TYPE=float3 -DNARROW_LOAD_TYPE=int2 \ // RUN: -DWIDE_LOAD_TYPE=int4 -DOFFSET_TYPE=int2 -DOFFSET_FLOAT_TYPE=float2 \ // RUN: -DWIDE_OFFSET_TYPE=int3 -verify %s // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl \ -// RUN: -finclude-default-header -DTEXTURE=Texture2DArray -DLOAD_TYPE=int4 \ -// RUN: -DLOAD_FLOAT_TYPE=float4 -DNARROW_LOAD_TYPE=int3 -DOFFSET_TYPE=int2 \ -// RUN: -DOFFSET_FLOAT_TYPE=float2 -DWIDE_OFFSET_TYPE=int3 -verify %s -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl \ -// RUN: -finclude-default-header -DTEXTURE=RWTexture2D -DLOAD_TYPE=int3 \ -// RUN: -DLOAD_FLOAT_TYPE=float3 -DNARROW_LOAD_TYPE=int2 \ -// RUN: -DWIDE_LOAD_TYPE=int4 -DOFFSET_TYPE=int2 -DOFFSET_FLOAT_TYPE=float2 \ +// RUN: -finclude-default-header -DTEXTURE=Texture2DArray -DHAS_OFFSET \ +// RUN: -DLOAD_TYPE=int4 -DLOAD_FLOAT_TYPE=float4 -DNARROW_LOAD_TYPE=int3 \ +// RUN: -DOFFSET_TYPE=int2 -DOFFSET_FLOAT_TYPE=float2 \ // RUN: -DWIDE_OFFSET_TYPE=int3 -verify %s // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl \ -// RUN: -finclude-default-header -DTEXTURE=RWTexture2DArray -DLOAD_TYPE=int4 \ -// RUN: -DLOAD_FLOAT_TYPE=float4 -DNARROW_LOAD_TYPE=int3 -DOFFSET_TYPE=int2 \ -// RUN: -DOFFSET_FLOAT_TYPE=float2 -DWIDE_OFFSET_TYPE=int3 -verify %s +// RUN: -finclude-default-header -DTEXTURE=RWTexture2D -DLOAD_TYPE=int2 \ +// RUN: -DLOAD_FLOAT_TYPE=float2 -DNARROW_LOAD_TYPE=int1 \ +// RUN: -DWIDE_LOAD_TYPE=int3 -DOFFSET_TYPE=int2 -verify %s +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl \ +// RUN: -finclude-default-header -DTEXTURE=RWTexture2DArray -DLOAD_TYPE=int3 \ +// RUN: -DLOAD_FLOAT_TYPE=float3 -DNARROW_LOAD_TYPE=int2 \ +// RUN: -DWIDE_LOAD_TYPE=int4 -DOFFSET_TYPE=int2 -verify %s // Parameterized over the texture types in the RUN lines above; adding a texture // of another dimension only requires new RUN lines. @@ -29,6 +29,14 @@ // OFFSET_TYPE offset type, one component per resource dimension // OFFSET_FLOAT_TYPE offset type, but floating point // WIDE_OFFSET_TYPE an offset with one component too many +// HAS_OFFSET defined for read-only (SRV) textures, whose location +// carries a trailing mip level and which have a second +// Load overload taking an offset +// +// A UAV descriptor binds a single mip slice, so a RWTexture location has no mip +// component, and DXIL's TextureLoad takes no offset on a UAV. Those types +// therefore have one Load overload instead of two, which changes the +// diagnostics from overload resolution failures to plain arity errors. // // The diagnostics that name a vector width use `-re` directives so that the // same assertions apply to every texture type. @@ -41,45 +49,67 @@ float4 test_exact_location(LOAD_TYPE loc) { } float4 test_too_few_args() { +#ifdef HAS_OFFSET return t.Load(); // expected-error {{no matching member function for call to 'Load'}} // expected-note@*:* {{candidate function not viable: requires single argument 'Location', but no arguments were provided}} // expected-note@*:* {{candidate function not viable: requires 2 arguments, but 0 were provided}} +#else + return t.Load(); // expected-error {{too few arguments to function call, single argument 'Location' was not specified}} + // expected-note@*:* {{'Load' declared here}} +#endif } float4 test_too_many_args(LOAD_TYPE loc, OFFSET_TYPE offset) { +#ifdef HAS_OFFSET return t.Load(loc, offset, 1); // expected-error {{no matching member function for call to 'Load'}} // expected-note@*:* {{candidate function not viable: requires 2 arguments, but 3 were provided}} // expected-note@*:* {{candidate function not viable: requires single argument 'Location', but 3 arguments were provided}} +#else + // There is no offset overload on a UAV, so even two arguments is too many. + return t.Load(loc, offset); // expected-error {{too many arguments to function call, expected single argument 'Location', have 2 arguments}} + // expected-note@*:* {{'Load' declared here}} +#endif } float4 test_invalid_coord_type(LOAD_FLOAT_TYPE loc) { return t.Load(loc); // expected-warning {{implicit conversion turns floating-point number into integer: }} } +#ifdef HAS_OFFSET float4 test_invalid_offset_type(LOAD_TYPE loc, OFFSET_FLOAT_TYPE offset) { // expected-warning-re@+1 {{implicit conversion turns floating-point number into integer: '{{float[0-9]}}' (aka 'vector<float, {{[0-9]}}>') to 'vector<int, {{[0-9]}}>' (vector of {{[0-9]}} 'int' values)}} return t.Load(loc, offset); } +#endif float4 test_invalid_location_count(NARROW_LOAD_TYPE loc) { +#ifdef HAS_OFFSET return t.Load(loc); // expected-error {{no matching member function for call to 'Load'}} // expected-note@*:* {{candidate function not viable: no known conversion from }} // expected-note@*:* {{candidate function not viable: requires 2 arguments, but 1 was provided}} +#else + // expected-error-re@+1 {{cannot initialize a parameter of type 'vector<int, {{[0-9]}}>' (vector of {{[0-9]}} 'int' values) with an lvalue of type '{{int[0-9]?}}'{{( \(aka 'vector<int, [0-9]>'\))?}}}} + return t.Load(loc); +#endif } #ifdef WIDE_LOAD_TYPE float4 test_truncated_location_count(WIDE_LOAD_TYPE loc) { + // On a UAV this is exactly a location that still carries a mip component: it + // truncates like any other over-wide HLSL vector argument. // expected-warning-re@+1 {{implicit conversion truncates vector: '{{int[0-9]}}' (aka 'vector<int, {{[0-9]}}>') to 'vector<int, {{[0-9]}}>' (vector of {{[0-9]}} 'int' values)}} return t.Load(loc); } #endif +#ifdef HAS_OFFSET float4 test_splatted_offset_count(LOAD_TYPE loc, int offset) { // No errors expected. The vector will be generated by splatting `offset`. return t.Load(loc, offset); } -float4 test_truncated_offset_count(LOAD_TYPE loc, WIDE_OFFSET_TYPE offset) { +float4 test_invalid_offset_count(LOAD_TYPE loc, WIDE_OFFSET_TYPE offset) { // expected-warning-re@+1 {{implicit conversion truncates vector: '{{int[0-9]}}' (aka 'vector<int, {{[0-9]}}>') to 'vector<int, {{[0-9]}}>' (vector of {{[0-9]}} 'int' values)}} return t.Load(loc, offset); } +#endif >From 63bedc99ecc6f6eb51e00e70fb21a09ad67cbb7d Mon Sep 17 00:00:00 2001 From: Deric Cheung <[email protected]> Date: Fri, 28 Aug 2026 15:14:08 -0700 Subject: [PATCH 2/5] Use poison instead of 0 for unused mip level --- clang/lib/CodeGen/CGHLSLBuiltins.cpp | 2 +- clang/test/CodeGenHLSL/resources/Textures-Load.hlsl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp index e1999ec36e382..062faadcdcab2 100644 --- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp +++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp @@ -812,7 +812,7 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, // A UAV descriptor binds a single mip slice, so a RWTexture location is // all coordinate and there is no mip level to select. CoordOp = CoordLODOp; - LODOp = llvm::ConstantInt::get(Int32Ty, 0); + LODOp = llvm::PoisonValue::get(Int32Ty); } else { auto *CoordLODVecTy = cast<llvm::FixedVectorType>(CoordLODOp->getType()); unsigned NumElts = CoordLODVecTy->getNumElements(); diff --git a/clang/test/CodeGenHLSL/resources/Textures-Load.hlsl b/clang/test/CodeGenHLSL/resources/Textures-Load.hlsl index bf53f2ed7370a..fb280af49d9c5 100644 --- a/clang/test/CodeGenHLSL/resources/Textures-Load.hlsl +++ b/clang/test/CodeGenHLSL/resources/Textures-Load.hlsl @@ -137,9 +137,9 @@ float4 test_load(ENTRY_TYPE loc : LOC) : SV_Target { // SRV: %[[COORD:.*]] = shufflevector <[[#LOAD_DIM]] x i32> %[[LOAD_VAL]], <[[#LOAD_DIM]] x i32> poison, <[[COORD_DIM]] x i32> [[COORD_MASK]] // SRV: %[[LOD:.*]] = extractelement <[[#LOAD_DIM]] x i32> %[[LOAD_VAL]], i64 [[COORD_DIM]] // DXIL-SRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_{{.*}}(target("dx.Texture", <4 x float>, [[RW]], 0, 0, [[DXIL_TY]]) %[[HANDLE]], <[[COORD_DIM]] x i32> %[[COORD]], i32 %[[LOD]], <[[DIM]] x i32> zeroinitializer) -// DXIL-UAV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_{{.*}}(target("dx.Texture", <4 x float>, [[RW]], 0, 0, [[DXIL_TY]]) %[[HANDLE]], <[[COORD_DIM]] x i32> %[[LOAD_VAL]], i32 0, <[[DIM]] x i32> zeroinitializer) +// DXIL-UAV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.dx.resource.load.level.v4f32.tdx.Texture_v4f32_{{.*}}(target("dx.Texture", <4 x float>, [[RW]], 0, 0, [[DXIL_TY]]) %[[HANDLE]], <[[COORD_DIM]] x i32> %[[LOAD_VAL]], i32 poison, <[[DIM]] x i32> zeroinitializer) // SPIRV-SRV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.spv.resource.load.level.v4f32.tspirv.Image_f32_{{.*}}(target("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT1]]) %[[HANDLE]], <[[COORD_DIM]] x i32> %[[COORD]], i32 %[[LOD]], <[[DIM]] x i32> zeroinitializer) -// SPIRV-UAV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.spv.resource.load.level.v4f32.tspirv.Image_f32_{{.*}}(target("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT1]]) %[[HANDLE]], <[[COORD_DIM]] x i32> %[[LOAD_VAL]], i32 0, <[[DIM]] x i32> zeroinitializer) +// SPIRV-UAV: %[[RES:.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.spv.resource.load.level.v4f32.tspirv.Image_f32_{{.*}}(target("spirv.Image", float, [[SPV_DIM]], 2, [[ARRAYED]], 0, [[SAMPLED]], [[FORMAT1]]) %[[HANDLE]], <[[COORD_DIM]] x i32> %[[LOAD_VAL]], i32 poison, <[[DIM]] x i32> zeroinitializer) // CHECK: ret <4 x float> %[[RES]] // SRV: define hidden {{.*}} <4 x float> @test_load_offset(int vector[[[ENTRY_DIM]]]) >From 870400fd33385bf3292aa102bf88a689dd2ec70a Mon Sep 17 00:00:00 2001 From: Deric Cheung <[email protected]> Date: Fri, 28 Aug 2026 15:14:12 -0700 Subject: [PATCH 3/5] Add AST test --- clang/test/AST/HLSL/Textures-AST.hlsl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/clang/test/AST/HLSL/Textures-AST.hlsl b/clang/test/AST/HLSL/Textures-AST.hlsl index d491055cda1e0..6e5655f0cbafd 100644 --- a/clang/test/AST/HLSL/Textures-AST.hlsl +++ b/clang/test/AST/HLSL/Textures-AST.hlsl @@ -50,6 +50,23 @@ // CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] // CHECK-SAME: {{\[\[}}hlsl::dimension("[[DIM_NAME]]"){{\]\]}} +// UAV: CXXMethodDecl {{.*}} Load 'element_type (vector<int, [[INDEX_DIM]]>)' inline +// UAV-NEXT: ParmVarDecl {{.*}} Location 'vector<int, [[INDEX_DIM]]>' +// UAV-NEXT: CompoundStmt +// UAV-NEXT: ReturnStmt +// UAV-NEXT: CStyleCastExpr {{.*}} 'element_type' <Dependent> +// UAV-NEXT: CallExpr {{.*}} '<dependent type>' +// UAV-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_load_level' 'void (...) noexcept' +// UAV-NEXT: MemberExpr {{.*}} '__hlsl_resource_t +// UAV-SAME{LITERAL}: [[hlsl::resource_class("UAV")]] +// UAV-ARRAY-SAME{LITERAL}: [[hlsl::is_array]] +// UAV-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] +// UAV-SAME: {{\[\[}}hlsl::dimension("[[DIM_NAME]]"){{\]\]}} +// UAV-SAME: ' lvalue .__handle +// UAV-NEXT: CXXThisExpr {{.*}} 'hlsl::[[TEXTURE]]<element_type>' lvalue implicit this +// UAV-NEXT: DeclRefExpr {{.*}} 'vector<int, [[INDEX_DIM]]>' lvalue ParmVar {{.*}} 'Location' 'vector<int, [[INDEX_DIM]]>' +// UAV-NEXT: AlwaysInlineAttr + // SRV: CXXMethodDecl {{.*}} operator[] 'const hlsl_device element_type &(vector<unsigned int, [[INDEX_DIM]]>) const' inline // SRV-NEXT: ParmVarDecl {{.*}} Index 'vector<unsigned int, [[INDEX_DIM]]>' // SRV-NEXT: CompoundStmt >From d55447d66bc594070d1feda16251bf72c5b9f99c Mon Sep 17 00:00:00 2001 From: Deric Cheung <[email protected]> Date: Fri, 28 Aug 2026 15:18:39 -0700 Subject: [PATCH 4/5] Remove unnecessary added trailing periods --- clang/test/CodeGenHLSL/resources/Textures-Load.hlsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/CodeGenHLSL/resources/Textures-Load.hlsl b/clang/test/CodeGenHLSL/resources/Textures-Load.hlsl index fb280af49d9c5..890efbdfeb02e 100644 --- a/clang/test/CodeGenHLSL/resources/Textures-Load.hlsl +++ b/clang/test/CodeGenHLSL/resources/Textures-Load.hlsl @@ -39,7 +39,7 @@ // RUN: -DFORMAT1=0 -DFORMAT3=0 -DFORMAT6=0 -DFORMAT21=0 -DFORMAT24=0 \ // RUN: -DFORMAT25=0 -DSPV_DIM=1 -DENTRY_DIM=2 -DDIM=2 -// RWTexture2D. +// RWTexture2D // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm \ // RUN: -disable-llvm-passes -finclude-default-header -DENTRY_TYPE=int2 \ // RUN: -DTEXTURE=RWTexture2D -DLOAD_ARG="loc" -o - %s \ @@ -56,7 +56,7 @@ // RUN: -DSAMPLED=2 -DFORMAT1=1 -DFORMAT3=3 -DFORMAT6=6 -DFORMAT21=21 \ // RUN: -DFORMAT24=24 -DFORMAT25=25 -DSPV_DIM=1 -DENTRY_DIM=2 -DDIM=2 -// RWTexture2DArray. +// RWTexture2DArray // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm \ // RUN: -disable-llvm-passes -finclude-default-header -DENTRY_TYPE=int2 \ // RUN: -DTEXTURE=RWTexture2DArray -DLOAD_ARG="int3(loc, 0)" -o - %s \ >From 39d1c4450c790c611f09f382f0a24765b01d92cf Mon Sep 17 00:00:00 2001 From: Deric Cheung <[email protected]> Date: Fri, 28 Aug 2026 15:18:49 -0700 Subject: [PATCH 5/5] Revise description of HAS_OFFSET --- clang/test/CodeGenHLSL/resources/Textures-Load.hlsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/CodeGenHLSL/resources/Textures-Load.hlsl b/clang/test/CodeGenHLSL/resources/Textures-Load.hlsl index 890efbdfeb02e..26692a276287d 100644 --- a/clang/test/CodeGenHLSL/resources/Textures-Load.hlsl +++ b/clang/test/CodeGenHLSL/resources/Textures-Load.hlsl @@ -78,8 +78,8 @@ // of another dimension only requires new RUN lines. // // ENTRY_TYPE the entry point's own coordinate type -// HAS_OFFSET defined for read-only (SRV) textures, which have a -// second Load overload taking an offset +// HAS_OFFSET defined for types whose Load has an overload taking an +// offset // OFFSET_ARG a literal offset argument // TEXTURE resource type name // LOAD_ARG the Load location, built from the entry point's `loc` _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
