[llvm-branch-commits] [clang] [llvm] [HLSL] GetDimensions methods for buffer resources (PR #161929)
Helena Kotas via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Oct 9 14:05:01 PDT 2025
https://github.com/hekota updated https://github.com/llvm/llvm-project/pull/161929
>From e50918910a0ce590228c6ecacd4ff2a578da6f58 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Fri, 3 Oct 2025 17:33:19 -0700
Subject: [PATCH 1/3] [HLSL] GetDimensions methods for buffer resources
Adds GetDimensions methods on all supported buffer resources.
---
clang/include/clang/Basic/Builtins.td | 12 +++
clang/lib/CodeGen/CGHLSLBuiltins.cpp | 61 ++++++++++++++
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 81 ++++++++++++++++++-
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h | 2 +
clang/lib/Sema/HLSLExternalSemaSource.cpp | 11 +++
clang/lib/Sema/SemaHLSL.cpp | 18 +++++
.../test/AST/HLSL/ByteAddressBuffers-AST.hlsl | 14 ++++
.../test/AST/HLSL/StructuredBuffers-AST.hlsl | 22 +++++
clang/test/AST/HLSL/TypedBuffers-AST.hlsl | 14 ++++
.../resources/ByteAddressBuffers-methods.hlsl | 47 +++++++++++
.../StructuredBuffers-methods-lib.hlsl | 53 +++++++++++-
.../StructuredBuffers-methods-ps.hlsl | 37 +++++++++
.../resources/TypedBuffers-methods.hlsl | 34 ++++++++
llvm/include/llvm/IR/IntrinsicsDirectX.td | 4 +
14 files changed, 406 insertions(+), 4 deletions(-)
create mode 100644 clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 468121f7d20ab..0b1587be51217 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4951,6 +4951,18 @@ def HLSLResourceNonUniformIndex : LangBuiltin<"HLSL_LANG"> {
let Prototype = "uint32_t(uint32_t)";
}
+def HLSLResourceGetDimensions : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_buffer_getdimensions"];
+ let Attributes = [NoThrow];
+ let Prototype = "void(...)";
+}
+
+def HLSLResourceGetStride : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_buffer_getstride"];
+ let Attributes = [NoThrow];
+ let Prototype = "void(...)";
+}
+
def HLSLAll : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_all"];
let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 6c0fc8d7f07be..373153e01c128 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -160,6 +160,58 @@ static Value *handleHlslSplitdouble(const CallExpr *E, CodeGenFunction *CGF) {
return LastInst;
}
+static Value *emitDXILGetDimensions(CodeGenFunction *CGF, Value *Handle,
+ Value *MipLevel, LValue *OutArg0,
+ LValue *OutArg1 = nullptr,
+ LValue *OutArg2 = nullptr,
+ LValue *OutArg3 = nullptr) {
+ assert(OutArg0 && "first output argument is required");
+
+ llvm::Type *I32 = CGF->Int32Ty;
+ StructType *RetTy = llvm::StructType::get(I32, I32, I32, I32);
+
+ CallInst *CI = CGF->Builder.CreateIntrinsic(
+ RetTy, llvm::Intrinsic::dx_resource_getdimensions,
+ ArrayRef<Value *>{Handle, MipLevel});
+
+ Value *LastInst = nullptr;
+ unsigned OutArgIndex = 0;
+ for (LValue *OutArg : {OutArg0, OutArg1, OutArg2, OutArg3}) {
+ if (OutArg) {
+ Value *OutArgVal = CGF->Builder.CreateExtractValue(CI, OutArgIndex);
+ LastInst = CGF->Builder.CreateStore(OutArgVal, OutArg->getAddress());
+ }
+ ++OutArgIndex;
+ }
+ assert(LastInst && "no output argument stored?");
+ return LastInst;
+}
+
+static Value *emitBufferGetDimensions(CodeGenFunction *CGF, Value *Handle,
+ LValue &Dim) {
+ // Generate the call to get the buffer dimension.
+ switch (CGF->CGM.getTarget().getTriple().getArch()) {
+ case llvm::Triple::dxil:
+ return emitDXILGetDimensions(CGF, Handle, PoisonValue::get(CGF->Int32Ty),
+ &Dim);
+ break;
+ case llvm::Triple::spirv:
+ llvm_unreachable("SPIR-V GetDimensions codegen not implemented yet.");
+ default:
+ llvm_unreachable("GetDimensions not supported by target architecture");
+ }
+}
+
+static Value *emitBufferStride(CodeGenFunction *CGF, const Expr *HandleExpr,
+ LValue &Stride) {
+ // Figure out the stride of the buffer elements from the handle type.
+ auto *HandleTy =
+ cast<HLSLAttributedResourceType>(HandleExpr->getType().getTypePtr());
+ QualType ElementTy = HandleTy->getContainedType();
+ Value *StrideValue = CGF->getTypeSize(ElementTy);
+ return CGF->Builder.CreateStore(StrideValue, Stride.getAddress());
+}
+
// Return dot product intrinsic that corresponds to the QT scalar type
static Intrinsic::ID getDotProductIntrinsic(CGHLSLRuntime &RT, QualType QT) {
if (QT->isFloatingType())
@@ -359,6 +411,15 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
RetTy, CGM.getHLSLRuntime().getNonUniformResourceIndexIntrinsic(),
ArrayRef<Value *>{IndexOp});
}
+ case Builtin::BI__builtin_hlsl_buffer_getdimensions: {
+ Value *Handle = EmitScalarExpr(E->getArg(0));
+ LValue Dim = EmitLValue(E->getArg(1));
+ return emitBufferGetDimensions(this, Handle, Dim);
+ }
+ case Builtin::BI__builtin_hlsl_buffer_getstride: {
+ LValue Stride = EmitLValue(E->getArg(1));
+ return emitBufferStride(this, E->getArg(0), Stride);
+ }
case Builtin::BI__builtin_hlsl_all: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
return Builder.CreateIntrinsic(
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 3c20ccd799b2d..d6d6b31aa2d9d 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -57,6 +57,29 @@ CXXConstructorDecl *lookupCopyConstructor(QualType ResTy) {
return CD;
return nullptr;
}
+
+ParameterABI
+convertParamModifierToParamABI(HLSLParamModifierAttr::Spelling Modifier) {
+ assert(Modifier != HLSLParamModifierAttr::Spelling::Keyword_in &&
+ "HLSL 'in' parameters modifier cannot be converted to ParameterABI");
+ switch (Modifier) {
+ case HLSLParamModifierAttr::Spelling::Keyword_out:
+ return ParameterABI::HLSLOut;
+ case HLSLParamModifierAttr::Spelling::Keyword_inout:
+ return ParameterABI::HLSLInOut;
+ default:
+ llvm_unreachable("Invalid HLSL parameter modifier");
+ }
+}
+
+QualType getInoutParameterType(ASTContext &AST, QualType Ty) {
+ assert(!Ty->isReferenceType() &&
+ "Pointer and reference types cannot be inout or out parameters");
+ Ty = AST.getLValueReferenceType(Ty);
+ Ty.addRestrict();
+ return Ty;
+}
+
} // namespace
// Builder for template arguments of builtin types. Used internally
@@ -421,13 +444,32 @@ BuiltinTypeMethodBuilder::addParam(StringRef Name, QualType Ty,
void BuiltinTypeMethodBuilder::createDecl() {
assert(Method == nullptr && "Method or constructor is already created");
- // create method or constructor type
+ // create function prototype
ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
SmallVector<QualType> ParamTypes;
- for (Param &MP : Params)
- ParamTypes.emplace_back(MP.Ty);
+ SmallVector<FunctionType::ExtParameterInfo> ParamExtInfos(Params.size());
+ uint32_t ArgIndex = 0;
+ bool IsTemplate = DeclBuilder.Template != nullptr;
+ bool UseParamExtInfo = false;
+ for (Param &MP : Params) {
+ QualType Ty = MP.Ty;
+ if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) {
+ UseParamExtInfo = true;
+ ParamExtInfos[ArgIndex].withABI(
+ convertParamModifierToParamABI(MP.Modifier));
+ // Only update types on inout and out parameters for non-templated
+ // methods. Templated types will have their inout/out parameters
+ // converted to references during template instantiation.
+ if (!IsTemplate)
+ Ty = getInoutParameterType(AST, Ty);
+ }
+ ParamTypes.emplace_back(Ty);
+ ++ArgIndex;
+ }
FunctionProtoType::ExtProtoInfo ExtInfo;
+ if (UseParamExtInfo)
+ ExtInfo.ExtParameterInfos = ParamExtInfos.data();
if (IsConst)
ExtInfo.TypeQuals.addConst();
@@ -459,6 +501,7 @@ void BuiltinTypeMethodBuilder::createDecl() {
AST.getTrivialTypeSourceInfo(MP.Ty, SourceLocation()), SC_None,
nullptr);
if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) {
+ Parm->setType(getInoutParameterType(AST, Parm->getType()));
auto *Mod =
HLSLParamModifierAttr::Create(AST, SourceRange(), MP.Modifier);
Parm->addAttr(Mod);
@@ -1127,5 +1170,37 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addConsumeMethod() {
.finalize();
}
+BuiltinTypeDeclBuilder &
+BuiltinTypeDeclBuilder::addGetDimensionsMethodForBuffer() {
+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
+ ASTContext &AST = SemaRef.getASTContext();
+ QualType UIntTy = AST.UnsignedIntTy;
+
+ QualType HandleTy = getResourceHandleField()->getType();
+ auto *AttrResTy = cast<HLSLAttributedResourceType>(HandleTy.getTypePtr());
+
+ // Structured buffers except {RW}ByteAddressBuffer have overload
+ // GetDimensions(out uint numStructs, out uint stride).
+ if (AttrResTy->getAttrs().RawBuffer &&
+ AttrResTy->getContainedType() != AST.Char8Ty) {
+ return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
+ .addParam("numStructs", UIntTy, HLSLParamModifierAttr::Keyword_out)
+ .addParam("stride", UIntTy, HLSLParamModifierAttr::Keyword_out)
+ .callBuiltin("__builtin_hlsl_buffer_getdimensions", QualType(),
+ PH::Handle, PH::_0)
+ .callBuiltin("__builtin_hlsl_buffer_getstride", QualType(), PH::Handle,
+ PH::_1)
+ .finalize();
+ }
+
+ // Typed buffers and {RW}ByteAddressBuffer have overload
+ // GetDimensions(out uint dim).
+ return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
+ .addParam("dim", UIntTy, HLSLParamModifierAttr::Keyword_out)
+ .callBuiltin("__builtin_hlsl_buffer_getdimensions", QualType(),
+ PH::Handle, PH::_0)
+ .finalize();
+}
+
} // namespace hlsl
} // namespace clang
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index a981602a50461..920a2f07a16ad 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -95,6 +95,8 @@ class BuiltinTypeDeclBuilder {
BuiltinTypeDeclBuilder &addAppendMethod();
BuiltinTypeDeclBuilder &addConsumeMethod();
+ BuiltinTypeDeclBuilder &addGetDimensionsMethodForBuffer();
+
private:
BuiltinTypeDeclBuilder &addResourceMember(StringRef MemberName,
ResourceClass RC, bool IsROV,
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index cc43e9474ea79..ce69e4987d6cd 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -380,6 +380,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
/*RawBuffer=*/false, /*HasCounter=*/false)
.addArraySubscriptOperators()
.addLoadMethods()
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
@@ -392,6 +393,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
/*RawBuffer=*/false, /*HasCounter=*/false)
.addArraySubscriptOperators()
.addLoadMethods()
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
@@ -404,6 +406,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
/*RawBuffer=*/false, /*HasCounter=*/false)
.addArraySubscriptOperators()
.addLoadMethods()
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
@@ -415,6 +418,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
/*RawBuffer=*/true, /*HasCounter=*/false)
.addArraySubscriptOperators()
.addLoadMethods()
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
@@ -428,6 +432,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
.addLoadMethods()
.addIncrementCounterMethod()
.addDecrementCounterMethod()
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
@@ -439,6 +444,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/false,
/*RawBuffer=*/true, /*HasCounter=*/true)
.addAppendMethod()
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
@@ -450,6 +456,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/false,
/*RawBuffer=*/true, /*HasCounter=*/true)
.addConsumeMethod()
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
@@ -464,6 +471,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
.addLoadMethods()
.addIncrementCounterMethod()
.addDecrementCounterMethod()
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
@@ -472,6 +480,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::SRV, /*IsROV=*/false,
/*RawBuffer=*/true, /*HasCounter=*/false)
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWByteAddressBuffer")
@@ -479,6 +488,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/false,
/*RawBuffer=*/true, /*HasCounter=*/false)
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace,
@@ -487,6 +497,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/true,
/*RawBuffer=*/true, /*HasCounter=*/false)
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
}
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index fa30c66b62684..e3281c493da50 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -2978,6 +2978,24 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
TheCall->setType(ResourceTy);
break;
}
+ case Builtin::BI__builtin_hlsl_buffer_getdimensions: {
+ ASTContext &AST = SemaRef.getASTContext();
+ if (SemaRef.checkArgCount(TheCall, 2) ||
+ CheckResourceHandle(&SemaRef, TheCall, 0) ||
+ CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
+ CheckModifiableLValue(&SemaRef, TheCall, 1))
+ return true;
+ break;
+ }
+ case Builtin::BI__builtin_hlsl_buffer_getstride: {
+ ASTContext &AST = SemaRef.getASTContext();
+ if (SemaRef.checkArgCount(TheCall, 2) ||
+ CheckResourceHandle(&SemaRef, TheCall, 0) ||
+ CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
+ CheckModifiableLValue(&SemaRef, TheCall, 1))
+ return true;
+ break;
+ }
case Builtin::BI__builtin_hlsl_and:
case Builtin::BI__builtin_hlsl_or: {
if (SemaRef.checkArgCount(TheCall, 2))
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index 43d8ddee6ccad..a2058b29401c0 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -142,5 +142,19 @@ RESOURCE Buffer;
// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]'
// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+// GetDimensions method
+
+// CHECK-NEXT: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int &__restrict)'
+// CHECK-NEXT: ParmVarDecl {{.*}} dim 'unsigned int &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CallExpr {{.*}} 'void'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_getdimensions' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle {{.*}}
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'dim' 'unsigned int &__restrict'
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'const char8_t &(unsigned int) const'
// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'char8_t &(unsigned int)'
diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
index 6779abb10bec4..e5f4b22fe2a10 100644
--- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
@@ -334,6 +334,28 @@ RESOURCE<float> Buffer;
// CHECK-CONSUME-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-CONSUME-NEXT: IntegerLiteral {{.*}} 'int' -1
+// GetDimensions method
+
+// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int, unsigned int)'
+// CHECK-NEXT: ParmVarDecl {{.*}} numStructs 'unsigned int &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: ParmVarDecl {{.*}} stride 'unsigned int &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CallExpr {{.*}} 'void'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_getdimensions' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle {{.*}}
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'numStructs' 'unsigned int &__restrict'
+// CHECK-NEXT: CallExpr {{.*}} 'void'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_getstride' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle {{.*}}
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'stride' 'unsigned int &__restrict'
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
// CHECK: ClassTemplateSpecializationDecl {{.*}} class [[RESOURCE]] definition
// CHECK: TemplateArgument type 'float'
// CHECK-NEXT: BuiltinType {{.*}} 'float'
diff --git a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
index 5182ce194cfb0..07f04001a58ae 100644
--- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
@@ -214,6 +214,20 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+// GetDimensions method
+
+// CHECK-NEXT: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int)'
+// CHECK-NEXT: ParmVarDecl {{.*}} dim 'unsigned int &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CallExpr {{.*}} 'void'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_getdimensions' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle {{.*}}
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'dim' 'unsigned int &__restrict'
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
// CHECK: ClassTemplateSpecializationDecl {{.*}} class [[RESOURCE]] definition
// CHECK: TemplateArgument type 'float'
diff --git a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
new file mode 100644
index 0000000000000..f089c0cdf0ca3
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL
+// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -finclude-default-header -emit-llvm -disable-llvm-passes -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV
+
+// NOTE: SPIRV codegen for resource methods is not yet implemented
+
+ByteAddressBuffer Buf : register(t0);
+RWByteAddressBuffer RWBuf : register(u0);
+
+// DXIL: %"class.hlsl::ByteAddressBuffer" = type { target("dx.RawBuffer", i8, 0, 0) }
+// DXIL: %"class.hlsl::RWByteAddressBuffer" = type { target("dx.RawBuffer", i8, 1, 0) }
+
+// DXIL: @Buf = internal global %"class.hlsl::ByteAddressBuffer" poison
+// DXIL: @RWBuf = internal global %"class.hlsl::RWByteAddressBuffer" poison
+
+export uint TestGetDimensions() {
+ uint dim1, dim2;
+ Buf.GetDimensions(dim1);
+ RWBuf.GetDimensions(dim2);
+ return dim1 + dim2;
+}
+
+// CHECK: define {{.*}} @TestGetDimensions()()
+// CHECK: call void @hlsl::ByteAddressBuffer::GetDimensions(unsigned int&)(ptr {{.*}} @Buf, ptr{{.*}} %dim1)
+// CHECK: call void @hlsl::RWByteAddressBuffer::GetDimensions(unsigned int&)(ptr{{.*}} @RWBuf, ptr{{.*}} %dim2)
+// CHECK: add
+// CHECK: ret
+
+// CHECK: define {{.*}} void @hlsl::ByteAddressBuffer::GetDimensions(unsigned int&)(ptr {{.*}} %this, {{.*}} %dim)
+// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
+// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 0, 0), ptr %[[HANDLE_PTR]]
+// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr
+// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0) %[[HANDLE]], i32 poison)
+// DXIL-NEXT: %[[DIM:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0
+// CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]]
+// CHECK-NEXT: ret void
+
+// CHECK: define {{.*}} void @hlsl::RWByteAddressBuffer::GetDimensions(unsigned int&)(ptr {{.*}} %this, ptr noalias {{.*}} %dim)
+// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
+// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %[[HANDLE_PTR]]
+// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr
+// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]], i32 poison)
+// DXIL-NEXT: %[[DIM:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0
+// CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]]
+// CHECK-NEXT: ret void
+
+// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0), i32)
+// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0), i32)
diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl
index a506c2b50b1dc..c3bb147ad4a53 100644
--- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl
+++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl
@@ -82,7 +82,7 @@ export float TestLoad() {
return RWSB1.Load(1) + SB1.Load(2);
}
-// CHECK: define noundef nofpclass(nan inf) float @TestLoad()()
+// CHECK: define {{.*}} float @TestLoad()()
// CHECK: call {{.*}} float @hlsl::RWStructuredBuffer<float>::Load(unsigned int)(ptr {{.*}} @RWSB1, i32 noundef 1)
// CHECK: call {{.*}} float @hlsl::StructuredBuffer<float>::Load(unsigned int)(ptr {{.*}} @SB1, i32 noundef 2)
// CHECK: add
@@ -104,9 +104,60 @@ export float TestLoad() {
// CHECK-NEXT: %[[VAL:.*]] = load float, ptr %[[PTR]], align 4
// CHECK-NEXT: ret float %[[VAL]]
+export uint TestGetDimensions() {
+ uint dim1, dim2, dim3, stride1, stride2, stride3;
+ SB1.GetDimensions(dim1, stride1);
+ RWSB2.GetDimensions(dim2, stride2);
+ CSB.GetDimensions(dim3, stride3);
+ return dim1 + dim2 + dim3 + stride1 + stride2 + stride3;
+}
+// CHECK: define noundef i32 @TestGetDimensions()()
+// CHECK: call void @hlsl::StructuredBuffer<float>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @SB1, ptr {{.*}} %dim1, ptr {{.*}} %stride1)
+// CHECK: call void @hlsl::RWStructuredBuffer<unsigned int vector[4]>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @RWSB2, ptr {{.*}} %dim2, ptr {{.*}} %stride2)
+// CHECK: call void @hlsl::ConsumeStructuredBuffer<double>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @CSB, ptr {{.*}} %dim3, ptr {{.*}} %stride3)
+// CHECK: add
+// CHECK: ret
+
+// CHECK: define {{.*}} void @hlsl::StructuredBuffer<float>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}}, ptr {{.*}} %numStructs, ptr {{.*}} %stride)
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %{{.*}}, i32 0, i32 0
+// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 0, 0), ptr %__handle
+// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr
+// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0) %[[HANDLE]], i32 poison)
+// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0
+// CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]]
+// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr
+// CHECK-NEXT: store i32 4, ptr %[[STRIDEPTR]]
+// CHECK-NEXT: ret void
+
+// CHECK: define {{.*}} void @hlsl::RWStructuredBuffer<unsigned int vector[4]>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} %this, {{.*}} %numStructs, {{.*}} %stride)
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer.0", ptr %{{.*}}, i32 0, i32 0
+// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <4 x i32>, 1, 0), ptr %__handle
+// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr
+// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0) %[[HANDLE]], i32 poison)
+// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0
+// CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]]
+// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr
+// CHECK-NEXT: store i32 16, ptr %[[STRIDEPTR]]
+// CHECK-NEXT: ret void
+
+// CHECK: define {{.*}} void @hlsl::ConsumeStructuredBuffer<double>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} %this, {{.*}} %numStructs, {{.*}} %stride)
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ConsumeStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
+// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", double, 1, 0), ptr %__handle
+// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr
+// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0) %[[HANDLE]], i32 poison)
+// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0
+// CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]]
+// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr
+// CHECK-NEXT: store i32 8, ptr %[[STRIDEPTR]]
+// CHECK-NEXT: ret void
+
// DXIL: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i8)
// DXIL: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0), i8)
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i32)
// DXIL: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0), i8)
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0), i32)
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0), i32)
+
+// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0), i32)
+// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0), i32)
+// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0), i32)
diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl
index af312f9a815b8..413f402f87c97 100644
--- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl
+++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl
@@ -65,7 +65,44 @@ export float TestLoad() {
// CHECK-NEXT: %[[VAL:.*]] = load <2 x i32>, ptr %[[BUFPTR]]
// CHECK-NEXT: ret <2 x i32> %[[VAL]]
+export uint TestGetDimensions() {
+ uint dim1, dim2, stride1, stride2;
+ ROSB1.GetDimensions(dim1, stride1);
+ ROSB2.GetDimensions(dim2, stride2);
+ return dim1 + dim2 + stride1 + stride2;
+}
+// CHECK: define noundef i32 @TestGetDimensions()()
+// CHECK: call void @hlsl::RasterizerOrderedStructuredBuffer<float>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @ROSB1, ptr {{.*}} %dim1, ptr {{.*}} %stride1)
+// CHECK: call void @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @ROSB2, ptr {{.*}} %dim2, ptr {{.*}} %stride2)
+// CHECK: add
+// CHECK: ret
+
+// CHECK: define {{.*}} void @hlsl::RasterizerOrderedStructuredBuffer<float>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}}, ptr {{.*}} %numStructs, ptr {{.*}} %stride)
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
+// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 1), ptr %__handle
+// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr
+// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %[[HANDLE]], i32 poison)
+// DXIL-NEXT: %[[AAA:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0
+// CHECK-NEXT: store i32 %[[AAA]], ptr %[[NUMSTRUCTS_PTR]]
+// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr
+// CHECK-NEXT: store i32 4, ptr %[[STRIDEPTR]]
+// CHECK-NEXT: ret void
+
+// CHECK: define {{.*}} void @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}}, ptr {{.*}} %numStructs, ptr {{.*}} %stride)
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer.0", ptr %{{.*}}, i32 0, i32 0
+// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <2 x i32>, 1, 1), ptr %__handle
+// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr
+// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1) %[[HANDLE]], i32 poison)
+// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0
+// CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]]
+// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr
+// CHECK-NEXT: store i32 8, ptr %[[STRIDEPTR]]
+// CHECK-NEXT: ret void
+
// DXIL: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i8)
// DXIL: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1), i8)
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i32)
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1), i32)
+
+// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i32)
+// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1), i32)
diff --git a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl
index b153bda167a35..b23c8360d244c 100644
--- a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl
+++ b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl
@@ -38,5 +38,39 @@ export float TestLoad() {
// CHECK-NEXT: %[[VEC:.*]] = load <4 x i32>, ptr %[[PTR]]
// CHECK-NEXT: ret <4 x i32> %[[VEC]]
+export uint TestGetDimensions() {
+ uint dim1, dim2;
+ Buf.GetDimensions(dim1);
+ RWBuf.GetDimensions(dim2);
+ return dim1 + dim2;
+}
+
+// CHECK: @TestGetDimensions()()
+// CHECK: call void @hlsl::Buffer<float>::GetDimensions(unsigned int&)(ptr {{.*}} @Buf, ptr {{.*}} %dim1)
+// CHECK: call void @hlsl::RWBuffer<unsigned int vector[4]>::GetDimensions(unsigned int&)(ptr {{.*}} @RWBuf, ptr {{.*}} %dim2)
+// CHECK: add
+// CHECK: ret
+
+// CHECK: define {{.*}} void @hlsl::Buffer<float>::GetDimensions(unsigned int&)(ptr {{.*}} %this, ptr noalias {{.*}} %dim)
+// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::Buffer", ptr %this1, i32 0, i32 0
+// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", float, 0, 0, 0), ptr %[[HANDLE_PTR]]
+// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr
+// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0) %[[HANDLE]], i32 poison)
+// DXIL-NEXT: %[[DIM:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0
+// CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]]
+// CHECK-NEXT: ret void
+
+// CHECK: define {{.*}} void @hlsl::RWBuffer<unsigned int vector[4]>::GetDimensions(unsigned int&)(ptr {{.*}} %this, {{.*}} %dim)
+// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %{{.*}}, i32 0, i32 0
+// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), ptr %[[HANDLE_PTR]]
+// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr
+// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0) %[[HANDLE]], i32 poison)
+// DXIL-NEXT: %[[DIM:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0
+// CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]]
+// CHECK-NEXT: ret void
+
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0), i32)
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), i32)
+
+// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0), i32)
+// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), i32)
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index 570d6bc35cbd0..38cd3f3e07a87 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -77,6 +77,10 @@ def int_dx_resource_updatecounter
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_i8_ty],
[IntrInaccessibleMemOrArgMemOnly]>;
+def int_dx_resource_getdimensions
+ : DefaultAttrsIntrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [llvm_any_ty, llvm_i32_ty],
+ [IntrReadMem]>;
+
// Cast between target extension handle types and dxil-style opaque handles
def int_dx_resource_casthandle : Intrinsic<[llvm_any_ty], [llvm_any_ty]>;
>From 2fd9c3a7a5e46fce4a740de3b9aba03ce122f975 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Wed, 8 Oct 2025 22:41:36 -0700
Subject: [PATCH 2/3] Change to buffer-specific LLVM intrinsic
---
clang/lib/CodeGen/CGHLSLBuiltins.cpp | 48 ++-----------------
clang/lib/CodeGen/CGHLSLRuntime.h | 2 +
.../resources/ByteAddressBuffers-methods.hlsl | 10 ++--
.../StructuredBuffers-methods-lib.hlsl | 15 +++---
.../StructuredBuffers-methods-ps.hlsl | 12 ++---
.../resources/TypedBuffers-methods.hlsl | 10 ++--
llvm/include/llvm/IR/IntrinsicsDirectX.td | 5 +-
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 3 ++
8 files changed, 31 insertions(+), 74 deletions(-)
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 373153e01c128..85d554d2ef158 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -160,48 +160,6 @@ static Value *handleHlslSplitdouble(const CallExpr *E, CodeGenFunction *CGF) {
return LastInst;
}
-static Value *emitDXILGetDimensions(CodeGenFunction *CGF, Value *Handle,
- Value *MipLevel, LValue *OutArg0,
- LValue *OutArg1 = nullptr,
- LValue *OutArg2 = nullptr,
- LValue *OutArg3 = nullptr) {
- assert(OutArg0 && "first output argument is required");
-
- llvm::Type *I32 = CGF->Int32Ty;
- StructType *RetTy = llvm::StructType::get(I32, I32, I32, I32);
-
- CallInst *CI = CGF->Builder.CreateIntrinsic(
- RetTy, llvm::Intrinsic::dx_resource_getdimensions,
- ArrayRef<Value *>{Handle, MipLevel});
-
- Value *LastInst = nullptr;
- unsigned OutArgIndex = 0;
- for (LValue *OutArg : {OutArg0, OutArg1, OutArg2, OutArg3}) {
- if (OutArg) {
- Value *OutArgVal = CGF->Builder.CreateExtractValue(CI, OutArgIndex);
- LastInst = CGF->Builder.CreateStore(OutArgVal, OutArg->getAddress());
- }
- ++OutArgIndex;
- }
- assert(LastInst && "no output argument stored?");
- return LastInst;
-}
-
-static Value *emitBufferGetDimensions(CodeGenFunction *CGF, Value *Handle,
- LValue &Dim) {
- // Generate the call to get the buffer dimension.
- switch (CGF->CGM.getTarget().getTriple().getArch()) {
- case llvm::Triple::dxil:
- return emitDXILGetDimensions(CGF, Handle, PoisonValue::get(CGF->Int32Ty),
- &Dim);
- break;
- case llvm::Triple::spirv:
- llvm_unreachable("SPIR-V GetDimensions codegen not implemented yet.");
- default:
- llvm_unreachable("GetDimensions not supported by target architecture");
- }
-}
-
static Value *emitBufferStride(CodeGenFunction *CGF, const Expr *HandleExpr,
LValue &Stride) {
// Figure out the stride of the buffer elements from the handle type.
@@ -414,7 +372,11 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
case Builtin::BI__builtin_hlsl_buffer_getdimensions: {
Value *Handle = EmitScalarExpr(E->getArg(0));
LValue Dim = EmitLValue(E->getArg(1));
- return emitBufferGetDimensions(this, Handle, Dim);
+ llvm::Type *RetTy = llvm::Type::getInt32Ty(getLLVMContext());
+ Value *DimValue = Builder.CreateIntrinsic(
+ RetTy, CGM.getHLSLRuntime().getGetDimensionsBufferIntrinsic(),
+ ArrayRef<Value *>{Handle});
+ return Builder.CreateStore(DimValue, Dim.getAddress());
}
case Builtin::BI__builtin_hlsl_buffer_getstride: {
LValue Stride = EmitLValue(E->getArg(1));
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index 7c6c2850fd4d4..5fd87d0b9a53c 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -135,6 +135,8 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(BufferUpdateCounter, resource_updatecounter)
GENERATE_HLSL_INTRINSIC_FUNCTION(GroupMemoryBarrierWithGroupSync,
group_memory_barrier_with_group_sync)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(GetDimensionsBuffer,
+ resource_getdimensions_buffer)
//===----------------------------------------------------------------------===//
// End of reserved area for HLSL intrinsic getters.
diff --git a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
index f089c0cdf0ca3..4e4d882057d48 100644
--- a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
+++ b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
@@ -29,8 +29,7 @@ export uint TestGetDimensions() {
// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 0, 0), ptr %[[HANDLE_PTR]]
// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr
-// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0) %[[HANDLE]], i32 poison)
-// DXIL-NEXT: %[[DIM:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0
+// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0) %[[HANDLE]])
// CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]]
// CHECK-NEXT: ret void
@@ -38,10 +37,9 @@ export uint TestGetDimensions() {
// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %[[HANDLE_PTR]]
// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr
-// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]], i32 poison)
-// DXIL-NEXT: %[[DIM:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0
+// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]])
// CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]]
// CHECK-NEXT: ret void
-// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0), i32)
-// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0), i32)
+// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0))
+// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0))
diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl
index c3bb147ad4a53..6197cc5cd0a19 100644
--- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl
+++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl
@@ -122,8 +122,7 @@ export uint TestGetDimensions() {
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %{{.*}}, i32 0, i32 0
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 0, 0), ptr %__handle
// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr
-// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0) %[[HANDLE]], i32 poison)
-// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0
+// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0) %[[HANDLE]])
// CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]]
// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr
// CHECK-NEXT: store i32 4, ptr %[[STRIDEPTR]]
@@ -133,8 +132,7 @@ export uint TestGetDimensions() {
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer.0", ptr %{{.*}}, i32 0, i32 0
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <4 x i32>, 1, 0), ptr %__handle
// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr
-// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0) %[[HANDLE]], i32 poison)
-// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0
+// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0) %[[HANDLE]])
// CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]]
// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr
// CHECK-NEXT: store i32 16, ptr %[[STRIDEPTR]]
@@ -144,8 +142,7 @@ export uint TestGetDimensions() {
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ConsumeStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", double, 1, 0), ptr %__handle
// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr
-// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0) %[[HANDLE]], i32 poison)
-// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0
+// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0) %[[HANDLE]])
// CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]]
// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr
// CHECK-NEXT: store i32 8, ptr %[[STRIDEPTR]]
@@ -158,6 +155,6 @@ export uint TestGetDimensions() {
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0), i32)
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0), i32)
-// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0), i32)
-// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0), i32)
-// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0), i32)
+// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0))
+// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0))
+// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0))
diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl
index 413f402f87c97..652446ba805da 100644
--- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl
+++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl
@@ -81,9 +81,8 @@ export uint TestGetDimensions() {
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 1), ptr %__handle
// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr
-// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %[[HANDLE]], i32 poison)
-// DXIL-NEXT: %[[AAA:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0
-// CHECK-NEXT: store i32 %[[AAA]], ptr %[[NUMSTRUCTS_PTR]]
+// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %[[HANDLE]])
+// CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]]
// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr
// CHECK-NEXT: store i32 4, ptr %[[STRIDEPTR]]
// CHECK-NEXT: ret void
@@ -92,8 +91,7 @@ export uint TestGetDimensions() {
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer.0", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <2 x i32>, 1, 1), ptr %__handle
// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr
-// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1) %[[HANDLE]], i32 poison)
-// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0
+// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1) %[[HANDLE]])
// CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]]
// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr
// CHECK-NEXT: store i32 8, ptr %[[STRIDEPTR]]
@@ -104,5 +102,5 @@ export uint TestGetDimensions() {
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i32)
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1), i32)
-// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i32)
-// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1), i32)
+// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1))
+// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1))
diff --git a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl
index b23c8360d244c..d3f7e19583906 100644
--- a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl
+++ b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl
@@ -55,8 +55,7 @@ export uint TestGetDimensions() {
// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::Buffer", ptr %this1, i32 0, i32 0
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", float, 0, 0, 0), ptr %[[HANDLE_PTR]]
// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr
-// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0) %[[HANDLE]], i32 poison)
-// DXIL-NEXT: %[[DIM:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0
+// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0) %[[HANDLE]])
// CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]]
// CHECK-NEXT: ret void
@@ -64,13 +63,12 @@ export uint TestGetDimensions() {
// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %{{.*}}, i32 0, i32 0
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), ptr %[[HANDLE_PTR]]
// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr
-// DXIL-NEXT: %[[FOURVAL:.*]] = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0) %[[HANDLE]], i32 poison)
-// DXIL-NEXT: %[[DIM:.*]] = extractvalue { i32, i32, i32, i32 } %[[FOURVAL]], 0
+// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0) %[[HANDLE]])
// CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]]
// CHECK-NEXT: ret void
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0), i32)
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), i32)
-// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0), i32)
-// DXIL: declare { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), i32)
+// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0))
+// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0))
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index 38cd3f3e07a87..855f2e522ba6b 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -77,9 +77,8 @@ def int_dx_resource_updatecounter
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_i8_ty],
[IntrInaccessibleMemOrArgMemOnly]>;
-def int_dx_resource_getdimensions
- : DefaultAttrsIntrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [llvm_any_ty, llvm_i32_ty],
- [IntrReadMem]>;
+def int_dx_resource_getdimensions_buffer
+ : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty], [IntrReadMem]>;
// Cast between target extension handle types and dxil-style opaque handles
def int_dx_resource_casthandle : Intrinsic<[llvm_any_ty], [llvm_any_ty]>;
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index 823c491e1bfee..c1476a0142c86 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -159,6 +159,9 @@ def int_spv_rsqrt : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty]
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_i8_ty],
[IntrInaccessibleMemOrArgMemOnly]>;
+ def int_spv_resource_getdimensions_buffer
+ : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty], [IntrReadMem]>;
+
def int_spv_resource_getpointer
: DefaultAttrsIntrinsic<[llvm_anyptr_ty], [llvm_any_ty, llvm_i32_ty],
[IntrNoMem]>;
>From 135a858b473ce823de26271de896bff7fcec403a Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Thu, 9 Oct 2025 14:04:40 -0700
Subject: [PATCH 3/3] Update builtins and intrinsic to
*resource_getdimensions_x and *_resource_getstride
---
clang/include/clang/Basic/Builtins.td | 6 +++---
clang/lib/CodeGen/CGHLSLBuiltins.cpp | 6 +++---
clang/lib/CodeGen/CGHLSLRuntime.h | 3 +--
clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 8 ++++----
clang/lib/Sema/SemaHLSL.cpp | 4 ++--
clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl | 2 +-
clang/test/AST/HLSL/StructuredBuffers-AST.hlsl | 4 ++--
clang/test/AST/HLSL/TypedBuffers-AST.hlsl | 2 +-
.../resources/ByteAddressBuffers-methods.hlsl | 8 ++++----
.../resources/StructuredBuffers-methods-lib.hlsl | 12 ++++++------
.../resources/StructuredBuffers-methods-ps.hlsl | 8 ++++----
.../CodeGenHLSL/resources/TypedBuffers-methods.hlsl | 8 ++++----
llvm/include/llvm/IR/IntrinsicsDirectX.td | 2 +-
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 +-
14 files changed, 37 insertions(+), 38 deletions(-)
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 0b1587be51217..90e549eda1aa2 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4951,14 +4951,14 @@ def HLSLResourceNonUniformIndex : LangBuiltin<"HLSL_LANG"> {
let Prototype = "uint32_t(uint32_t)";
}
-def HLSLResourceGetDimensions : LangBuiltin<"HLSL_LANG"> {
- let Spellings = ["__builtin_hlsl_buffer_getdimensions"];
+def HLSLResourceGetDimensionsX : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_resource_getdimensions_x"];
let Attributes = [NoThrow];
let Prototype = "void(...)";
}
def HLSLResourceGetStride : LangBuiltin<"HLSL_LANG"> {
- let Spellings = ["__builtin_hlsl_buffer_getstride"];
+ let Spellings = ["__builtin_hlsl_resource_getstride"];
let Attributes = [NoThrow];
let Prototype = "void(...)";
}
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 85d554d2ef158..11c6231704ebb 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -369,16 +369,16 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
RetTy, CGM.getHLSLRuntime().getNonUniformResourceIndexIntrinsic(),
ArrayRef<Value *>{IndexOp});
}
- case Builtin::BI__builtin_hlsl_buffer_getdimensions: {
+ case Builtin::BI__builtin_hlsl_resource_getdimensions_x: {
Value *Handle = EmitScalarExpr(E->getArg(0));
LValue Dim = EmitLValue(E->getArg(1));
llvm::Type *RetTy = llvm::Type::getInt32Ty(getLLVMContext());
Value *DimValue = Builder.CreateIntrinsic(
- RetTy, CGM.getHLSLRuntime().getGetDimensionsBufferIntrinsic(),
+ RetTy, CGM.getHLSLRuntime().getGetDimensionsXIntrinsic(),
ArrayRef<Value *>{Handle});
return Builder.CreateStore(DimValue, Dim.getAddress());
}
- case Builtin::BI__builtin_hlsl_buffer_getstride: {
+ case Builtin::BI__builtin_hlsl_resource_getstride: {
LValue Stride = EmitLValue(E->getArg(1));
return emitBufferStride(this, E->getArg(0), Stride);
}
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index 5fd87d0b9a53c..103b4a98f6c26 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -135,8 +135,7 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(BufferUpdateCounter, resource_updatecounter)
GENERATE_HLSL_INTRINSIC_FUNCTION(GroupMemoryBarrierWithGroupSync,
group_memory_barrier_with_group_sync)
- GENERATE_HLSL_INTRINSIC_FUNCTION(GetDimensionsBuffer,
- resource_getdimensions_buffer)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(GetDimensionsX, resource_getdimensions_x)
//===----------------------------------------------------------------------===//
// End of reserved area for HLSL intrinsic getters.
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index d6d6b31aa2d9d..38edba36633d4 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -1186,10 +1186,10 @@ BuiltinTypeDeclBuilder::addGetDimensionsMethodForBuffer() {
return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
.addParam("numStructs", UIntTy, HLSLParamModifierAttr::Keyword_out)
.addParam("stride", UIntTy, HLSLParamModifierAttr::Keyword_out)
- .callBuiltin("__builtin_hlsl_buffer_getdimensions", QualType(),
+ .callBuiltin("__builtin_hlsl_resource_getdimensions_x", QualType(),
PH::Handle, PH::_0)
- .callBuiltin("__builtin_hlsl_buffer_getstride", QualType(), PH::Handle,
- PH::_1)
+ .callBuiltin("__builtin_hlsl_resource_getstride", QualType(),
+ PH::Handle, PH::_1)
.finalize();
}
@@ -1197,7 +1197,7 @@ BuiltinTypeDeclBuilder::addGetDimensionsMethodForBuffer() {
// GetDimensions(out uint dim).
return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
.addParam("dim", UIntTy, HLSLParamModifierAttr::Keyword_out)
- .callBuiltin("__builtin_hlsl_buffer_getdimensions", QualType(),
+ .callBuiltin("__builtin_hlsl_resource_getdimensions_x", QualType(),
PH::Handle, PH::_0)
.finalize();
}
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index e3281c493da50..4c0981d78ab65 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -2978,7 +2978,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
TheCall->setType(ResourceTy);
break;
}
- case Builtin::BI__builtin_hlsl_buffer_getdimensions: {
+ case Builtin::BI__builtin_hlsl_resource_getdimensions_x: {
ASTContext &AST = SemaRef.getASTContext();
if (SemaRef.checkArgCount(TheCall, 2) ||
CheckResourceHandle(&SemaRef, TheCall, 0) ||
@@ -2987,7 +2987,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return true;
break;
}
- case Builtin::BI__builtin_hlsl_buffer_getstride: {
+ case Builtin::BI__builtin_hlsl_resource_getstride: {
ASTContext &AST = SemaRef.getASTContext();
if (SemaRef.checkArgCount(TheCall, 2) ||
CheckResourceHandle(&SemaRef, TheCall, 0) ||
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index a2058b29401c0..9ecd6dbb6456f 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -150,7 +150,7 @@ RESOURCE Buffer;
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: CallExpr {{.*}} 'void'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_getdimensions' 'void (...) noexcept'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getdimensions_x' 'void (...) noexcept'
// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle {{.*}}
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'dim' 'unsigned int &__restrict'
diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
index e5f4b22fe2a10..7cfb4126824c0 100644
--- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
@@ -344,13 +344,13 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: CallExpr {{.*}} 'void'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_getdimensions' 'void (...) noexcept'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getdimensions_x' 'void (...) noexcept'
// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle {{.*}}
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'numStructs' 'unsigned int &__restrict'
// CHECK-NEXT: CallExpr {{.*}} 'void'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_getstride' 'void (...) noexcept'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getstride' 'void (...) noexcept'
// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle {{.*}}
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'stride' 'unsigned int &__restrict'
diff --git a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
index 07f04001a58ae..44a866397f68b 100644
--- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
@@ -222,7 +222,7 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: CallExpr {{.*}} 'void'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
-// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_getdimensions' 'void (...) noexcept'
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_resource_getdimensions_x' 'void (...) noexcept'
// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle {{.*}}
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'dim' 'unsigned int &__restrict'
diff --git a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
index 4e4d882057d48..2b235da4ba6c7 100644
--- a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
+++ b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl
@@ -29,7 +29,7 @@ export uint TestGetDimensions() {
// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 0, 0), ptr %[[HANDLE_PTR]]
// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr
-// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0) %[[HANDLE]])
+// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0) %[[HANDLE]])
// CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]]
// CHECK-NEXT: ret void
@@ -37,9 +37,9 @@ export uint TestGetDimensions() {
// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %[[HANDLE_PTR]]
// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr
-// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]])
+// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]])
// CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]]
// CHECK-NEXT: ret void
-// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0))
-// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0))
+// DXIL: declare i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0))
+// DXIL: declare i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0))
diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl
index 6197cc5cd0a19..a98d2bbdca6f4 100644
--- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl
+++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl
@@ -122,7 +122,7 @@ export uint TestGetDimensions() {
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %{{.*}}, i32 0, i32 0
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 0, 0), ptr %__handle
// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr
-// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0) %[[HANDLE]])
+// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0) %[[HANDLE]])
// CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]]
// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr
// CHECK-NEXT: store i32 4, ptr %[[STRIDEPTR]]
@@ -132,7 +132,7 @@ export uint TestGetDimensions() {
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer.0", ptr %{{.*}}, i32 0, i32 0
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <4 x i32>, 1, 0), ptr %__handle
// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr
-// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0) %[[HANDLE]])
+// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0) %[[HANDLE]])
// CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]]
// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr
// CHECK-NEXT: store i32 16, ptr %[[STRIDEPTR]]
@@ -142,7 +142,7 @@ export uint TestGetDimensions() {
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ConsumeStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", double, 1, 0), ptr %__handle
// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr
-// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0) %[[HANDLE]])
+// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0) %[[HANDLE]])
// CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]]
// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr
// CHECK-NEXT: store i32 8, ptr %[[STRIDEPTR]]
@@ -155,6 +155,6 @@ export uint TestGetDimensions() {
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0), i32)
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0), i32)
-// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0))
-// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0))
-// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0))
+// DXIL: declare i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0))
+// DXIL: declare i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0))
+// DXIL: declare i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0))
diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl
index 652446ba805da..dfc7ddb41731d 100644
--- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl
+++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl
@@ -81,7 +81,7 @@ export uint TestGetDimensions() {
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 1), ptr %__handle
// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr
-// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %[[HANDLE]])
+// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %[[HANDLE]])
// CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]]
// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr
// CHECK-NEXT: store i32 4, ptr %[[STRIDEPTR]]
@@ -91,7 +91,7 @@ export uint TestGetDimensions() {
// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer.0", ptr %{{.*}}, i32 0, i32 0
// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <2 x i32>, 1, 1), ptr %__handle
// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr
-// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1) %[[HANDLE]])
+// DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1) %[[HANDLE]])
// CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]]
// CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr
// CHECK-NEXT: store i32 8, ptr %[[STRIDEPTR]]
@@ -102,5 +102,5 @@ export uint TestGetDimensions() {
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i32)
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1), i32)
-// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1))
-// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1))
+// DXIL: declare i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1))
+// DXIL: declare i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1))
diff --git a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl
index d3f7e19583906..3df904ba8421c 100644
--- a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl
+++ b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl
@@ -55,7 +55,7 @@ export uint TestGetDimensions() {
// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::Buffer", ptr %this1, i32 0, i32 0
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", float, 0, 0, 0), ptr %[[HANDLE_PTR]]
// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr
-// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0) %[[HANDLE]])
+// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0) %[[HANDLE]])
// CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]]
// CHECK-NEXT: ret void
@@ -63,12 +63,12 @@ export uint TestGetDimensions() {
// CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %{{.*}}, i32 0, i32 0
// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), ptr %[[HANDLE_PTR]]
// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr
-// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.buffer.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0) %[[HANDLE]])
+// DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0) %[[HANDLE]])
// CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]]
// CHECK-NEXT: ret void
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0), i32)
// DXIL: declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), i32)
-// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0))
-// DXIL: declare i32 @llvm.dx.resource.getdimensions.buffer.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0))
+// DXIL: declare i32 @llvm.dx.resource.getdimensions.x.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0))
+// DXIL: declare i32 @llvm.dx.resource.getdimensions.x.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0))
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index 855f2e522ba6b..3b7077c52db21 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -77,7 +77,7 @@ def int_dx_resource_updatecounter
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_i8_ty],
[IntrInaccessibleMemOrArgMemOnly]>;
-def int_dx_resource_getdimensions_buffer
+def int_dx_resource_getdimensions_x
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty], [IntrReadMem]>;
// Cast between target extension handle types and dxil-style opaque handles
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index c1476a0142c86..7b27b46668ea9 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -159,7 +159,7 @@ def int_spv_rsqrt : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty]
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_i8_ty],
[IntrInaccessibleMemOrArgMemOnly]>;
- def int_spv_resource_getdimensions_buffer
+ def int_spv_resource_getdimensions_x
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty], [IntrReadMem]>;
def int_spv_resource_getpointer
More information about the llvm-branch-commits
mailing list