Author: Deric C.
Date: 2026-08-31T18:04:45-07:00
New Revision: b04534c1df27bd06fe3ae108a2795e8498e96c5b

URL: 
https://github.com/llvm/llvm-project/commit/b04534c1df27bd06fe3ae108a2795e8498e96c5b
DIFF: 
https://github.com/llvm/llvm-project/commit/b04534c1df27bd06fe3ae108a2795e8498e96c5b.diff

LOG: [HLSL] Add UAV-specific texture load method (#218728)

Fixes https://github.com/llvm/llvm-project/issues/218535

UAV texture resources were using the SRV version of the .Load() method
and resulted in no matching member function calls when attempted to be
used.
This PR fixes that issue by adding addRWTextureLoadMethods() to
HLSLBuiltinTypeDeclBuilder.cpp and fixing the codegen for
BI__builtin_hlsl_resource_load_level to handle UAVs.

Assisted by: Claude Opus 5

---

<sub>Stack created with <a
href="https://github.com/github/gh-stack";>GitHub Stacks CLI</a> • <a
href="https://gh.io/stacks-feedback";>Give Feedback 💬</a></sub>

Added: 
    

Modified: 
    clang/lib/CodeGen/CGHLSLBuiltins.cpp
    clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
    clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
    clang/lib/Sema/HLSLExternalSemaSource.cpp
    clang/lib/Sema/SemaHLSL.cpp
    clang/test/AST/HLSL/Textures-AST.hlsl
    clang/test/CodeGenHLSL/resources/Textures-Load.hlsl
    clang/test/SemaHLSL/Resources/Textures-Load-errors.hlsl

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp 
b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 36f729a98539a..062faadcdcab2 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::PoisonValue::get(Int32Ty);
+    } 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/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

diff  --git a/clang/test/CodeGenHLSL/resources/Textures-Load.hlsl 
b/clang/test/CodeGenHLSL/resources/Textures-Load.hlsl
index fb643ee0533ee..26692a276287d 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
 // 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
 // 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 types whose Load has an 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 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 poison, <[[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


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to