Skip to content

Commit 54ed459

Browse files
authored
[HLSL] Add copy assignment and construtor to resource types (#156075)
The wrapper used to hold the handle for resource type has just the default copy constructor and assignment operator. This causes clang to insert memcpys when it does an assignment of a resource type. The memcpy then cause optimizations to fail when the memcpy is turned into a load and store of an i64. To fix this, we should define copying of a resource type by adding the operator= and copy constructor. Partially fixes #154669
1 parent 6c0154f commit 54ed459

13 files changed

+199
-31
lines changed

clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ struct BuiltinTypeMethodBuilder {
156156
BuiltinTypeDeclBuilder &finalize();
157157
Expr *getResourceHandleExpr();
158158

159+
template <typename T>
160+
BuiltinTypeMethodBuilder &getResourceHandle(T ResourceRecord);
161+
BuiltinTypeMethodBuilder &returnThis();
162+
159163
private:
160164
void createDecl();
161165

@@ -332,7 +336,7 @@ Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
332336
return DeclRefExpr::Create(
333337
AST, NestedNameSpecifierLoc(), SourceLocation(), ParamDecl, false,
334338
DeclarationNameInfo(ParamDecl->getDeclName(), SourceLocation()),
335-
ParamDecl->getType(), VK_PRValue);
339+
ParamDecl->getType().getNonReferenceType(), VK_PRValue);
336340
}
337341

338342
BuiltinTypeMethodBuilder::BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB,
@@ -431,6 +435,31 @@ Expr *BuiltinTypeMethodBuilder::getResourceHandleExpr() {
431435
OK_Ordinary);
432436
}
433437

438+
template <typename T>
439+
BuiltinTypeMethodBuilder &
440+
BuiltinTypeMethodBuilder::getResourceHandle(T ResourceRecord) {
441+
ensureCompleteDecl();
442+
443+
Expr *ResourceExpr = convertPlaceholder(ResourceRecord);
444+
445+
ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
446+
FieldDecl *HandleField = DeclBuilder.getResourceHandleField();
447+
MemberExpr *HandleExpr = MemberExpr::CreateImplicit(
448+
AST, ResourceExpr, /*IsArrow=*/false, HandleField, HandleField->getType(),
449+
VK_LValue, OK_Ordinary);
450+
StmtsList.push_back(HandleExpr);
451+
return *this;
452+
}
453+
454+
BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::returnThis() {
455+
ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
456+
CXXThisExpr *ThisExpr = CXXThisExpr::Create(
457+
AST, SourceLocation(), Method->getFunctionObjectParameterType(),
458+
/*IsImplicit=*/true);
459+
StmtsList.push_back(ThisExpr);
460+
return *this;
461+
}
462+
434463
template <typename... Ts>
435464
BuiltinTypeMethodBuilder &
436465
BuiltinTypeMethodBuilder::callBuiltin(StringRef BuiltinName,
@@ -676,6 +705,45 @@ BuiltinTypeDeclBuilder::addHandleConstructorFromImplicitBinding() {
676705
.finalize();
677706
}
678707

708+
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyConstructor() {
709+
if (Record->isCompleteDefinition())
710+
return *this;
711+
712+
ASTContext &AST = SemaRef.getASTContext();
713+
QualType RecordType = AST.getCanonicalTagType(Record);
714+
QualType ConstRecordType = RecordType.withConst();
715+
QualType ConstRecordRefType = AST.getLValueReferenceType(ConstRecordType);
716+
717+
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
718+
719+
return BuiltinTypeMethodBuilder(*this, /*Name=*/"", AST.VoidTy,
720+
/*IsConst=*/false, /*IsCtor=*/true)
721+
.addParam("other", ConstRecordRefType)
722+
.getResourceHandle(PH::_0)
723+
.assign(PH::Handle, PH::LastStmt)
724+
.finalize();
725+
}
726+
727+
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addCopyAssignmentOperator() {
728+
if (Record->isCompleteDefinition())
729+
return *this;
730+
731+
ASTContext &AST = SemaRef.getASTContext();
732+
QualType RecordType = AST.getCanonicalTagType(Record);
733+
QualType ConstRecordType = RecordType.withConst();
734+
QualType ConstRecordRefType = AST.getLValueReferenceType(ConstRecordType);
735+
QualType RecordRefType = AST.getLValueReferenceType(RecordType);
736+
737+
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
738+
DeclarationName Name = AST.DeclarationNames.getCXXOperatorName(OO_Equal);
739+
return BuiltinTypeMethodBuilder(*this, Name, RecordRefType)
740+
.addParam("other", ConstRecordRefType)
741+
.getResourceHandle(PH::_0)
742+
.assign(PH::Handle, PH::LastStmt)
743+
.returnThis()
744+
.finalize();
745+
}
746+
679747
BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addArraySubscriptOperators() {
680748
ASTContext &AST = Record->getASTContext();
681749
DeclarationName Subscript =

clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ class BuiltinTypeDeclBuilder {
8080
BuiltinTypeDeclBuilder &addDefaultHandleConstructor();
8181
BuiltinTypeDeclBuilder &addHandleConstructorFromBinding();
8282
BuiltinTypeDeclBuilder &addHandleConstructorFromImplicitBinding();
83+
BuiltinTypeDeclBuilder &addCopyConstructor();
84+
BuiltinTypeDeclBuilder &addCopyAssignmentOperator();
8385

8486
// Builtin types methods
8587
BuiltinTypeDeclBuilder &addLoadMethods();

clang/lib/Sema/HLSLExternalSemaSource.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
132132
return BuiltinTypeDeclBuilder(S, Decl)
133133
.addHandleMember(RC, IsROV, RawBuffer)
134134
.addDefaultHandleConstructor()
135+
.addCopyConstructor()
136+
.addCopyAssignmentOperator()
135137
.addHandleConstructorFromBinding()
136138
.addHandleConstructorFromImplicitBinding();
137139
}

clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,32 @@ RESOURCE Buffer;
5656
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
5757
// CHECK-NEXT: AlwaysInlineAttr
5858

59+
// Copy constructor
60+
61+
// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]] 'void (const hlsl::[[RESOURCE]] &)' inline
62+
// CHECK-NEXT: ParmVarDecl {{.*}} other 'const hlsl::[[RESOURCE]] &'
63+
// CHECK-NEXT: CompoundStmt
64+
// CHECK-NEXT: BinaryOperator {{.*}} '='
65+
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
66+
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
67+
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
68+
// CHECK-NEXT: DeclRefExpr {{.*}} 'const hlsl::[[RESOURCE]]' ParmVar {{.*}} 'other' 'const hlsl::[[RESOURCE]] &'
69+
// CHECK-NEXT: AlwaysInlineAttr
70+
71+
// operator=
72+
73+
// CHECK: CXXMethodDecl {{.*}} operator= 'hlsl::[[RESOURCE]] &(const hlsl::[[RESOURCE]] &)'
74+
// CHECK-NEXT: ParmVarDecl {{.*}} other 'const hlsl::[[RESOURCE]] &'
75+
// CHECK-NEXT: CompoundStmt
76+
// CHECK-NEXT: BinaryOperator {{.*}} '='
77+
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
78+
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
79+
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
80+
// CHECK-NEXT: DeclRefExpr {{.*}} 'const hlsl::[[RESOURCE]]' ParmVar {{.*}} 'other' 'const hlsl::[[RESOURCE]] &'
81+
// CHECK-NEXT: ReturnStmt
82+
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
83+
// CHECK-NEXT: AlwaysInlineAttr
84+
5985
// Constructor from binding
6086

6187
// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]] 'void (unsigned int, unsigned int, int, unsigned int, const char *)' inline

clang/test/AST/HLSL/StructuredBuffers-AST.hlsl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,32 @@ RESOURCE<float> Buffer;
103103
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
104104
// CHECK-NEXT: AlwaysInlineAttr
105105

106+
// Copy constructor
107+
108+
// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]]<element_type> 'void (const hlsl::[[RESOURCE]]<element_type> &)' inline
109+
// CHECK-NEXT: ParmVarDecl {{.*}} other 'const hlsl::[[RESOURCE]]<element_type> &'
110+
// CHECK-NEXT: CompoundStmt
111+
// CHECK-NEXT: BinaryOperator {{.*}} '='
112+
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
113+
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
114+
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
115+
// CHECK-NEXT: DeclRefExpr {{.*}} 'const hlsl::[[RESOURCE]]<element_type>' ParmVar {{.*}} 'other' 'const hlsl::[[RESOURCE]]<element_type> &'
116+
// CHECK-NEXT: AlwaysInlineAttr
117+
118+
// operator=
119+
120+
// CHECK: CXXMethodDecl {{.*}} operator= 'hlsl::[[RESOURCE]]<element_type> &(const hlsl::[[RESOURCE]]<element_type> &)'
121+
// CHECK-NEXT: ParmVarDecl {{.*}} other 'const hlsl::[[RESOURCE]]<element_type> &'
122+
// CHECK-NEXT: CompoundStmt
123+
// CHECK-NEXT: BinaryOperator {{.*}} '='
124+
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
125+
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
126+
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
127+
// CHECK-NEXT: DeclRefExpr {{.*}} 'const hlsl::[[RESOURCE]]<element_type>' ParmVar {{.*}} 'other' 'const hlsl::[[RESOURCE]]<element_type> &'
128+
// CHECK-NEXT: ReturnStmt
129+
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
130+
// CHECK-NEXT: AlwaysInlineAttr
131+
106132
// Constructor from binding
107133

108134
// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]]<element_type> 'void (unsigned int, unsigned int, int, unsigned int, const char *)' inline

clang/test/AST/HLSL/TypedBuffers-AST.hlsl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,32 @@ RESOURCE<float> Buffer;
7878
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
7979
// CHECK-NEXT: AlwaysInlineAttr
8080

81+
// Copy constructor
82+
83+
// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]]<element_type> 'void (const hlsl::[[RESOURCE]]<element_type> &)' inline
84+
// CHECK-NEXT: ParmVarDecl {{.*}} other 'const hlsl::[[RESOURCE]]<element_type> &'
85+
// CHECK-NEXT: CompoundStmt
86+
// CHECK-NEXT: BinaryOperator {{.*}} '='
87+
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
88+
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
89+
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
90+
// CHECK-NEXT: DeclRefExpr {{.*}} 'const hlsl::[[RESOURCE]]<element_type>' ParmVar {{.*}} 'other' 'const hlsl::[[RESOURCE]]<element_type> &'
91+
// CHECK-NEXT: AlwaysInlineAttr
92+
93+
// operator=
94+
95+
// CHECK: CXXMethodDecl {{.*}} operator= 'hlsl::[[RESOURCE]]<element_type> &(const hlsl::[[RESOURCE]]<element_type> &)'
96+
// CHECK-NEXT: ParmVarDecl {{.*}} other 'const hlsl::[[RESOURCE]]<element_type> &'
97+
// CHECK-NEXT: CompoundStmt
98+
// CHECK-NEXT: BinaryOperator {{.*}} '='
99+
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
100+
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
101+
// CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle
102+
// CHECK-NEXT: DeclRefExpr {{.*}} 'const hlsl::[[RESOURCE]]<element_type>' ParmVar {{.*}} 'other' 'const hlsl::[[RESOURCE]]<element_type> &'
103+
// CHECK-NEXT: ReturnStmt
104+
// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
105+
// CHECK-NEXT: AlwaysInlineAttr
106+
81107
// Constructor from binding
82108

83109
// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]]<element_type> 'void (unsigned int, unsigned int, int, unsigned int, const char *)' inline

clang/test/CodeGenHLSL/builtins/hlsl_resource_t.hlsl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ void fb(CustomResource a) {
2626
CustomResource b = a;
2727
}
2828

29-
// CHECK: define hidden void @_Z2fcN4hlsl8RWBufferIDv4_fEE(ptr noundef byval(%"class.hlsl::RWBuffer") align 4 %a)
30-
// CHECK: call void @_Z4foo2N4hlsl8RWBufferIDv4_fEE(ptr noundef byval(%"class.hlsl::RWBuffer") align 4 %agg.tmp)
31-
// CHECK: declare hidden void @_Z4foo2N4hlsl8RWBufferIDv4_fEE(ptr noundef byval(%"class.hlsl::RWBuffer") align 4)
29+
// CHECK: define hidden void @_Z2fcN4hlsl8RWBufferIDv4_fEE(ptr dead_on_return noundef %a)
30+
// CHECK: call void @_Z4foo2N4hlsl8RWBufferIDv4_fEE(ptr dead_on_return noundef %{{.*}})
31+
// CHECK: declare hidden void @_Z4foo2N4hlsl8RWBufferIDv4_fEE(ptr dead_on_return noundef)
3232
void foo2(RWBuffer<float4> buf);
3333

3434
void fc(RWBuffer<float4> a) {
@@ -44,9 +44,9 @@ struct MyStruct {
4444
int2 i;
4545
};
4646

47-
// CHECK: define hidden void @_Z2feN4hlsl16StructuredBufferI8MyStructEE(ptr noundef byval(%"class.hlsl::StructuredBuffer") align 4 %a)
48-
// CHECK: call void @_Z4foo3N4hlsl16StructuredBufferI8MyStructEE(ptr noundef byval(%"class.hlsl::StructuredBuffer") align 4 %agg.tmp)
49-
// CHECK: declare hidden void @_Z4foo3N4hlsl16StructuredBufferI8MyStructEE(ptr noundef byval(%"class.hlsl::StructuredBuffer") align 4)
47+
// CHECK: define hidden void @_Z2feN4hlsl16StructuredBufferI8MyStructEE(ptr dead_on_return noundef %a)
48+
// CHECK: call void @_Z4foo3N4hlsl16StructuredBufferI8MyStructEE(ptr dead_on_return noundef %{{.*}})
49+
// CHECK: declare hidden void @_Z4foo3N4hlsl16StructuredBufferI8MyStructEE(ptr dead_on_return noundef)
5050
void foo3(StructuredBuffer<MyStruct> buf);
5151

5252
void fe(StructuredBuffer<MyStruct> a) {

clang/test/CodeGenHLSL/debug/rwbuffer_debug_info.hlsl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -x hlsl -emit-llvm -disable-llvm-passes -o - -hlsl-entry main %s -debug-info-kind=standalone -dwarf-version=4 | FileCheck %s
22

33

4-
// CHECK: [[DWTag:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "RWBuffer<float>",
4+
// CHECK: [[DWTag:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "RWBuffer<float>",
5+
// CHECK: [[thisType:![0-9]+]] = !DIDerivedType(tag: DW_TAG_reference_type, baseType: [[DWTag]], size: 32)
56
// CHECK: [[RWBuffer:![0-9]+]] = distinct !DISubprogram(name: "RWBuffer",
67
// CHECK-SAME: scope: [[DWTag]]
78
// CHECK: [[FirstThis:![0-9]+]] = !DILocalVariable(name: "this", arg: 1, scope: [[RWBuffer]], type: [[thisType:![0-9]+]]
8-
// CHECK: [[thisType]] = !DIDerivedType(tag: DW_TAG_reference_type, baseType: [[DWTag]], size: 32)
99
RWBuffer<float> Out : register(u7, space4);
1010

1111
[numthreads(8,1,1)]

clang/test/CodeGenHLSL/implicit-norecurse-attrib.hlsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ uint Find(Node SortedTree[MAX], uint key) {
3131
}
3232

3333
// CHECK: Function Attrs:{{.*}}norecurse
34-
// CHECK: define noundef i1 @_Z8InitTreeA100_4NodeN4hlsl8RWBufferIDv4_jEEj(ptr noundef byval([100 x %struct.Node]) align 1 %tree, ptr noundef byval(%"class.hlsl::RWBuffer") align 4 %encodedTree, i32 noundef %maxDepth) [[Attr:\#[0-9]+]]
34+
// CHECK: define noundef i1 @_Z8InitTreeA100_4NodeN4hlsl8RWBufferIDv4_jEEj(ptr noundef byval([100 x %struct.Node]) align 1 %tree, ptr dead_on_return noundef %encodedTree, i32 noundef %maxDepth) [[Attr:\#[0-9]+]]
3535
// CHECK: ret i1
3636
// Initialize tree with given buffer
3737
// Imagine the inout works

clang/test/CodeGenHLSL/resources/res-array-local-multi-dim.hlsl

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -finclude-default-header \
22
// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
33

4+
// https://github.com/llvm/llvm-project/issues/156786
5+
// XFAIL: *
6+
47
// This test verifies handling of multi-dimensional local arrays of resources
58
// when used as a function argument and local variable.
69

@@ -29,19 +32,35 @@ float foo(RWBuffer<float> Arr[2][2]) {
2932
// CHECK-NEXT: entry:
3033
[numthreads(4,1,1)]
3134
void main() {
32-
// CHECK-NEXT: %L = alloca [2 x [2 x %"class.hlsl::RWBuffer"]], align 4
33-
// CHECK-NEXT: %[[Tmp:.*]] = alloca [2 x [2 x %"class.hlsl::RWBuffer"]], align 4
34-
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %L, ptr align 4 @_ZL1A, i32 4, i1 false)
35-
// CHECK-NEXT: %[[Ptr1:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %L, i32 1
36-
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Ptr1]], ptr align 4 @_ZL1B, i32 4, i1 false)
37-
// CHECK-NEXT: %[[Ptr2:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %L, i32 1
38-
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Ptr2]], ptr align 4 @_ZL1A, i32 4, i1 false)
39-
// CHECK-NEXT: %[[Ptr3:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %[[Ptr2]], i32 1
40-
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Ptr3]], ptr align 4 @_ZL1B, i32 4, i1 false)
35+
// CHECK: %L = alloca [2 x [2 x %"class.hlsl::RWBuffer"]], align 4
36+
// CHECK: %[[ref_tmp:.*]] = alloca %"class.hlsl::RWBuffer", align 4
37+
// CHECK: %[[ref_tmp1:.*]] = alloca %"class.hlsl::RWBuffer", align 4
38+
// CHECK: %[[ref_tmp2:.*]] = alloca %"class.hlsl::RWBuffer", align 4
39+
// CHECK: %[[ref_tmp3:.*]] = alloca %"class.hlsl::RWBuffer", align 4
40+
// CHECK: %[[ref_tmp4:.*]] = alloca %"class.hlsl::RWBuffer", align 4
41+
// CHECK: %[[ref_tmp5:.*]] = alloca %"class.hlsl::RWBuffer", align 4
42+
// CHECK: %[[ref_tmp6:.*]] = alloca %"class.hlsl::RWBuffer", align 4
43+
// CHECK: %[[ref_tmp7:.*]] = alloca %"class.hlsl::RWBuffer", align 4
44+
// CHECK: %[[agg_tmp:.*]] = alloca [2 x [2 x %"class.hlsl::RWBuffer"]], align 4
45+
// CHECK: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[ref_tmp]], ptr {{.*}} @_ZL1A)
46+
// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[ref_tmp1]], ptr {{.*}} %[[ref_tmp]])
47+
// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[ref_tmp2]], ptr {{.*}} @_ZL1B)
48+
// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[ref_tmp3]], ptr {{.*}} %[[ref_tmp2]])
49+
// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[ref_tmp4]], ptr {{.*}} @_ZL1A)
50+
// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[ref_tmp5]], ptr {{.*}} %[[ref_tmp4]])
51+
// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[ref_tmp6]], ptr {{.*}} @_ZL1B)
52+
// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[ref_tmp7]], ptr {{.*}} %[[ref_tmp6]])
53+
// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %L, ptr {{.*}} %[[ref_tmp1]])
54+
// CHECK-NEXT: %[[arrayinit_element:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %L, i32 1
55+
// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[arrayinit_element]], ptr {{.*}} %[[ref_tmp3]])
56+
// CHECK-NEXT: %[[arrayinit_element8:.*]] = getelementptr inbounds [2 x %"class.hlsl::RWBuffer"], ptr %L, i32 1
57+
// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[arrayinit_element8]], ptr {{.*}} %[[ref_tmp5]])
58+
// CHECK-NEXT: %[[arrayinit_element9:.*]] = getelementptr inbounds %"class.hlsl::RWBuffer", ptr %[[arrayinit_element8]], i32 1
59+
// CHECK-NEXT: call void @_ZN4hlsl8RWBufferIfEC1ERKS1_(ptr {{.*}} %[[arrayinit_element9]], ptr {{.*}} %[[ref_tmp7]])
4160
RWBuffer<float> L[2][2] = { { A, B }, { A, B } };
4261

43-
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[Tmp]], ptr align 4 %L, i32 16, i1 false)
44-
// CHECK-NEXT: %[[ReturnedValue:.*]] = call {{.*}}float @_Z3fooA2_A2_N4hlsl8RWBufferIfEE(ptr noundef byval([2 x [2 x %"class.hlsl::RWBuffer"]]) align 4 %[[Tmp]])
62+
// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[agg_tmp]], ptr align 4 %L, i32 16, i1 false)
63+
// CHECK-NEXT: %[[ReturnedValue:.*]] = call {{.*}}float @_Z3fooA2_A2_N4hlsl8RWBufferIfEE(ptr noundef byval([2 x [2 x %"class.hlsl::RWBuffer"]]) align 4 %[[agg_tmp]])
4564
// CHECK-NEXT: %[[OutBufPtr:.*]] = call {{.*}} ptr @_ZN4hlsl18RWStructuredBufferIfEixEj(ptr {{.*}} @_ZL3Out, i32 noundef 0)
4665
// CHECK-NEXT: store float %[[ReturnedValue]], ptr %[[OutBufPtr]], align 4
4766
// CHECK-NEXT: ret void

0 commit comments

Comments
 (0)