aboutsummaryrefslogtreecommitdiff
path: root/clang/test/CodeGenHLSL
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/CodeGenHLSL')
-rw-r--r--clang/test/CodeGenHLSL/ArrayAssignable.hlsl70
-rw-r--r--clang/test/CodeGenHLSL/BasicFeatures/MatrixConstructor.hlsl95
-rw-r--r--clang/test/CodeGenHLSL/BasicFeatures/MatrixElementTypeCast.hlsl219
-rw-r--r--clang/test/CodeGenHLSL/BasicFeatures/MatrixExplicitTruncation.hlsl156
-rw-r--r--clang/test/CodeGenHLSL/BasicFeatures/MatrixImplicitTruncation.hlsl138
-rw-r--r--clang/test/CodeGenHLSL/BasicFeatures/OutputArguments.hlsl12
-rw-r--r--clang/test/CodeGenHLSL/BoolVector.hlsl15
-rw-r--r--clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl5
-rw-r--r--clang/test/CodeGenHLSL/builtins/ScalarSwizzles.hlsl25
-rw-r--r--clang/test/CodeGenHLSL/builtins/VectorElementStore.hlsl41
-rw-r--r--clang/test/CodeGenHLSL/builtins/VectorSwizzles.hlsl96
-rw-r--r--clang/test/CodeGenHLSL/builtins/ddx-coarse-builtin.hlsl26
-rw-r--r--clang/test/CodeGenHLSL/builtins/ddx-coarse.hlsl86
-rw-r--r--clang/test/CodeGenHLSL/builtins/ddy-coarse-builtin.hlsl26
-rw-r--r--clang/test/CodeGenHLSL/builtins/ddy-coarse.hlsl86
-rw-r--r--clang/test/CodeGenHLSL/builtins/exp-overloads.hlsl80
-rw-r--r--clang/test/CodeGenHLSL/builtins/exp.hlsl48
-rw-r--r--clang/test/CodeGenHLSL/builtins/exp2-overloads.hlsl80
-rw-r--r--clang/test/CodeGenHLSL/builtins/exp2.hlsl48
-rw-r--r--clang/test/CodeGenHLSL/builtins/f16tof32-builtin.hlsl30
-rw-r--r--clang/test/CodeGenHLSL/builtins/f16tof32.hlsl30
-rw-r--r--clang/test/CodeGenHLSL/builtins/faceforward.hlsl41
-rw-r--r--clang/test/CodeGenHLSL/builtins/firstbithigh.hlsl163
-rw-r--r--clang/test/CodeGenHLSL/builtins/fwidth.hlsl118
-rw-r--r--clang/test/CodeGenHLSL/builtins/ldexp.hlsl32
-rw-r--r--clang/test/CodeGenHLSL/builtins/lit.hlsl18
-rw-r--r--clang/test/CodeGenHLSL/builtins/round-overloads.hlsl80
-rw-r--r--clang/test/CodeGenHLSL/builtins/round.hlsl48
-rw-r--r--clang/test/CodeGenHLSL/builtins/select.hlsl64
-rw-r--r--clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl38
-rw-r--r--clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl37
-rw-r--r--clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl38
-rw-r--r--clang/test/CodeGenHLSL/resources/cbuffer.hlsl253
-rw-r--r--clang/test/CodeGenHLSL/resources/cbuffer_and_namespaces.hlsl10
-rw-r--r--clang/test/CodeGenHLSL/resources/cbuffer_geps.hlsl117
-rw-r--r--clang/test/CodeGenHLSL/resources/cbuffer_with_packoffset.hlsl38
-rw-r--r--clang/test/CodeGenHLSL/resources/cbuffer_with_static_global_and_function.hlsl2
-rw-r--r--clang/test/CodeGenHLSL/resources/default_cbuffer.hlsl11
-rw-r--r--clang/test/CodeGenHLSL/resources/default_cbuffer_with_layout.hlsl28
-rw-r--r--clang/test/CodeGenHLSL/semantics/DispatchThreadID-noindex.hlsl2
-rw-r--r--clang/test/CodeGenHLSL/semantics/DispatchThreadID.hlsl1
-rw-r--r--clang/test/CodeGenHLSL/semantics/SV_GroupID-noindex.hlsl7
-rw-r--r--clang/test/CodeGenHLSL/semantics/SV_GroupThreadID-noindex.hlsl2
-rw-r--r--clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl21
-rw-r--r--clang/test/CodeGenHLSL/semantics/SV_Position.vs.hlsl26
-rw-r--r--clang/test/CodeGenHLSL/semantics/SV_Target.ps.hlsl19
-rw-r--r--clang/test/CodeGenHLSL/semantics/semantic-struct-2-output.hlsl35
-rw-r--r--clang/test/CodeGenHLSL/semantics/semantic.arbitrary.hlsl36
-rw-r--r--clang/test/CodeGenHLSL/semantics/semantic.array.hlsl37
-rw-r--r--clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl37
-rw-r--r--clang/test/CodeGenHLSL/semantics/semantic.explicit-location-output-struct.hlsl37
-rw-r--r--clang/test/CodeGenHLSL/semantics/semantic.explicit-location.hlsl19
-rw-r--r--clang/test/CodeGenHLSL/semantics/semantic.explicit-mix-builtin.hlsl39
-rw-r--r--clang/test/CodeGenHLSL/semantics/semantic.explicit-mix-builtin.vs.hlsl31
-rw-r--r--clang/test/CodeGenHLSL/semantics/semantic.explicit-mix.lib.hlsl40
-rw-r--r--clang/test/CodeGenHLSL/semantics/semantic.struct.hlsl77
-rw-r--r--clang/test/CodeGenHLSL/semantics/semantic.struct.output.hlsl56
-rw-r--r--clang/test/CodeGenHLSL/sret_output.hlsl32
58 files changed, 2621 insertions, 481 deletions
diff --git a/clang/test/CodeGenHLSL/ArrayAssignable.hlsl b/clang/test/CodeGenHLSL/ArrayAssignable.hlsl
index aaa486e..d1bfc6d 100644
--- a/clang/test/CodeGenHLSL/ArrayAssignable.hlsl
+++ b/clang/test/CodeGenHLSL/ArrayAssignable.hlsl
@@ -5,18 +5,19 @@ struct S {
float f;
};
-// CHECK: [[CBLayout:%.*]] = type <{ [2 x float], [2 x <4 x i32>], [2 x [2 x i32]], [1 x target("dx.Layout", %S, 8, 0, 4)] }>
-// CHECK: @CBArrays.cb = global target("dx.CBuffer", target("dx.Layout", [[CBLayout]], 136, 0, 32, 64, 128))
-// CHECK: @c1 = external hidden addrspace(2) global [2 x float], align 4
+// CHECK: [[CBLayout:%.*]] = type <{ <{ [1 x <{ float, target("dx.Padding", 12) }>], float }>, target("dx.Padding", 12), [2 x <4 x i32>], <{ [1 x <{ <{ [1 x <{ i32, target("dx.Padding", 12) }>], i32 }>, target("dx.Padding", 12) }>], <{ [1 x <{ i32, target("dx.Padding", 12) }>], i32 }> }>, target("dx.Padding", 12), <{ [1 x <{ %S, target("dx.Padding", 8) }>], %S }> }>
+
+// CHECK: @CBArrays.cb = global target("dx.CBuffer", [[CBLayout]])
+// CHECK: @c1 = external hidden addrspace(2) global <{ [1 x <{ float, target("dx.Padding", 12) }>], float }>, align 4
// CHECK: @c2 = external hidden addrspace(2) global [2 x <4 x i32>], align 16
-// CHECK: @c3 = external hidden addrspace(2) global [2 x [2 x i32]], align 4
-// CHECK: @c4 = external hidden addrspace(2) global [1 x target("dx.Layout", %S, 8, 0, 4)], align 1
+// CHECK: @c3 = external hidden addrspace(2) global <{ [1 x <{ <{ [1 x <{ i32, target("dx.Padding", 12) }>], i32 }>, target("dx.Padding", 12) }>], <{ [1 x <{ i32, target("dx.Padding", 12) }>], i32 }> }>, align 4
+// CHECK: @c4 = external hidden addrspace(2) global <{ [1 x <{ %S, target("dx.Padding", 8) }>], %S }>, align 1
cbuffer CBArrays : register(b0) {
float c1[2];
int4 c2[2];
int c3[2][2];
- S c4[1];
+ S c4[2];
}
// CHECK-LABEL: define hidden void {{.*}}arr_assign1
@@ -140,40 +141,71 @@ void arr_assign7() {
// CHECK-LABEL: define hidden void {{.*}}arr_assign8
// CHECK: [[C:%.*]] = alloca [2 x float], align 4
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[C]], ptr align 4 {{.*}}, i32 8, i1 false)
-// CHECK-NEXT: call void @llvm.memcpy.p0.p2.i32(ptr align 4 [[C]], ptr addrspace(2) align 4 @c1, i32 8, i1 false)
+// CHECK-NEXT: [[V0:%.*]] = getelementptr inbounds [2 x float], ptr [[C]], i32 0
+// CHECK-NEXT: [[L0:%.*]] = load float, ptr addrspace(2) @c1, align 4
+// CHECK-NEXT: store float [[L0]], ptr [[V0]], align 4
+// CHECK-NEXT: [[V1:%.*]] = getelementptr inbounds [2 x float], ptr [[C]], i32 0, i32 1
+// CHECK-NEXT: [[L1:%.*]] = load float, ptr addrspace(2) getelementptr inbounds (<{ [1 x <{ float, target("dx.Padding", 12) }>], float }>, ptr addrspace(2) @c1, i32 0, i32 1), align 4
+// CHECK-NEXT: store float [[L1]], ptr [[V1]], align 4
// CHECK-NEXT: ret void
void arr_assign8() {
- float C[2] = {1.0, 2.0};
+ float C[2];
C = c1;
}
+// TODO: We should be able to just memcpy here.
+// See https://github.com/llvm/wg-hlsl/issues/351
+//
// CHECK-LABEL: define hidden void {{.*}}arr_assign9
// CHECK: [[C:%.*]] = alloca [2 x <4 x i32>], align 16
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[C]], ptr align 16 {{.*}}, i32 32, i1 false)
-// CHECK-NEXT: call void @llvm.memcpy.p0.p2.i32(ptr align 16 [[C]], ptr addrspace(2) align 16 @c2, i32 32, i1 false)
+// CHECK-NEXT: [[V0:%.*]] = getelementptr inbounds [2 x <4 x i32>], ptr [[C]], i32 0
+// CHECK-NEXT: [[L0:%.*]] = load <4 x i32>, ptr addrspace(2) @c2, align 16
+// CHECK-NEXT: store <4 x i32> [[L0]], ptr [[V0]], align 16
+// CHECK-NEXT: [[V1:%.*]] = getelementptr inbounds [2 x <4 x i32>], ptr [[C]], i32 0, i32 1
+// CHECK-NEXT: [[L1:%.*]] = load <4 x i32>, ptr addrspace(2) getelementptr inbounds ([2 x <4 x i32>], ptr addrspace(2) @c2, i32 0, i32 1), align 16
+// CHECK-NEXT: store <4 x i32> [[L1]], ptr [[V1]], align 16
// CHECK-NEXT: ret void
void arr_assign9() {
- int4 C[2] = {1,2,3,4,5,6,7,8};
+ int4 C[2];
C = c2;
}
// CHECK-LABEL: define hidden void {{.*}}arr_assign10
// CHECK: [[C:%.*]] = alloca [2 x [2 x i32]], align 4
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[C]], ptr align 4 {{.*}}, i32 16, i1 false)
-// CHECK-NEXT: call void @llvm.memcpy.p0.p2.i32(ptr align 4 [[C]], ptr addrspace(2) align 4 @c3, i32 16, i1 false)
+// CHECK-NEXT: [[V0:%.*]] = getelementptr inbounds [2 x [2 x i32]], ptr [[C]], i32 0, i32 0, i32 0
+// CHECK-NEXT: [[L0:%.*]] = load i32, ptr addrspace(2) @c3, align 4
+// CHECK-NEXT: store i32 [[L0]], ptr [[V0]], align 4
+// CHECK-NEXT: [[V1:%.*]] = getelementptr inbounds [2 x [2 x i32]], ptr [[C]], i32 0, i32 0, i32 1
+// CHECK-NEXT: [[L1:%.*]] = load i32, ptr addrspace(2) getelementptr inbounds (<{ [1 x <{ <{ [1 x <{ i32, target("dx.Padding", 12) }>], i32 }>, target("dx.Padding", 12) }>], <{ [1 x <{ i32, target("dx.Padding", 12) }>], i32 }> }>, ptr addrspace(2) @c3, i32 0, i32 0, i32 0, i32 0, i32 1), align 4
+// CHECK-NEXT: store i32 [[L1]], ptr [[V1]], align 4
+// CHECK-NEXT: [[V2:%.*]] = getelementptr inbounds [2 x [2 x i32]], ptr [[C]], i32 0, i32 1, i32 0
+// CHECK-NEXT: [[L2:%.*]] = load i32, ptr addrspace(2) getelementptr inbounds (<{ [1 x <{ <{ [1 x <{ i32, target("dx.Padding", 12) }>], i32 }>, target("dx.Padding", 12) }>], <{ [1 x <{ i32, target("dx.Padding", 12) }>], i32 }> }>, ptr addrspace(2) @c3, i32 0, i32 1, i32 0, i32 0, i32 0), align 4
+// CHECK-NEXT: store i32 [[L2]], ptr [[V2]], align 4
+// CHECK-NEXT: [[V3:%.*]] = getelementptr inbounds [2 x [2 x i32]], ptr [[C]], i32 0, i32 1, i32 1
+// CHECK-NEXT: [[L3:%.*]] = load i32, ptr addrspace(2) getelementptr inbounds (<{ [1 x <{ <{ [1 x <{ i32, target("dx.Padding", 12) }>], i32 }>, target("dx.Padding", 12) }>], <{ [1 x <{ i32, target("dx.Padding", 12) }>], i32 }> }>, ptr addrspace(2) @c3, i32 0, i32 1, i32 1), align 4
+// CHECK-NEXT: store i32 [[L3]], ptr [[V3]], align 4
// CHECK-NEXT: ret void
void arr_assign10() {
- int C[2][2] = {1,2,3,4};
+ int C[2][2];
C = c3;
}
// CHECK-LABEL: define hidden void {{.*}}arr_assign11
-// CHECK: [[C:%.*]] = alloca [1 x %struct.S], align 1
-// CHECK: call void @llvm.memcpy.p0.p2.i32(ptr align 1 [[C]], ptr addrspace(2) align 1 @c4, i32 8, i1 false)
+// CHECK: [[C:%.*]] = alloca [2 x %struct.S], align 1
+// CHECK-NEXT: [[V0:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[C]], i32 0, i32 0, i32 0
+// CHECK-NEXT: [[L0:%.*]] = load i32, ptr addrspace(2) @c4, align 4
+// CHECK-NEXT: store i32 [[L0]], ptr [[V0]], align 4
+// CHECK-NEXT: [[V1:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[C]], i32 0, i32 0, i32 1
+// CHECK-NEXT: [[L1:%.*]] = load float, ptr addrspace(2) getelementptr inbounds (<{ [1 x <{ %S, target("dx.Padding", 8) }>], %S }>, ptr addrspace(2) @c4, i32 0, i32 0, i32 0, i32 0, i32 1), align 4
+// CHECK-NEXT: store float [[L1]], ptr [[V1]], align 4
+// CHECK-NEXT: [[V2:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[C]], i32 0, i32 1, i32 0
+// CHECK-NEXT: [[L2:%.*]] = load i32, ptr addrspace(2) getelementptr inbounds (<{ [1 x <{ %S, target("dx.Padding", 8) }>], %S }>, ptr addrspace(2) @c4, i32 0, i32 1, i32 0), align 4
+// CHECK-NEXT: store i32 [[L2]], ptr [[V2]], align 4
+// CHECK-NEXT: [[V3:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[C]], i32 0, i32 1, i32 1
+// CHECK-NEXT: [[L3:%.*]] = load float, ptr addrspace(2) getelementptr inbounds (<{ [1 x <{ %S, target("dx.Padding", 8) }>], %S }>, ptr addrspace(2) @c4, i32 0, i32 1, i32 1), align 4
+// CHECK-NEXT: store float [[L3]], ptr [[V3]], align 4
// CHECK-NEXT: ret void
void arr_assign11() {
- S s = {1, 2.0};
- S C[1] = {s};
+ S C[2];
C = c4;
}
diff --git a/clang/test/CodeGenHLSL/BasicFeatures/MatrixConstructor.hlsl b/clang/test/CodeGenHLSL/BasicFeatures/MatrixConstructor.hlsl
new file mode 100644
index 0000000..a7c0101
--- /dev/null
+++ b/clang/test/CodeGenHLSL/BasicFeatures/MatrixConstructor.hlsl
@@ -0,0 +1,95 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -disable-llvm-passes -emit-llvm -finclude-default-header -o - %s | FileCheck %s
+
+// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <6 x float> @_Z5case1v(
+// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: ret <6 x float> <float 0.000000e+00, float 2.000000e+00, float 4.000000e+00, float 1.000000e+00, float 3.000000e+00, float 5.000000e+00>
+//
+float3x2 case1() {
+ // vec[0] = 0
+ // vec[1] = 2
+ // vec[2] = 4
+ // vec[3] = 1
+ // vec[4] = 3
+ // vec[5] = 5
+ return float3x2(0, 1,
+ 2, 3,
+ 4, 5);
+}
+
+
+RWStructuredBuffer<float> In;
+
+// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <6 x float> @_Z5case2v(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[CALL:%.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @_ZN4hlsl18RWStructuredBufferIfEixEj(ptr noundef nonnull align 4 dereferenceable(8) @_ZL2In, i32 noundef 0) #[[ATTR3:[0-9]+]]
+// CHECK-NEXT: [[CALL1:%.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @_ZN4hlsl18RWStructuredBufferIfEixEj(ptr noundef nonnull align 4 dereferenceable(8) @_ZL2In, i32 noundef 1) #[[ATTR3]]
+// CHECK-NEXT: [[CALL2:%.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @_ZN4hlsl18RWStructuredBufferIfEixEj(ptr noundef nonnull align 4 dereferenceable(8) @_ZL2In, i32 noundef 2) #[[ATTR3]]
+// CHECK-NEXT: [[CALL3:%.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @_ZN4hlsl18RWStructuredBufferIfEixEj(ptr noundef nonnull align 4 dereferenceable(8) @_ZL2In, i32 noundef 3) #[[ATTR3]]
+// CHECK-NEXT: [[CALL4:%.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @_ZN4hlsl18RWStructuredBufferIfEixEj(ptr noundef nonnull align 4 dereferenceable(8) @_ZL2In, i32 noundef 4) #[[ATTR3]]
+// CHECK-NEXT: [[CALL5:%.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @_ZN4hlsl18RWStructuredBufferIfEixEj(ptr noundef nonnull align 4 dereferenceable(8) @_ZL2In, i32 noundef 5) #[[ATTR3]]
+// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[CALL]], align 4
+// CHECK-NEXT: [[VECINIT:%.*]] = insertelement <6 x float> poison, float [[TMP0]], i32 0
+// CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[CALL2]], align 4
+// CHECK-NEXT: [[VECINIT6:%.*]] = insertelement <6 x float> [[VECINIT]], float [[TMP1]], i32 1
+// CHECK-NEXT: [[TMP2:%.*]] = load float, ptr [[CALL4]], align 4
+// CHECK-NEXT: [[VECINIT7:%.*]] = insertelement <6 x float> [[VECINIT6]], float [[TMP2]], i32 2
+// CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[CALL1]], align 4
+// CHECK-NEXT: [[VECINIT8:%.*]] = insertelement <6 x float> [[VECINIT7]], float [[TMP3]], i32 3
+// CHECK-NEXT: [[TMP4:%.*]] = load float, ptr [[CALL3]], align 4
+// CHECK-NEXT: [[VECINIT9:%.*]] = insertelement <6 x float> [[VECINIT8]], float [[TMP4]], i32 4
+// CHECK-NEXT: [[TMP5:%.*]] = load float, ptr [[CALL5]], align 4
+// CHECK-NEXT: [[VECINIT10:%.*]] = insertelement <6 x float> [[VECINIT9]], float [[TMP5]], i32 5
+// CHECK-NEXT: ret <6 x float> [[VECINIT10]]
+//
+float3x2 case2() {
+ // vec[0] = Call
+ // vec[1] = Call2
+ // vec[2] = Call4
+ // vec[3] = Call1
+ // vec[4] = Call3
+ // vec[5] = Call5
+ return float3x2(In[0], In[1],
+ In[2], In[3],
+ In[4], In[5]);
+}
+
+
+// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <6 x float> @_Z5case3Dv3_fS_(
+// CHECK-SAME: <3 x float> noundef nofpclass(nan inf) [[A:%.*]], <3 x float> noundef nofpclass(nan inf) [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <3 x float>, align 16
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <3 x float>, align 16
+// CHECK-NEXT: store <3 x float> [[A]], ptr [[A_ADDR]], align 16
+// CHECK-NEXT: store <3 x float> [[B]], ptr [[B_ADDR]], align 16
+// CHECK-NEXT: [[TMP0:%.*]] = load <3 x float>, ptr [[A_ADDR]], align 16
+// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <3 x float> [[TMP0]], i64 0
+// CHECK-NEXT: [[VECINIT:%.*]] = insertelement <6 x float> poison, float [[VECEXT]], i32 0
+// CHECK-NEXT: [[TMP1:%.*]] = load <3 x float>, ptr [[A_ADDR]], align 16
+// CHECK-NEXT: [[VECEXT1:%.*]] = extractelement <3 x float> [[TMP1]], i64 2
+// CHECK-NEXT: [[VECINIT2:%.*]] = insertelement <6 x float> [[VECINIT]], float [[VECEXT1]], i32 1
+// CHECK-NEXT: [[TMP2:%.*]] = load <3 x float>, ptr [[B_ADDR]], align 16
+// CHECK-NEXT: [[VECEXT3:%.*]] = extractelement <3 x float> [[TMP2]], i64 1
+// CHECK-NEXT: [[VECINIT4:%.*]] = insertelement <6 x float> [[VECINIT2]], float [[VECEXT3]], i32 2
+// CHECK-NEXT: [[TMP3:%.*]] = load <3 x float>, ptr [[A_ADDR]], align 16
+// CHECK-NEXT: [[VECEXT5:%.*]] = extractelement <3 x float> [[TMP3]], i64 1
+// CHECK-NEXT: [[VECINIT6:%.*]] = insertelement <6 x float> [[VECINIT4]], float [[VECEXT5]], i32 3
+// CHECK-NEXT: [[TMP4:%.*]] = load <3 x float>, ptr [[B_ADDR]], align 16
+// CHECK-NEXT: [[VECEXT7:%.*]] = extractelement <3 x float> [[TMP4]], i64 0
+// CHECK-NEXT: [[VECINIT8:%.*]] = insertelement <6 x float> [[VECINIT6]], float [[VECEXT7]], i32 4
+// CHECK-NEXT: [[TMP5:%.*]] = load <3 x float>, ptr [[B_ADDR]], align 16
+// CHECK-NEXT: [[VECEXT9:%.*]] = extractelement <3 x float> [[TMP5]], i64 2
+// CHECK-NEXT: [[VECINIT10:%.*]] = insertelement <6 x float> [[VECINIT8]], float [[VECEXT9]], i32 5
+// CHECK-NEXT: ret <6 x float> [[VECINIT10]]
+//
+float3x2 case3(float3 a, float3 b) {
+ // vec[0] = A[0]
+ // vec[1] = A[2]
+ // vec[2] = B[1]
+ // vec[3] = A[1]
+ // vec[4] = B[0]
+ // vec[5] = B[2]
+ return float3x2(a,b);
+}
diff --git a/clang/test/CodeGenHLSL/BasicFeatures/MatrixElementTypeCast.hlsl b/clang/test/CodeGenHLSL/BasicFeatures/MatrixElementTypeCast.hlsl
new file mode 100644
index 0000000..3bd7636
--- /dev/null
+++ b/clang/test/CodeGenHLSL/BasicFeatures/MatrixElementTypeCast.hlsl
@@ -0,0 +1,219 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -disable-llvm-passes -fnative-half-type -fnative-int16-type -o - %s | FileCheck %s
+
+
+// CHECK-LABEL: define hidden noundef <6 x i32> @_Z22elementwise_type_cast0u11matrix_typeILm3ELm2EfE(
+// CHECK-SAME: <6 x float> noundef nofpclass(nan inf) [[F32:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[F32_ADDR:%.*]] = alloca [6 x float], align 4
+// CHECK-NEXT: [[I32:%.*]] = alloca [6 x i32], align 4
+// CHECK-NEXT: store <6 x float> [[F32]], ptr [[F32_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load <6 x float>, ptr [[F32_ADDR]], align 4
+// CHECK-NEXT: [[CONV:%.*]] = fptosi <6 x float> [[TMP0]] to <6 x i32>
+// CHECK-NEXT: store <6 x i32> [[CONV]], ptr [[I32]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load <6 x i32>, ptr [[I32]], align 4
+// CHECK-NEXT: ret <6 x i32> [[TMP1]]
+//
+int3x2 elementwise_type_cast0(float3x2 f32) {
+ int3x2 i32 = (int3x2)f32;
+ return i32;
+}
+
+// CHECK-LABEL: define hidden noundef <6 x i32> @_Z22elementwise_type_cast1u11matrix_typeILm3ELm2EsE(
+// CHECK-SAME: <6 x i16> noundef [[I16_32:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I16_32_ADDR:%.*]] = alloca [6 x i16], align 2
+// CHECK-NEXT: [[I32:%.*]] = alloca [6 x i32], align 4
+// CHECK-NEXT: store <6 x i16> [[I16_32]], ptr [[I16_32_ADDR]], align 2
+// CHECK-NEXT: [[TMP0:%.*]] = load <6 x i16>, ptr [[I16_32_ADDR]], align 2
+// CHECK-NEXT: [[CONV:%.*]] = sext <6 x i16> [[TMP0]] to <6 x i32>
+// CHECK-NEXT: store <6 x i32> [[CONV]], ptr [[I32]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load <6 x i32>, ptr [[I32]], align 4
+// CHECK-NEXT: ret <6 x i32> [[TMP1]]
+//
+int3x2 elementwise_type_cast1(int16_t3x2 i16_32) {
+ int3x2 i32 = (int3x2)i16_32;
+ return i32;
+}
+
+// CHECK-LABEL: define hidden noundef <6 x i32> @_Z22elementwise_type_cast2u11matrix_typeILm3ELm2ElE(
+// CHECK-SAME: <6 x i64> noundef [[I64_32:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I64_32_ADDR:%.*]] = alloca [6 x i64], align 8
+// CHECK-NEXT: [[I32:%.*]] = alloca [6 x i32], align 4
+// CHECK-NEXT: store <6 x i64> [[I64_32]], ptr [[I64_32_ADDR]], align 8
+// CHECK-NEXT: [[TMP0:%.*]] = load <6 x i64>, ptr [[I64_32_ADDR]], align 8
+// CHECK-NEXT: [[CONV:%.*]] = trunc <6 x i64> [[TMP0]] to <6 x i32>
+// CHECK-NEXT: store <6 x i32> [[CONV]], ptr [[I32]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load <6 x i32>, ptr [[I32]], align 4
+// CHECK-NEXT: ret <6 x i32> [[TMP1]]
+//
+int3x2 elementwise_type_cast2(int64_t3x2 i64_32) {
+ int3x2 i32 = (int3x2)i64_32;
+ return i32;
+}
+
+// CHECK-LABEL: define hidden noundef <6 x i16> @_Z22elementwise_type_cast3u11matrix_typeILm2ELm3EDhE(
+// CHECK-SAME: <6 x half> noundef nofpclass(nan inf) [[H23:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[H23_ADDR:%.*]] = alloca [6 x half], align 2
+// CHECK-NEXT: [[I23:%.*]] = alloca [6 x i16], align 2
+// CHECK-NEXT: store <6 x half> [[H23]], ptr [[H23_ADDR]], align 2
+// CHECK-NEXT: [[TMP0:%.*]] = load <6 x half>, ptr [[H23_ADDR]], align 2
+// CHECK-NEXT: [[CONV:%.*]] = fptosi <6 x half> [[TMP0]] to <6 x i16>
+// CHECK-NEXT: store <6 x i16> [[CONV]], ptr [[I23]], align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load <6 x i16>, ptr [[I23]], align 2
+// CHECK-NEXT: ret <6 x i16> [[TMP1]]
+//
+int16_t2x3 elementwise_type_cast3(half2x3 h23) {
+ int16_t2x3 i23 = (int16_t2x3)h23;
+ return i23;
+}
+
+// CHECK-LABEL: define hidden noundef <6 x i32> @_Z22elementwise_type_cast4u11matrix_typeILm3ELm2EdE(
+// CHECK-SAME: <6 x double> noundef nofpclass(nan inf) [[D32:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[D32_ADDR:%.*]] = alloca [6 x double], align 8
+// CHECK-NEXT: [[I32:%.*]] = alloca [6 x i32], align 4
+// CHECK-NEXT: store <6 x double> [[D32]], ptr [[D32_ADDR]], align 8
+// CHECK-NEXT: [[TMP0:%.*]] = load <6 x double>, ptr [[D32_ADDR]], align 8
+// CHECK-NEXT: [[CONV:%.*]] = fptosi <6 x double> [[TMP0]] to <6 x i32>
+// CHECK-NEXT: store <6 x i32> [[CONV]], ptr [[I32]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load <6 x i32>, ptr [[I32]], align 4
+// CHECK-NEXT: ret <6 x i32> [[TMP1]]
+//
+int3x2 elementwise_type_cast4(double3x2 d32) {
+ int3x2 i32 = (int3x2)d32;
+ return i32;
+}
+
+// CHECK-LABEL: define hidden void @_Z5call2v(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[A:%.*]] = alloca [2 x [1 x i32]], align 4
+// CHECK-NEXT: [[B:%.*]] = alloca [2 x i32], align 4
+// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca [2 x [1 x i32]], align 4
+// CHECK-NEXT: [[FLATCAST_TMP:%.*]] = alloca <2 x i32>, align 4
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @__const._Z5call2v.A, i32 8, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[AGG_TEMP]], ptr align 4 [[A]], i32 8, i1 false)
+// CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [2 x [1 x i32]], ptr [[AGG_TEMP]], i32 0, i32 0, i32 0
+// CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds [2 x [1 x i32]], ptr [[AGG_TEMP]], i32 0, i32 1, i32 0
+// CHECK-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr [[FLATCAST_TMP]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[GEP]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i32> [[TMP0]], i32 [[TMP1]], i64 0
+// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[GEP1]], align 4
+// CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x i32> [[TMP2]], i32 [[TMP3]], i64 1
+// CHECK-NEXT: store <2 x i32> [[TMP4]], ptr [[B]], align 4
+// CHECK-NEXT: ret void
+//
+void call2() {
+ int A[2][1] = {{1},{2}};
+ int2x1 B = (int2x1)A;
+}
+
+struct S {
+ int X;
+ float Y;
+};
+
+// CHECK-LABEL: define hidden void @_Z5call3v(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S:%.*]], align 1
+// CHECK-NEXT: [[A:%.*]] = alloca [2 x i32], align 4
+// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca [[STRUCT_S]], align 1
+// CHECK-NEXT: [[FLATCAST_TMP:%.*]] = alloca <2 x i32>, align 4
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[S]], ptr align 1 @__const._Z5call3v.s, i32 8, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[AGG_TEMP]], ptr align 1 [[S]], i32 8, i1 false)
+// CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_TEMP]], i32 0, i32 0
+// CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_TEMP]], i32 0, i32 1
+// CHECK-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr [[FLATCAST_TMP]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[GEP]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i32> [[TMP0]], i32 [[TMP1]], i64 0
+// CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[GEP1]], align 4
+// CHECK-NEXT: [[CONV:%.*]] = fptosi float [[TMP3]] to i32
+// CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x i32> [[TMP2]], i32 [[CONV]], i64 1
+// CHECK-NEXT: store <2 x i32> [[TMP4]], ptr [[A]], align 4
+// CHECK-NEXT: ret void
+//
+void call3() {
+ S s = {1, 2.0};
+ int2x1 A = (int2x1)s;
+}
+
+struct BFields {
+ double D;
+ int E: 15;
+ int : 8;
+ float F;
+};
+
+struct Derived : BFields {
+ int G;
+};
+
+// CHECK-LABEL: define hidden void @_Z5call47Derived(
+// CHECK-SAME: ptr noundef byval([[STRUCT_DERIVED:%.*]]) align 1 [[D:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[A:%.*]] = alloca [4 x i32], align 4
+// CHECK-NEXT: [[AGG_TEMP:%.*]] = alloca [[STRUCT_DERIVED]], align 1
+// CHECK-NEXT: [[FLATCAST_TMP:%.*]] = alloca <4 x i32>, align 4
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[AGG_TEMP]], ptr align 1 [[D]], i32 19, i1 false)
+// CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[STRUCT_DERIVED]], ptr [[AGG_TEMP]], i32 0, i32 0
+// CHECK-NEXT: [[E:%.*]] = getelementptr inbounds nuw [[STRUCT_BFIELDS:%.*]], ptr [[GEP]], i32 0, i32 1
+// CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds [[STRUCT_DERIVED]], ptr [[AGG_TEMP]], i32 0, i32 0, i32 0
+// CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds [[STRUCT_DERIVED]], ptr [[AGG_TEMP]], i32 0, i32 0, i32 2
+// CHECK-NEXT: [[GEP3:%.*]] = getelementptr inbounds [[STRUCT_DERIVED]], ptr [[AGG_TEMP]], i32 0, i32 1
+// CHECK-NEXT: [[TMP0:%.*]] = load <4 x i32>, ptr [[FLATCAST_TMP]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load double, ptr [[GEP1]], align 8
+// CHECK-NEXT: [[CONV:%.*]] = fptosi double [[TMP1]] to i32
+// CHECK-NEXT: [[TMP2:%.*]] = insertelement <4 x i32> [[TMP0]], i32 [[CONV]], i64 0
+// CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[GEP2]], align 4
+// CHECK-NEXT: [[CONV4:%.*]] = fptosi float [[TMP3]] to i32
+// CHECK-NEXT: [[TMP4:%.*]] = insertelement <4 x i32> [[TMP2]], i32 [[CONV4]], i64 1
+// CHECK-NEXT: [[BF_LOAD:%.*]] = load i24, ptr [[E]], align 1
+// CHECK-NEXT: [[BF_SHL:%.*]] = shl i24 [[BF_LOAD]], 9
+// CHECK-NEXT: [[BF_ASHR:%.*]] = ashr i24 [[BF_SHL]], 9
+// CHECK-NEXT: [[BF_CAST:%.*]] = sext i24 [[BF_ASHR]] to i32
+// CHECK-NEXT: [[TMP5:%.*]] = insertelement <4 x i32> [[TMP4]], i32 [[BF_CAST]], i64 2
+// CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[GEP3]], align 4
+// CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x i32> [[TMP5]], i32 [[TMP6]], i64 3
+// CHECK-NEXT: store <4 x i32> [[TMP7]], ptr [[A]], align 4
+// CHECK-NEXT: ret void
+//
+void call4(Derived D) {
+ int2x2 A = (int2x2)D;
+}
+
+// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> @_Z5call5Dv4_f(
+// CHECK-SAME: <4 x float> noundef nofpclass(nan inf) [[V:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[V_ADDR:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[M:%.*]] = alloca [4 x float], align 4
+// CHECK-NEXT: [[HLSL_EWCAST_SRC:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[FLATCAST_TMP:%.*]] = alloca <4 x float>, align 4
+// CHECK-NEXT: store <4 x float> [[V]], ptr [[V_ADDR]], align 16
+// CHECK-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr [[V_ADDR]], align 16
+// CHECK-NEXT: store <4 x float> [[TMP0]], ptr [[HLSL_EWCAST_SRC]], align 16
+// CHECK-NEXT: [[VECTOR_GEP:%.*]] = getelementptr inbounds <4 x float>, ptr [[HLSL_EWCAST_SRC]], i32 0
+// CHECK-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr [[FLATCAST_TMP]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load <4 x float>, ptr [[VECTOR_GEP]], align 16
+// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <4 x float> [[TMP2]], i32 0
+// CHECK-NEXT: [[TMP3:%.*]] = insertelement <4 x float> [[TMP1]], float [[VECEXT]], i64 0
+// CHECK-NEXT: [[TMP4:%.*]] = load <4 x float>, ptr [[VECTOR_GEP]], align 16
+// CHECK-NEXT: [[VECEXT1:%.*]] = extractelement <4 x float> [[TMP4]], i32 2
+// CHECK-NEXT: [[TMP5:%.*]] = insertelement <4 x float> [[TMP3]], float [[VECEXT1]], i64 1
+// CHECK-NEXT: [[TMP6:%.*]] = load <4 x float>, ptr [[VECTOR_GEP]], align 16
+// CHECK-NEXT: [[VECEXT2:%.*]] = extractelement <4 x float> [[TMP6]], i32 1
+// CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[TMP5]], float [[VECEXT2]], i64 2
+// CHECK-NEXT: [[TMP8:%.*]] = load <4 x float>, ptr [[VECTOR_GEP]], align 16
+// CHECK-NEXT: [[VECEXT3:%.*]] = extractelement <4 x float> [[TMP8]], i32 3
+// CHECK-NEXT: [[TMP9:%.*]] = insertelement <4 x float> [[TMP7]], float [[VECEXT3]], i64 3
+// CHECK-NEXT: store <4 x float> [[TMP9]], ptr [[M]], align 4
+// CHECK-NEXT: [[TMP10:%.*]] = load <4 x float>, ptr [[M]], align 4
+// CHECK-NEXT: ret <4 x float> [[TMP10]]
+//
+float2x2 call5(float4 v) {
+ float2x2 m = (float2x2)v;
+ return m;
+}
diff --git a/clang/test/CodeGenHLSL/BasicFeatures/MatrixExplicitTruncation.hlsl b/clang/test/CodeGenHLSL/BasicFeatures/MatrixExplicitTruncation.hlsl
new file mode 100644
index 0000000..f3c4bc4
--- /dev/null
+++ b/clang/test/CodeGenHLSL/BasicFeatures/MatrixExplicitTruncation.hlsl
@@ -0,0 +1,156 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.7-library -disable-llvm-passes -emit-llvm -finclude-default-header -o - %s | FileCheck %s
+
+// CHECK-LABEL: define hidden noundef <12 x i32> @_Z10trunc_castu11matrix_typeILm4ELm4EiE(
+// CHECK-SAME: <16 x i32> noundef [[I44:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I44_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT: [[I34:%.*]] = alloca [12 x i32], align 4
+// CHECK-NEXT: store <16 x i32> [[I44]], ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <12 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11>
+// CHECK-NEXT: store <12 x i32> [[TRUNC]], ptr [[I34]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load <12 x i32>, ptr [[I34]], align 4
+// CHECK-NEXT: ret <12 x i32> [[TMP1]]
+//
+ int3x4 trunc_cast(int4x4 i44) {
+ int3x4 i34 = (int3x4)i44;
+ return i34;
+}
+
+// CHECK-LABEL: define hidden noundef <12 x i32> @_Z11trunc_cast0u11matrix_typeILm4ELm4EiE(
+// CHECK-SAME: <16 x i32> noundef [[I44:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I44_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT: [[I43:%.*]] = alloca [12 x i32], align 4
+// CHECK-NEXT: store <16 x i32> [[I44]], ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <12 x i32> <i32 0, i32 1, i32 2, i32 4, i32 5, i32 6, i32 8, i32 9, i32 10, i32 12, i32 13, i32 14>
+// CHECK-NEXT: store <12 x i32> [[TRUNC]], ptr [[I43]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load <12 x i32>, ptr [[I43]], align 4
+// CHECK-NEXT: ret <12 x i32> [[TMP1]]
+//
+ int4x3 trunc_cast0(int4x4 i44) {
+ int4x3 i43 = (int4x3)i44;
+ return i43;
+}
+
+// CHECK-LABEL: define hidden noundef <9 x i32> @_Z11trunc_cast1u11matrix_typeILm4ELm4EiE(
+// CHECK-SAME: <16 x i32> noundef [[I44:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I44_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT: [[I33:%.*]] = alloca [9 x i32], align 4
+// CHECK-NEXT: store <16 x i32> [[I44]], ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <9 x i32> <i32 0, i32 1, i32 2, i32 4, i32 5, i32 6, i32 8, i32 9, i32 10>
+// CHECK-NEXT: store <9 x i32> [[TRUNC]], ptr [[I33]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load <9 x i32>, ptr [[I33]], align 4
+// CHECK-NEXT: ret <9 x i32> [[TMP1]]
+//
+ int3x3 trunc_cast1(int4x4 i44) {
+ int3x3 i33 = (int3x3)i44;
+ return i33;
+}
+
+// CHECK-LABEL: define hidden noundef <6 x i32> @_Z11trunc_cast2u11matrix_typeILm4ELm4EiE(
+// CHECK-SAME: <16 x i32> noundef [[I44:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I44_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT: [[I32:%.*]] = alloca [6 x i32], align 4
+// CHECK-NEXT: store <16 x i32> [[I44]], ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <6 x i32> <i32 0, i32 1, i32 4, i32 5, i32 8, i32 9>
+// CHECK-NEXT: store <6 x i32> [[TRUNC]], ptr [[I32]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load <6 x i32>, ptr [[I32]], align 4
+// CHECK-NEXT: ret <6 x i32> [[TMP1]]
+//
+ int3x2 trunc_cast2(int4x4 i44) {
+ int3x2 i32 = (int3x2)i44;
+ return i32;
+}
+
+// CHECK-LABEL: define hidden noundef <6 x i32> @_Z11trunc_cast3u11matrix_typeILm4ELm4EiE(
+// CHECK-SAME: <16 x i32> noundef [[I44:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I44_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT: [[I23:%.*]] = alloca [6 x i32], align 4
+// CHECK-NEXT: store <16 x i32> [[I44]], ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <6 x i32> <i32 0, i32 1, i32 2, i32 4, i32 5, i32 6>
+// CHECK-NEXT: store <6 x i32> [[TRUNC]], ptr [[I23]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load <6 x i32>, ptr [[I23]], align 4
+// CHECK-NEXT: ret <6 x i32> [[TMP1]]
+//
+ int2x3 trunc_cast3(int4x4 i44) {
+ int2x3 i23 = (int2x3)i44;
+ return i23;
+}
+
+// CHECK-LABEL: define hidden noundef <4 x i32> @_Z11trunc_cast4u11matrix_typeILm4ELm4EiE(
+// CHECK-SAME: <16 x i32> noundef [[I44:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I44_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT: [[I22:%.*]] = alloca [4 x i32], align 4
+// CHECK-NEXT: store <16 x i32> [[I44]], ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+// CHECK-NEXT: store <4 x i32> [[TRUNC]], ptr [[I22]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr [[I22]], align 4
+// CHECK-NEXT: ret <4 x i32> [[TMP1]]
+//
+ int2x2 trunc_cast4(int4x4 i44) {
+ int2x2 i22 = (int2x2)i44;
+ return i22;
+}
+
+// CHECK-LABEL: define hidden noundef <2 x i32> @_Z11trunc_cast5u11matrix_typeILm4ELm4EiE(
+// CHECK-SAME: <16 x i32> noundef [[I44:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I44_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT: [[I21:%.*]] = alloca [2 x i32], align 4
+// CHECK-NEXT: store <16 x i32> [[I44]], ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <2 x i32> <i32 0, i32 4>
+// CHECK-NEXT: store <2 x i32> [[TRUNC]], ptr [[I21]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr [[I21]], align 4
+// CHECK-NEXT: ret <2 x i32> [[TMP1]]
+//
+ int2x1 trunc_cast5(int4x4 i44) {
+ int2x1 i21 = (int2x1)i44;
+ return i21;
+}
+
+// CHECK-LABEL: define hidden noundef i32 @_Z11trunc_cast6u11matrix_typeILm4ELm4EiE(
+// CHECK-SAME: <16 x i32> noundef [[I44:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I44_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT: [[I1:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store <16 x i32> [[I44]], ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[CAST_MTRUNC:%.*]] = extractelement <16 x i32> [[TMP0]], i32 0
+// CHECK-NEXT: store i32 [[CAST_MTRUNC]], ptr [[I1]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[I1]], align 4
+// CHECK-NEXT: ret i32 [[TMP1]]
+//
+ int trunc_cast6(int4x4 i44) {
+ int i1 = (int)i44;
+ return i1;
+}
+
+// CHECK-LABEL: define hidden noundef i32 @_Z16trunc_multi_castu11matrix_typeILm4ELm4EiE(
+// CHECK-SAME: <16 x i32> noundef [[I44:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I44_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT: [[I1:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store <16 x i32> [[I44]], ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <12 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11>
+// CHECK-NEXT: [[CAST_MTRUNC:%.*]] = extractelement <12 x i32> [[TRUNC]], i32 0
+// CHECK-NEXT: store i32 [[CAST_MTRUNC]], ptr [[I1]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[I1]], align 4
+// CHECK-NEXT: ret i32 [[TMP1]]
+//
+ int trunc_multi_cast(int4x4 i44) {
+ int i1 = (int)(int3x4)i44;
+ return i1;
+}
diff --git a/clang/test/CodeGenHLSL/BasicFeatures/MatrixImplicitTruncation.hlsl b/clang/test/CodeGenHLSL/BasicFeatures/MatrixImplicitTruncation.hlsl
new file mode 100644
index 0000000..e621f68
--- /dev/null
+++ b/clang/test/CodeGenHLSL/BasicFeatures/MatrixImplicitTruncation.hlsl
@@ -0,0 +1,138 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.7-library -disable-llvm-passes -emit-llvm -finclude-default-header -o - %s | FileCheck %s
+
+// CHECK-LABEL: define hidden noundef <12 x i32> @_Z10trunc_castu11matrix_typeILm4ELm4EiE(
+// CHECK-SAME: <16 x i32> noundef [[I44:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I44_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT: [[I34:%.*]] = alloca [12 x i32], align 4
+// CHECK-NEXT: store <16 x i32> [[I44]], ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <12 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11>
+// CHECK-NEXT: store <12 x i32> [[TRUNC]], ptr [[I34]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load <12 x i32>, ptr [[I34]], align 4
+// CHECK-NEXT: ret <12 x i32> [[TMP1]]
+//
+ int3x4 trunc_cast(int4x4 i44) {
+ int3x4 i34 = i44;
+ return i34;
+}
+
+// CHECK-LABEL: define hidden noundef <12 x i32> @_Z11trunc_cast0u11matrix_typeILm4ELm4EiE(
+// CHECK-SAME: <16 x i32> noundef [[I44:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I44_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT: [[I43:%.*]] = alloca [12 x i32], align 4
+// CHECK-NEXT: store <16 x i32> [[I44]], ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <12 x i32> <i32 0, i32 1, i32 2, i32 4, i32 5, i32 6, i32 8, i32 9, i32 10, i32 12, i32 13, i32 14>
+// CHECK-NEXT: store <12 x i32> [[TRUNC]], ptr [[I43]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load <12 x i32>, ptr [[I43]], align 4
+// CHECK-NEXT: ret <12 x i32> [[TMP1]]
+//
+ int4x3 trunc_cast0(int4x4 i44) {
+ int4x3 i43 = i44;
+ return i43;
+}
+
+// CHECK-LABEL: define hidden noundef <9 x i32> @_Z11trunc_cast1u11matrix_typeILm4ELm4EiE(
+// CHECK-SAME: <16 x i32> noundef [[I44:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I44_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT: [[I33:%.*]] = alloca [9 x i32], align 4
+// CHECK-NEXT: store <16 x i32> [[I44]], ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <9 x i32> <i32 0, i32 1, i32 2, i32 4, i32 5, i32 6, i32 8, i32 9, i32 10>
+// CHECK-NEXT: store <9 x i32> [[TRUNC]], ptr [[I33]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load <9 x i32>, ptr [[I33]], align 4
+// CHECK-NEXT: ret <9 x i32> [[TMP1]]
+//
+ int3x3 trunc_cast1(int4x4 i44) {
+ int3x3 i33 = i44;
+ return i33;
+}
+
+// CHECK-LABEL: define hidden noundef <6 x i32> @_Z11trunc_cast2u11matrix_typeILm4ELm4EiE(
+// CHECK-SAME: <16 x i32> noundef [[I44:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I44_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT: [[I32:%.*]] = alloca [6 x i32], align 4
+// CHECK-NEXT: store <16 x i32> [[I44]], ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <6 x i32> <i32 0, i32 1, i32 4, i32 5, i32 8, i32 9>
+// CHECK-NEXT: store <6 x i32> [[TRUNC]], ptr [[I32]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load <6 x i32>, ptr [[I32]], align 4
+// CHECK-NEXT: ret <6 x i32> [[TMP1]]
+//
+ int3x2 trunc_cast2(int4x4 i44) {
+ int3x2 i32 = i44;
+ return i32;
+}
+
+// CHECK-LABEL: define hidden noundef <6 x i32> @_Z11trunc_cast3u11matrix_typeILm4ELm4EiE(
+// CHECK-SAME: <16 x i32> noundef [[I44:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I44_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT: [[I23:%.*]] = alloca [6 x i32], align 4
+// CHECK-NEXT: store <16 x i32> [[I44]], ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <6 x i32> <i32 0, i32 1, i32 2, i32 4, i32 5, i32 6>
+// CHECK-NEXT: store <6 x i32> [[TRUNC]], ptr [[I23]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load <6 x i32>, ptr [[I23]], align 4
+// CHECK-NEXT: ret <6 x i32> [[TMP1]]
+//
+ int2x3 trunc_cast3(int4x4 i44) {
+ int2x3 i23 = i44;
+ return i23;
+}
+
+// CHECK-LABEL: define hidden noundef <4 x i32> @_Z11trunc_cast4u11matrix_typeILm4ELm4EiE(
+// CHECK-SAME: <16 x i32> noundef [[I44:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I44_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT: [[I22:%.*]] = alloca [4 x i32], align 4
+// CHECK-NEXT: store <16 x i32> [[I44]], ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+// CHECK-NEXT: store <4 x i32> [[TRUNC]], ptr [[I22]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr [[I22]], align 4
+// CHECK-NEXT: ret <4 x i32> [[TMP1]]
+//
+ int2x2 trunc_cast4(int4x4 i44) {
+ int2x2 i22 = i44;
+ return i22;
+}
+
+// CHECK-LABEL: define hidden noundef <2 x i32> @_Z11trunc_cast5u11matrix_typeILm4ELm4EiE(
+// CHECK-SAME: <16 x i32> noundef [[I44:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I44_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT: [[I21:%.*]] = alloca [2 x i32], align 4
+// CHECK-NEXT: store <16 x i32> [[I44]], ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TRUNC:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <2 x i32> <i32 0, i32 4>
+// CHECK-NEXT: store <2 x i32> [[TRUNC]], ptr [[I21]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr [[I21]], align 4
+// CHECK-NEXT: ret <2 x i32> [[TMP1]]
+//
+ int2x1 trunc_cast5(int4x4 i44) {
+ int2x1 i21 = i44;
+ return i21;
+}
+
+// CHECK-LABEL: define hidden noundef i32 @_Z11trunc_cast6u11matrix_typeILm4ELm4EiE(
+// CHECK-SAME: <16 x i32> noundef [[I44:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I44_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT: [[I1:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store <16 x i32> [[I44]], ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[I44_ADDR]], align 4
+// CHECK-NEXT: [[CAST_MTRUNC:%.*]] = extractelement <16 x i32> [[TMP0]], i32 0
+// CHECK-NEXT: store i32 [[CAST_MTRUNC]], ptr [[I1]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[I1]], align 4
+// CHECK-NEXT: ret i32 [[TMP1]]
+//
+ int trunc_cast6(int4x4 i44) {
+ int i1 = i44;
+ return i1;
+}
diff --git a/clang/test/CodeGenHLSL/BasicFeatures/OutputArguments.hlsl b/clang/test/CodeGenHLSL/BasicFeatures/OutputArguments.hlsl
index d0ba8f4..ec03804a 100644
--- a/clang/test/CodeGenHLSL/BasicFeatures/OutputArguments.hlsl
+++ b/clang/test/CodeGenHLSL/BasicFeatures/OutputArguments.hlsl
@@ -101,10 +101,16 @@ void funky(inout int3 X) {
// Call the function with the temporary.
// CHECK: call void {{.*}}funky{{.*}}(ptr noalias noundef nonnull align 16 dereferenceable(16) [[ArgTmp]])
-// Shuffle it back.
+// Write it back.
// CHECK: [[RetVal:%.*]] = load <3 x i32>, ptr [[ArgTmp]]
-// CHECK: [[Vxyz:%.*]] = shufflevector <3 x i32> [[RetVal]], <3 x i32> poison, <3 x i32> <i32 2, i32 0, i32 1>
-// CHECK: store <3 x i32> [[Vxyz]], ptr [[V]]
+// CHECK: [[Src0:%.*]] = extractelement <3 x i32> [[RetVal]], i32 0
+// CHECK: [[PtrY:%.*]] = getelementptr <3 x i32>, ptr %V, i32 0, i32 1
+// CHECK: store i32 [[Src0]], ptr [[PtrY]], align 4
+// CHECK: [[Src1:%.*]] = extractelement <3 x i32> [[RetVal]], i32 1
+// CHECK: [[PtrZ:%.*]] = getelementptr <3 x i32>, ptr %V, i32 0, i32 2
+// CHECK: store i32 [[Src1]], ptr [[PtrZ]], align 4
+// CHECK: [[Src2:%.*]] = extractelement <3 x i32> [[RetVal]], i32 2
+// CHECK: store i32 [[Src2]], ptr %V, align 4
// OPT: ret <3 x i32> <i32 3, i32 1, i32 2>
export int3 case4() {
diff --git a/clang/test/CodeGenHLSL/BoolVector.hlsl b/clang/test/CodeGenHLSL/BoolVector.hlsl
index d5054a5..6be90e8 100644
--- a/clang/test/CodeGenHLSL/BoolVector.hlsl
+++ b/clang/test/CodeGenHLSL/BoolVector.hlsl
@@ -69,9 +69,8 @@ bool fn4() {
// CHECK-LABEL: define hidden void {{.*}}fn5{{.*}}
// CHECK: [[Arr:%.*]] = alloca <2 x i32>, align 8
// CHECK-NEXT: store <2 x i32> splat (i32 1), ptr [[Arr]], align 8
-// CHECK-NEXT: [[L:%.*]] = load <2 x i32>, ptr [[Arr]], align 8
-// CHECK-NEXT: [[V:%.*]] = insertelement <2 x i32> [[L]], i32 0, i32 1
-// CHECK-NEXT: store <2 x i32> [[V]], ptr [[Arr]], align 8
+// CHECK-NEXT: [[Ptr:%.*]] = getelementptr <2 x i32>, ptr [[Arr]]
+// CHECK-NEXT: store i32 0, ptr [[Ptr]], align 4
// CHECK-NEXT: ret void
void fn5() {
bool2 Arr = {true,true};
@@ -86,10 +85,9 @@ void fn5() {
// CHECK-NEXT: [[Y:%.*]] = load i32, ptr [[V]], align 4
// CHECK-NEXT: [[LV:%.*]] = trunc i32 [[Y]] to i1
// CHECK-NEXT: [[BV:%.*]] = getelementptr inbounds nuw %struct.S, ptr [[S]], i32 0, i32 0
-// CHECK-NEXT: [[X:%.*]] = load <2 x i32>, ptr [[BV]], align 1
// CHECK-NEXT: [[Z:%.*]] = zext i1 [[LV]] to i32
-// CHECK-NEXT: [[VI:%.*]] = insertelement <2 x i32> [[X]], i32 [[Z]], i32 1
-// CHECK-NEXT: store <2 x i32> [[VI]], ptr [[BV]], align 1
+// CHECK-NEXT: [[Ptr:%.*]] = getelementptr <2 x i32>, ptr [[BV]], i32 0, i32 1
+// CHECK-NEXT: store i32 [[Z]], ptr [[Ptr]], align 4
// CHECK-NEXT: ret void
void fn6() {
bool V = false;
@@ -101,9 +99,8 @@ void fn6() {
// CHECK: [[Arr:%.*]] = alloca [2 x <2 x i32>], align 8
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 8 [[Arr]], ptr align 8 {{.*}}, i32 16, i1 false)
// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x <2 x i32>], ptr [[Arr]], i32 0, i32 0
-// CHECK-NEXT: [[X:%.*]] = load <2 x i32>, ptr [[Idx]], align 8
-// CHECK-NEXT: [[VI:%.*]] = insertelement <2 x i32> [[X]], i32 0, i32 1
-// CHECK-NEXT: store <2 x i32> [[VI]], ptr [[Idx]], align 8
+// CHECK-NEXT: %[[Ptr:.*]] = getelementptr <2 x i32>, ptr [[Idx]], i32 0, i32 1
+// CHECK-NEXT: store i32 0, ptr %[[Ptr]], align 4
// CHECK-NEXT: ret void
void fn7() {
bool2 Arr[2] = {{true,true}, {false,false}};
diff --git a/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl b/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl
index b36682e..5553f8c 100644
--- a/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl
+++ b/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl
@@ -37,9 +37,8 @@ void main(unsigned GI : SV_GroupIndex) {}
// INLINE-NEXT: alloca
// INLINE-NEXT: store i32 12
// INLINE-NEXT: store i32 13
-// INLINE-NEXT: %[[HANDLE:.*]] = call target("dx.CBuffer", target("dx.Layout", %"__cblayout_$Globals", 4, 0))
-// INLINE-NEXT-SAME: @"llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_$Globalss_4_0tt"(i32 0, i32 0, i32 1, i32 0, i1 false)
-// INLINE-NEXT: store target("dx.CBuffer", target("dx.Layout", %"__cblayout_$Globals", 4, 0)) %[[HANDLE]], ptr @"$Globals.cb", align 4
+// INLINE-NEXT: %[[HANDLE:.*]] = call target("dx.CBuffer", %"__cblayout_$Globals") @"llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_s___cblayout_$Globalsst"(i32 0, i32 0, i32 1, i32 0, ptr @"$Globals.str")
+// INLINE-NEXT: store target("dx.CBuffer", %"__cblayout_$Globals") %[[HANDLE]], ptr @"$Globals.cb", align 4
// INLINE-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
// INLINE-NEXT: store i32 %
// INLINE-NEXT: store i32 0
diff --git a/clang/test/CodeGenHLSL/builtins/ScalarSwizzles.hlsl b/clang/test/CodeGenHLSL/builtins/ScalarSwizzles.hlsl
index 7804239..2705982 100644
--- a/clang/test/CodeGenHLSL/builtins/ScalarSwizzles.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/ScalarSwizzles.hlsl
@@ -259,9 +259,8 @@ bool AssignBool(bool V) {
// CHECK-NEXT: [[B:%.*]] = load i32, ptr [[VAddr]], align 4
// CHECK-NEXT: [[LV1:%.*]] = trunc i32 [[B]] to i1
// CHECK-NEXT: [[D:%.*]] = zext i1 [[LV1]] to i32
-// CHECK-NEXT: [[C:%.*]] = load <2 x i32>, ptr [[X]], align 8
-// CHECK-NEXT: [[E:%.*]] = insertelement <2 x i32> [[C]], i32 [[D]], i32 1
-// CHECK-NEXT: store <2 x i32> [[E]], ptr [[X]], align 8
+// CHECK-NEXT: [[C:%.*]] = getelementptr <2 x i32>, ptr [[X]], i32 0, i32 1
+// CHECK-NEXT: store i32 [[D]], ptr [[C]], align 4
// CHECK-NEXT: ret void
void AssignBool2(bool V) {
bool2 X = true.xx;
@@ -277,10 +276,13 @@ void AssignBool2(bool V) {
// CHECK-NEXT: [[Z:%.*]] = load <2 x i32>, ptr [[VAddr]], align 8
// CHECK-NEXT: [[LV:%.*]] = trunc <2 x i32> [[Z]] to <2 x i1>
// CHECK-NEXT: [[B:%.*]] = zext <2 x i1> [[LV]] to <2 x i32>
-// CHECK-NEXT: [[A:%.*]] = load <2 x i32>, ptr [[X]], align 8
-// CHECK-NEXT: [[C:%.*]] = shufflevector <2 x i32> [[B]], <2 x i32> poison, <2 x i32> <i32 0, i32 1>
-// CHECK-NEXT: store <2 x i32> [[C]], ptr [[X]], align 8
+// CHECK-NEXT: [[V1:%.*]] = extractelement <2 x i32> [[B]], i32 0
+// CHECK-NEXT: store i32 [[V1]], ptr [[X]], align 4
+// CHECK-NEXT: [[V2:%.*]] = extractelement <2 x i32> [[B]], i32 1
+// CHECK-NEXT: [[X2:%.*]] = getelementptr <2 x i32>, ptr [[X]], i32 0, i32 1
+// CHECK-NEXT: store i32 [[V2]], ptr [[X2]], align 4
// CHECK-NEXT: ret void
+
void AssignBool3(bool2 V) {
bool2 X = {true,true};
X.xy = V;
@@ -313,10 +315,13 @@ bool2 AccessBools() {
// CHECK-NEXT: [[L1:%.*]] = shufflevector <1 x i32> [[L0]], <1 x i32> poison, <3 x i32> zeroinitializer
// CHECK-NEXT: [[TruncV:%.*]] = trunc <3 x i32> [[L1]] to <3 x i1>
// CHECK-NEXT: [[L2:%.*]] = zext <3 x i1> [[TruncV]] to <3 x i32>
-// CHECK-NEXT: [[L3:%.*]] = load <4 x i32>, ptr [[B]], align 16
-// CHECK-NEXT: [[L4:%.*]] = shufflevector <3 x i32> [[L2]], <3 x i32> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 poison>
-// CHECK-NEXT: [[L5:%.*]] = shufflevector <4 x i32> [[L3]], <4 x i32> [[L4]], <4 x i32> <i32 4, i32 5, i32 6, i32 3>
-// CHECK-NEXT: store <4 x i32> [[L5]], ptr [[B]], align 16
+// CHECK-NEXT: [[V1:%.*]] = extractelement <3 x i32> [[L2]], i32 0
+// CHECK-NEXT: store i32 [[V1]], ptr %B, align 4
+// CHECK-NEXT: [[V2:%.*]] = extractelement <3 x i32> [[L2]], i32 1
+// CHECK-NEXT: [[B2:%.*]] = getelementptr <4 x i32>, ptr %B, i32 0, i32 1
+// CHECK-NEXT: store i32 [[V2]], ptr [[B2]], align 4
+// CHECK-NEXT: [[V3:%.*]] = extractelement <3 x i32> [[L2]], i32 2
+// CHECK-NEXT: [[B3:%.*]] = getelementptr <4 x i32>, ptr %B, i32 0, i32 2
void BoolSizeMismatch() {
bool4 B = {true,true,true,true};
B.xyz = false.xxx;
diff --git a/clang/test/CodeGenHLSL/builtins/VectorElementStore.hlsl b/clang/test/CodeGenHLSL/builtins/VectorElementStore.hlsl
new file mode 100644
index 0000000..e0c3aa5
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/VectorElementStore.hlsl
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -finclude-default-header -emit-llvm -disable-llvm-passes \
+// RUN: -triple dxil-pc-shadermodel6.3-library %s -o - | FileCheck %s
+
+// Test groupshared vector element store for uint.
+// CHECK-LABEL: test_uint4
+// CHECK: [[VAL:%.*]] = load i32, ptr %Val.addr, align 4
+// CHECK: [[IDX:%.*]] = load i32, ptr %Idx.addr, align 4
+// CHECK: [[PTR:%.*]] = getelementptr <4 x i32>, ptr addrspace(3) @SMem, i32 0, i32 [[IDX]]
+// CHECK: store i32 [[VAL]], ptr addrspace(3) [[PTR]], align 4
+// CHECK-: ret void
+groupshared uint4 SMem;
+void test_uint4(uint Idx, uint Val) {
+ SMem[Idx] = Val;
+}
+
+// Test local vector element store for bool.
+// CHECK: [[COND1:%.*]] = load i32, ptr addrspace(3) @Cond, align 4
+// CHECK: [[COND2:%.*]] = trunc i32 [[COND1]] to i1
+// CHECK: [[IDX:%.*]] = load i32, ptr %Idx.addr, align 4
+// CHECK: [[COND3:%.*]] = zext i1 [[COND2]] to i32
+// CHECK: [[PTR:%.*]] = getelementptr <3 x i32>, ptr %Val, i32 0, i32 [[IDX]]
+// CHECK: store i32 [[COND3]], ptr [[PTR]], align 4
+// CHECK: ret
+groupshared bool Cond;
+bool3 test_bool(uint Idx) {
+ bool3 Val = { false, false, false};
+ Val[Idx] = Cond;
+ return Val;
+}
+
+// Test resource vector element store for float.
+// CHECK: [[VAL:%.*]] = load float, ptr %Val.addr, align 4
+// CHECK: [[RES_PTR:%.*]] = call {{.*}} ptr @_ZN4hlsl18RWStructuredBufferIDv4_fEixEj(ptr {{.*}} @_ZL3Buf, i32 noundef 0)
+// CHECK: [[IDX:%.*]] = load i32, ptr %Idx.addr, align 4
+// CHECK: [[PTR:%.*]] = getelementptr <4 x float>, ptr [[RES_PTR]], i32 0, i32 [[IDX]]
+// CHECK: store float [[VAL]], ptr [[PTR]], align 4
+// CHECK: ret void
+RWStructuredBuffer<float4> Buf : register(u0);
+void test_float(uint Idx, float Val) {
+ Buf[0][Idx] = Val;
+}
diff --git a/clang/test/CodeGenHLSL/builtins/VectorSwizzles.hlsl b/clang/test/CodeGenHLSL/builtins/VectorSwizzles.hlsl
new file mode 100644
index 0000000..c632e79
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/VectorSwizzles.hlsl
@@ -0,0 +1,96 @@
+// RUN: %clang_cc1 -finclude-default-header -fnative-half-type \
+// RUN: -triple dxil-pc-shadermodel6.3-library %s -disable-llvm-passes \
+// RUN: -emit-llvm -o - | FileCheck %s
+
+// CHECK-LABEL: Single
+
+// Setup local vars.
+// CHECK: [[VecAddr:%.*]] = alloca <3 x i64>, align 32
+// CHECK-NEXT: [[AAddr:%.*]] = alloca i64, align 8
+// CHECK-NEXT: store <3 x i64> %vec, ptr [[VecAddr]], align 32
+// CHECK-NEXT: store i64 %a, ptr [[AAddr]], align 8
+
+// Update single element of the vector.
+// CHECK-NEXT: [[A:%.*]] = load i64, ptr [[AAddr]], align 8
+// CHECK-NEXT: [[Vy:%.*]] = getelementptr <3 x i64>, ptr [[VecAddr]], i32 0, i32 1
+// CHECK-NEXT: store i64 [[A]], ptr [[Vy]], align 8
+
+// Return.
+// CHECK-NEXT: [[RetVal:%.*]] = load <3 x i64>, ptr [[VecAddr]], align 32
+// CHECK-NEXT: ret <3 x i64> [[RetVal]]
+uint64_t3 Single(uint64_t3 vec, uint64_t a){
+ vec.y = a;
+ return vec;
+}
+
+// CHECK-LABEL: Double
+
+// Setup local vars.
+// CHECK: [[VecAddr:%.*]] = alloca <3 x float>, align 16
+// CHECK-NEXT: [[AAddr:%.*]] = alloca float, align 4
+// CHECK-NEXT: [[BAddr:%.*]] = alloca float, align 4
+// CHECK-NEXT: store <3 x float> %vec, ptr [[VecAddr]], align 16
+// CHECK-NEXT: store float %a, ptr [[AAddr]], align 4
+// CHECK-NEXT: store float %b, ptr [[BAddr]], align 4
+
+// Create temporary vector {a, b}.
+// CHECK-NEXT: [[A:%.*]] = load float, ptr [[AAddr]], align 4
+// CHECK-NEXT: [[TmpVec0:%.*]] = insertelement <2 x float> poison, float [[A]], i32 0
+// CHECK-NEXT: [[B:%.*]] = load float, ptr [[BAddr]], align 4
+// CHECK-NEXT: [[TmpVec1:%.*]] = insertelement <2 x float> [[TmpVec0]], float [[B]], i32 1
+
+// Update two elements of the vector from temporary vector.
+// CHECK-NEXT: [[TmpX:%.*]] = extractelement <2 x float> [[TmpVec1]], i32 0
+// CHECK-NEXT: [[VecZ:%.*]] = getelementptr <3 x float>, ptr [[VecAddr]], i32 0, i32 2
+// CHECK-NEXT: store float [[TmpX]], ptr [[VecZ]], align 4
+// CHECK-NEXT: [[TmpY:%.*]] = extractelement <2 x float> [[TmpVec1]], i32 1
+// CHECK-NEXT: [[VecY:%.*]] = getelementptr <3 x float>, ptr [[VecAddr]], i32 0, i32 1
+// CHECK-NEXT: store float [[TmpY]], ptr [[VecY]], align 4
+
+// Return.
+// CHECK-NEXT: [[RetVal:%.*]] = load <3 x float>, ptr [[VecAddr]], align 16
+// CHECK-NEXT: ret <3 x float> [[RetVal]]
+float3 Double(float3 vec, float a, float b) {
+ vec.zy = {a, b};
+ return vec;
+}
+
+// CHECK-LABEL: Shuffle
+
+// Setup local vars.
+// CHECK: [[VecAddr:%.*]] = alloca <4 x half>, align 8
+// CHECK-NEXT: [[AAddr:%.*]] = alloca half, align 2
+// CHECK-NEXT: [[BAddr:%.*]] = alloca half, align 2
+// CHECK-NEXT: store <4 x half> %vec, ptr [[VecAddr]], align 8
+// CHECK-NEXT: store half %a, ptr [[AAddr]], align 2
+// CHECK-NEXT: store half %b, ptr [[BAddr]], align 2
+
+// Create temporary vector {a, b, 13.74, a}.
+// CHECK-NEXT: [[A:%.*]] = load half, ptr [[AAddr]], align 2
+// CHECK-NEXT: [[TmpVec0:%.*]] = insertelement <4 x half> poison, half [[A]], i32 0
+// CHECK-NEXT: [[B:%.*]] = load half, ptr [[BAddr]], align 2
+// CHECK-NEXT: [[TmpVec1:%.*]] = insertelement <4 x half> [[TmpVec0]], half [[B]], i32 1
+// CHECK-NEXT: [[TmpVec2:%.*]] = insertelement <4 x half> %vecinit1, half 0xH4ADF, i32 2
+// CHECK-NEXT: [[A:%.*]] = load half, ptr [[AAddr]], align 2
+// CHECK-NEXT: [[TmpVec3:%.*]] = insertelement <4 x half> [[TmpVec2]], half [[A]], i32 3
+
+// Update four elements of the vector via mixed up swizzle from the temporary vector.
+// CHECK-NEXT: [[TmpX:%.*]] = extractelement <4 x half> [[TmpVec3]], i32 0
+// CHECK-NEXT: [[VecZ:%.*]] = getelementptr <4 x half>, ptr [[VecAddr]], i32 0, i32 2
+// CHECK-NEXT: store half [[TmpX]], ptr [[VecZ]], align 2
+// CHECK-NEXT: [[TmpY:%.*]] = extractelement <4 x half> [[TmpVec3]], i32 1
+// CHECK-NEXT: [[VecW:%.*]] = getelementptr <4 x half>, ptr [[VecAddr]], i32 0, i32 3
+// CHECK-NEXT: store half [[TmpY]], ptr [[VecW]], align 2
+// CHECK-NEXT: [[TmpZ:%.*]] = extractelement <4 x half> [[TmpVec3]], i32 2
+// CHECK-NEXT: store half [[TmpZ]], ptr [[VecAddr]], align 2
+// CHECK-NEXT: [[TmpW:%.*]] = extractelement <4 x half> [[TmpVec3]], i32 3
+// CHECK-NEXT: [[VecY:%.*]] = getelementptr <4 x half>, ptr [[VecAddr]], i32 0, i32 1
+// CHECK-NEXT: store half [[TmpW]], ptr [[VecY]], align 2
+
+// Return.
+// CHECK-NEXT: [[RetVal:%.*]] = load <4 x half>, ptr [[VecAddr]], align 8
+// CHECK-NEXT: ret <4 x half> [[RetVal]]
+half4 Shuffle(half4 vec, half a, half b) {
+ vec.zwxy = {a, b, 13.74, a};
+ return vec;
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddx-coarse-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/ddx-coarse-builtin.hlsl
new file mode 100644
index 0000000..01216ee
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddx-coarse-builtin.hlsl
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z19test_f16_ddx_coarseDh
+// CHECK: %hlsl.ddx.coarse = call {{.*}} half @llvm.dx.ddx.coarse.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: half @_Z19test_f16_ddx_coarseDh
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} half @llvm.spv.ddx.coarse.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddx.coarse
+half test_f16_ddx_coarse(half val) {
+ return __builtin_hlsl_elementwise_ddx_coarse(val);
+}
+
+// CHECK-LABEL: float @_Z19test_f32_ddx_coarsef
+// CHECK: %hlsl.ddx.coarse = call {{.*}} float @llvm.dx.ddx.coarse.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: float @_Z19test_f32_ddx_coarsef
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} float @llvm.spv.ddx.coarse.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddx.coarse
+float test_f32_ddx_coarse(float val) {
+ return __builtin_hlsl_elementwise_ddx_coarse(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddx-coarse.hlsl b/clang/test/CodeGenHLSL/builtins/ddx-coarse.hlsl
new file mode 100644
index 0000000..c200d47
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddx-coarse.hlsl
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z19test_f16_ddx_coarseDh
+// CHECK: %hlsl.ddx.coarse = call {{.*}} half @llvm.dx.ddx.coarse.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: half @_Z19test_f16_ddx_coarseDh
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} half @llvm.spv.ddx.coarse.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddx.coarse
+half test_f16_ddx_coarse(half val) {
+ return ddx_coarse(val);
+}
+
+// CHECK-LABEL: <2 x half> @_Z20test_f16_ddx_coarse2Dv2_Dh
+// CHECK: %hlsl.ddx.coarse = call {{.*}} <2 x half> @llvm.dx.ddx.coarse.v2f16(<2 x half> %{{.*}})
+// CHECK: ret <2 x half> %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: <2 x half> @_Z20test_f16_ddx_coarse2Dv2_Dh
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} <2 x half> @llvm.spv.ddx.coarse.v2f16(<2 x half> %{{.*}})
+// CHECK-SPIRV: ret <2 x half> %hlsl.ddx.coarse
+half2 test_f16_ddx_coarse2(half2 val) {
+ return ddx_coarse(val);
+}
+
+// CHECK-LABEL: <3 x half> @_Z20test_f16_ddx_coarse3Dv3_Dh
+// CHECK: %hlsl.ddx.coarse = call {{.*}} <3 x half> @llvm.dx.ddx.coarse.v3f16(<3 x half> %{{.*}})
+// CHECK: ret <3 x half> %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: <3 x half> @_Z20test_f16_ddx_coarse3Dv3_Dh
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} <3 x half> @llvm.spv.ddx.coarse.v3f16(<3 x half> %{{.*}})
+// CHECK-SPIRV: ret <3 x half> %hlsl.ddx.coarse
+half3 test_f16_ddx_coarse3(half3 val) {
+ return ddx_coarse(val);
+}
+
+// CHECK-LABEL: <4 x half> @_Z20test_f16_ddx_coarse4Dv4_Dh
+// CHECK: %hlsl.ddx.coarse = call {{.*}} <4 x half> @llvm.dx.ddx.coarse.v4f16(<4 x half> %{{.*}})
+// CHECK: ret <4 x half> %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: <4 x half> @_Z20test_f16_ddx_coarse4Dv4_Dh
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} <4 x half> @llvm.spv.ddx.coarse.v4f16(<4 x half> %{{.*}})
+// CHECK-SPIRV: ret <4 x half> %hlsl.ddx.coarse
+half4 test_f16_ddx_coarse4(half4 val) {
+ return ddx_coarse(val);
+}
+
+// CHECK-LABEL: float @_Z19test_f32_ddx_coarsef
+// CHECK: %hlsl.ddx.coarse = call {{.*}} float @llvm.dx.ddx.coarse.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: float @_Z19test_f32_ddx_coarsef
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} float @llvm.spv.ddx.coarse.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddx.coarse
+float test_f32_ddx_coarse(float val) {
+ return ddx_coarse(val);
+}
+
+// CHECK-LABEL: <2 x float> @_Z20test_f32_ddx_coarse2Dv2_f
+// CHECK: %hlsl.ddx.coarse = call {{.*}} <2 x float> @llvm.dx.ddx.coarse.v2f32(<2 x float> %{{.*}})
+// CHECK: ret <2 x float> %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: <2 x float> @_Z20test_f32_ddx_coarse2Dv2_f
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} <2 x float> @llvm.spv.ddx.coarse.v2f32(<2 x float> %{{.*}})
+// CHECK-SPIRV: ret <2 x float> %hlsl.ddx.coarse
+float2 test_f32_ddx_coarse2(float2 val) {
+ return ddx_coarse(val);
+}
+
+// CHECK-LABEL: <3 x float> @_Z20test_f32_ddx_coarse3Dv3_f
+// CHECK: %hlsl.ddx.coarse = call {{.*}} <3 x float> @llvm.dx.ddx.coarse.v3f32(<3 x float> %{{.*}})
+// CHECK: ret <3 x float> %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: <3 x float> @_Z20test_f32_ddx_coarse3Dv3_f
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} <3 x float> @llvm.spv.ddx.coarse.v3f32(<3 x float> %{{.*}})
+// CHECK-SPIRV: ret <3 x float> %hlsl.ddx.coarse
+float3 test_f32_ddx_coarse3(float3 val) {
+ return ddx_coarse(val);
+}
+
+// CHECK-LABEL: <4 x float> @_Z20test_f32_ddx_coarse4Dv4_f
+// CHECK: %hlsl.ddx.coarse = call {{.*}} <4 x float> @llvm.dx.ddx.coarse.v4f32(<4 x float> %{{.*}})
+// CHECK: ret <4 x float> %hlsl.ddx.coarse
+// CHECK-LABEL-SPIRV: <4 x float> @_Z20test_f32_ddx_coarse4Dv4_f
+// CHECK-SPIRV: %hlsl.ddx.coarse = call {{.*}} <4 x float> @llvm.spv.ddx.coarse.v4f32(<4 x float> %{{.*}})
+// CHECK-SPIRV: ret <4 x float> %hlsl.ddx.coarse
+float4 test_f32_ddx_coarse4(float4 val) {
+ return ddx_coarse(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddy-coarse-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/ddy-coarse-builtin.hlsl
new file mode 100644
index 0000000..2967deb
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddy-coarse-builtin.hlsl
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z19test_f16_ddy_coarseDh
+// CHECK: %hlsl.ddy.coarse = call {{.*}} half @llvm.dx.ddy.coarse.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: half @_Z19test_f16_ddy_coarseDh
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} half @llvm.spv.ddy.coarse.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddy.coarse
+half test_f16_ddy_coarse(half val) {
+ return __builtin_hlsl_elementwise_ddy_coarse(val);
+}
+
+// CHECK-LABEL: float @_Z19test_f32_ddy_coarsef
+// CHECK: %hlsl.ddy.coarse = call {{.*}} float @llvm.dx.ddy.coarse.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: float @_Z19test_f32_ddy_coarsef
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} float @llvm.spv.ddy.coarse.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddy.coarse
+float test_f32_ddy_coarse(float val) {
+ return __builtin_hlsl_elementwise_ddy_coarse(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddy-coarse.hlsl b/clang/test/CodeGenHLSL/builtins/ddy-coarse.hlsl
new file mode 100644
index 0000000..faa972a
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddy-coarse.hlsl
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z19test_f16_ddy_coarseDh
+// CHECK: %hlsl.ddy.coarse = call {{.*}} half @llvm.dx.ddy.coarse.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: half @_Z19test_f16_ddy_coarseDh
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} half @llvm.spv.ddy.coarse.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddy.coarse
+half test_f16_ddy_coarse(half val) {
+ return ddy_coarse(val);
+}
+
+// CHECK-LABEL: <2 x half> @_Z20test_f16_ddy_coarse2Dv2_Dh
+// CHECK: %hlsl.ddy.coarse = call {{.*}} <2 x half> @llvm.dx.ddy.coarse.v2f16(<2 x half> %{{.*}})
+// CHECK: ret <2 x half> %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: <2 x half> @_Z20test_f16_ddy_coarse2Dv2_Dh
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} <2 x half> @llvm.spv.ddy.coarse.v2f16(<2 x half> %{{.*}})
+// CHECK-SPIRV: ret <2 x half> %hlsl.ddy.coarse
+half2 test_f16_ddy_coarse2(half2 val) {
+ return ddy_coarse(val);
+}
+
+// CHECK-LABEL: <3 x half> @_Z20test_f16_ddy_coarse3Dv3_Dh
+// CHECK: %hlsl.ddy.coarse = call {{.*}} <3 x half> @llvm.dx.ddy.coarse.v3f16(<3 x half> %{{.*}})
+// CHECK: ret <3 x half> %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: <3 x half> @_Z20test_f16_ddy_coarse3Dv3_Dh
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} <3 x half> @llvm.spv.ddy.coarse.v3f16(<3 x half> %{{.*}})
+// CHECK-SPIRV: ret <3 x half> %hlsl.ddy.coarse
+half3 test_f16_ddy_coarse3(half3 val) {
+ return ddy_coarse(val);
+}
+
+// CHECK-LABEL: <4 x half> @_Z20test_f16_ddy_coarse4Dv4_Dh
+// CHECK: %hlsl.ddy.coarse = call {{.*}} <4 x half> @llvm.dx.ddy.coarse.v4f16(<4 x half> %{{.*}})
+// CHECK: ret <4 x half> %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: <4 x half> @_Z20test_f16_ddy_coarse4Dv4_Dh
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} <4 x half> @llvm.spv.ddy.coarse.v4f16(<4 x half> %{{.*}})
+// CHECK-SPIRV: ret <4 x half> %hlsl.ddy.coarse
+half4 test_f16_ddy_coarse4(half4 val) {
+ return ddy_coarse(val);
+}
+
+// CHECK-LABEL: float @_Z19test_f32_ddy_coarsef
+// CHECK: %hlsl.ddy.coarse = call {{.*}} float @llvm.dx.ddy.coarse.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: float @_Z19test_f32_ddy_coarsef
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} float @llvm.spv.ddy.coarse.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddy.coarse
+float test_f32_ddy_coarse(float val) {
+ return ddy_coarse(val);
+}
+
+// CHECK-LABEL: <2 x float> @_Z20test_f32_ddy_coarse2Dv2_f
+// CHECK: %hlsl.ddy.coarse = call {{.*}} <2 x float> @llvm.dx.ddy.coarse.v2f32(<2 x float> %{{.*}})
+// CHECK: ret <2 x float> %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: <2 x float> @_Z20test_f32_ddy_coarse2Dv2_f
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} <2 x float> @llvm.spv.ddy.coarse.v2f32(<2 x float> %{{.*}})
+// CHECK-SPIRV: ret <2 x float> %hlsl.ddy.coarse
+float2 test_f32_ddy_coarse2(float2 val) {
+ return ddy_coarse(val);
+}
+
+// CHECK-LABEL: <3 x float> @_Z20test_f32_ddy_coarse3Dv3_f
+// CHECK: %hlsl.ddy.coarse = call {{.*}} <3 x float> @llvm.dx.ddy.coarse.v3f32(<3 x float> %{{.*}})
+// CHECK: ret <3 x float> %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: <3 x float> @_Z20test_f32_ddy_coarse3Dv3_f
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} <3 x float> @llvm.spv.ddy.coarse.v3f32(<3 x float> %{{.*}})
+// CHECK-SPIRV: ret <3 x float> %hlsl.ddy.coarse
+float3 test_f32_ddy_coarse3(float3 val) {
+ return ddy_coarse(val);
+}
+
+// CHECK-LABEL: <4 x float> @_Z20test_f32_ddy_coarse4Dv4_f
+// CHECK: %hlsl.ddy.coarse = call {{.*}} <4 x float> @llvm.dx.ddy.coarse.v4f32(<4 x float> %{{.*}})
+// CHECK: ret <4 x float> %hlsl.ddy.coarse
+// CHECK-LABEL-SPIRV: <4 x float> @_Z20test_f32_ddy_coarse4Dv4_f
+// CHECK-SPIRV: %hlsl.ddy.coarse = call {{.*}} <4 x float> @llvm.spv.ddy.coarse.v4f32(<4 x float> %{{.*}})
+// CHECK-SPIRV: ret <4 x float> %hlsl.ddy.coarse
+float4 test_f32_ddy_coarse4(float4 val) {
+ return ddy_coarse(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/exp-overloads.hlsl b/clang/test/CodeGenHLSL/builtins/exp-overloads.hlsl
index df34bee..c22f012 100644
--- a/clang/test/CodeGenHLSL/builtins/exp-overloads.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/exp-overloads.hlsl
@@ -3,86 +3,86 @@
// RUN: FileCheck %s --check-prefixes=CHECK
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float {{.*}}test_exp_double
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn float @llvm.exp.f32(
-// CHECK: ret float %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.exp.f32(
+// CHECK: ret float [[EXP]]
float test_exp_double(double p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> {{.*}}test_exp_double2
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp.v2f32
-// CHECK: ret <2 x float> %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp.v2f32
+// CHECK: ret <2 x float> [[EXP]]
float2 test_exp_double2(double2 p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> {{.*}}test_exp_double3
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp.v3f32
-// CHECK: ret <3 x float> %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp.v3f32
+// CHECK: ret <3 x float> [[EXP]]
float3 test_exp_double3(double3 p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> {{.*}}test_exp_double4
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp.v4f32
-// CHECK: ret <4 x float> %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp.v4f32
+// CHECK: ret <4 x float> [[EXP]]
float4 test_exp_double4(double4 p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float {{.*}}test_exp_int
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn float @llvm.exp.f32(
-// CHECK: ret float %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.exp.f32(
+// CHECK: ret float [[EXP]]
float test_exp_int(int p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> {{.*}}test_exp_int2
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp.v2f32
-// CHECK: ret <2 x float> %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp.v2f32
+// CHECK: ret <2 x float> [[EXP]]
float2 test_exp_int2(int2 p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> {{.*}}test_exp_int3
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp.v3f32
-// CHECK: ret <3 x float> %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp.v3f32
+// CHECK: ret <3 x float> [[EXP]]
float3 test_exp_int3(int3 p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> {{.*}}test_exp_int4
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp.v4f32
-// CHECK: ret <4 x float> %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp.v4f32
+// CHECK: ret <4 x float> [[EXP]]
float4 test_exp_int4(int4 p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float {{.*}}test_exp_uint
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn float @llvm.exp.f32(
-// CHECK: ret float %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.exp.f32(
+// CHECK: ret float [[EXP]]
float test_exp_uint(uint p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> {{.*}}test_exp_uint2
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp.v2f32
-// CHECK: ret <2 x float> %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp.v2f32
+// CHECK: ret <2 x float> [[EXP]]
float2 test_exp_uint2(uint2 p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> {{.*}}test_exp_uint3
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp.v3f32
-// CHECK: ret <3 x float> %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp.v3f32
+// CHECK: ret <3 x float> [[EXP]]
float3 test_exp_uint3(uint3 p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> {{.*}}test_exp_uint4
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp.v4f32
-// CHECK: ret <4 x float> %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp.v4f32
+// CHECK: ret <4 x float> [[EXP]]
float4 test_exp_uint4(uint4 p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float {{.*}}test_exp_int64_t
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn float @llvm.exp.f32(
-// CHECK: ret float %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.exp.f32(
+// CHECK: ret float [[EXP]]
float test_exp_int64_t(int64_t p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> {{.*}}test_exp_int64_t2
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp.v2f32
-// CHECK: ret <2 x float> %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp.v2f32
+// CHECK: ret <2 x float> [[EXP]]
float2 test_exp_int64_t2(int64_t2 p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> {{.*}}test_exp_int64_t3
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp.v3f32
-// CHECK: ret <3 x float> %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp.v3f32
+// CHECK: ret <3 x float> [[EXP]]
float3 test_exp_int64_t3(int64_t3 p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> {{.*}}test_exp_int64_t4
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp.v4f32
-// CHECK: ret <4 x float> %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp.v4f32
+// CHECK: ret <4 x float> [[EXP]]
float4 test_exp_int64_t4(int64_t4 p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float {{.*}}test_exp_uint64_t
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn float @llvm.exp.f32(
-// CHECK: ret float %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.exp.f32(
+// CHECK: ret float [[EXP]]
float test_exp_uint64_t(uint64_t p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> {{.*}}test_exp_uint64_t2
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp.v2f32
-// CHECK: ret <2 x float> %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp.v2f32
+// CHECK: ret <2 x float> [[EXP]]
float2 test_exp_uint64_t2(uint64_t2 p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> {{.*}}test_exp_uint64_t3
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp.v3f32
-// CHECK: ret <3 x float> %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp.v3f32
+// CHECK: ret <3 x float> [[EXP]]
float3 test_exp_uint64_t3(uint64_t3 p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> {{.*}}test_exp_uint64_t4
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp.v4f32
-// CHECK: ret <4 x float> %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp.v4f32
+// CHECK: ret <4 x float> [[EXP]]
float4 test_exp_uint64_t4(uint64_t4 p0) { return exp(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/exp.hlsl b/clang/test/CodeGenHLSL/builtins/exp.hlsl
index d50ef02..56efb03 100644
--- a/clang/test/CodeGenHLSL/builtins/exp.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/exp.hlsl
@@ -6,47 +6,47 @@
// RUN: FileCheck %s --check-prefixes=CHECK,NO_HALF
// NATIVE_HALF-LABEL: define hidden noundef nofpclass(nan inf) half @_Z13test_exp_half
-// NATIVE_HALF: %elt.exp = call reassoc nnan ninf nsz arcp afn half @llvm.exp.f16(
-// NATIVE_HALF: ret half %elt.exp
+// NATIVE_HALF: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.exp.f16(
+// NATIVE_HALF: ret half [[EXP]]
// NO_HALF-LABEL: define hidden noundef nofpclass(nan inf) float @_Z13test_exp_half
-// NO_HALF: %elt.exp = call reassoc nnan ninf nsz arcp afn float @llvm.exp.f32(
-// NO_HALF: ret float %elt.exp
+// NO_HALF: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.exp.f32(
+// NO_HALF: ret float [[EXP]]
half test_exp_half(half p0) { return exp(p0); }
// NATIVE_HALF-LABEL: define hidden noundef nofpclass(nan inf) <2 x half> @_Z14test_exp_half2
-// NATIVE_HALF: %elt.exp = call reassoc nnan ninf nsz arcp afn <2 x half> @llvm.exp.v2f16
-// NATIVE_HALF: ret <2 x half> %elt.exp
+// NATIVE_HALF: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x half> @llvm.exp.v2f16
+// NATIVE_HALF: ret <2 x half> [[EXP]]
// NO_HALF-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> @_Z14test_exp_half2
-// NO_HALF: %elt.exp = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp.v2f32(
-// NO_HALF: ret <2 x float> %elt.exp
+// NO_HALF: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp.v2f32(
+// NO_HALF: ret <2 x float> [[EXP]]
half2 test_exp_half2(half2 p0) { return exp(p0); }
// NATIVE_HALF-LABEL: define hidden noundef nofpclass(nan inf) <3 x half> @_Z14test_exp_half3
-// NATIVE_HALF: %elt.exp = call reassoc nnan ninf nsz arcp afn <3 x half> @llvm.exp.v3f16
-// NATIVE_HALF: ret <3 x half> %elt.exp
+// NATIVE_HALF: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x half> @llvm.exp.v3f16
+// NATIVE_HALF: ret <3 x half> [[EXP]]
// NO_HALF-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> @_Z14test_exp_half3
-// NO_HALF: %elt.exp = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp.v3f32(
-// NO_HALF: ret <3 x float> %elt.exp
+// NO_HALF: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp.v3f32(
+// NO_HALF: ret <3 x float> [[EXP]]
half3 test_exp_half3(half3 p0) { return exp(p0); }
// NATIVE_HALF-LABEL: define hidden noundef nofpclass(nan inf) <4 x half> @_Z14test_exp_half4
-// NATIVE_HALF: %elt.exp = call reassoc nnan ninf nsz arcp afn <4 x half> @llvm.exp.v4f16
-// NATIVE_HALF: ret <4 x half> %elt.exp
+// NATIVE_HALF: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x half> @llvm.exp.v4f16
+// NATIVE_HALF: ret <4 x half> [[EXP]]
// NO_HALF-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> @_Z14test_exp_half4
-// NO_HALF: %elt.exp = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp.v4f32(
-// NO_HALF: ret <4 x float> %elt.exp
+// NO_HALF: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp.v4f32(
+// NO_HALF: ret <4 x float> [[EXP]]
half4 test_exp_half4(half4 p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z14test_exp_float
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn float @llvm.exp.f32(
-// CHECK: ret float %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.exp.f32(
+// CHECK: ret float [[EXP:%.*]]
float test_exp_float(float p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> @_Z15test_exp_float2
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp.v2f32
-// CHECK: ret <2 x float> %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp.v2f32
+// CHECK: ret <2 x float> [[EXP]]
float2 test_exp_float2(float2 p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> @_Z15test_exp_float3
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp.v3f32
-// CHECK: ret <3 x float> %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp.v3f32
+// CHECK: ret <3 x float> [[EXP]]
float3 test_exp_float3(float3 p0) { return exp(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> @_Z15test_exp_float4
-// CHECK: %elt.exp = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp.v4f32
-// CHECK: ret <4 x float> %elt.exp
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp.v4f32
+// CHECK: ret <4 x float> [[EXP]]
float4 test_exp_float4(float4 p0) { return exp(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/exp2-overloads.hlsl b/clang/test/CodeGenHLSL/builtins/exp2-overloads.hlsl
index 2048277..a8a6f3b 100644
--- a/clang/test/CodeGenHLSL/builtins/exp2-overloads.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/exp2-overloads.hlsl
@@ -3,86 +3,86 @@
// RUN: FileCheck %s --check-prefixes=CHECK
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float {{.*}}test_exp2_double
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn float @llvm.exp2.f32(
-// CHECK: ret float %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.exp2.f32(
+// CHECK: ret float [[EXP2]]
float test_exp2_double(double p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> {{.*}}test_exp2_double2
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp2.v2f32
-// CHECK: ret <2 x float> %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp2.v2f32
+// CHECK: ret <2 x float> [[EXP2]]
float2 test_exp2_double2(double2 p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> {{.*}}test_exp2_double3
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp2.v3f32
-// CHECK: ret <3 x float> %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp2.v3f32
+// CHECK: ret <3 x float> [[EXP2]]
float3 test_exp2_double3(double3 p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> {{.*}}test_exp2_double4
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp2.v4f32
-// CHECK: ret <4 x float> %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp2.v4f32
+// CHECK: ret <4 x float> [[EXP2]]
float4 test_exp2_double4(double4 p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float {{.*}}test_exp2_int
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn float @llvm.exp2.f32(
-// CHECK: ret float %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.exp2.f32(
+// CHECK: ret float [[EXP2]]
float test_exp2_int(int p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> {{.*}}test_exp2_int2
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp2.v2f32
-// CHECK: ret <2 x float> %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp2.v2f32
+// CHECK: ret <2 x float> [[EXP2]]
float2 test_exp2_int2(int2 p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> {{.*}}test_exp2_int3
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp2.v3f32
-// CHECK: ret <3 x float> %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp2.v3f32
+// CHECK: ret <3 x float> [[EXP2]]
float3 test_exp2_int3(int3 p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> {{.*}}test_exp2_int4
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp2.v4f32
-// CHECK: ret <4 x float> %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp2.v4f32
+// CHECK: ret <4 x float> [[EXP2]]
float4 test_exp2_int4(int4 p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float {{.*}}test_exp2_uint
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn float @llvm.exp2.f32(
-// CHECK: ret float %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.exp2.f32(
+// CHECK: ret float [[EXP2]]
float test_exp2_uint(uint p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> {{.*}}test_exp2_uint2
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp2.v2f32
-// CHECK: ret <2 x float> %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp2.v2f32
+// CHECK: ret <2 x float> [[EXP2]]
float2 test_exp2_uint2(uint2 p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> {{.*}}test_exp2_uint3
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp2.v3f32
-// CHECK: ret <3 x float> %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp2.v3f32
+// CHECK: ret <3 x float> [[EXP2]]
float3 test_exp2_uint3(uint3 p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> {{.*}}test_exp2_uint4
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp2.v4f32
-// CHECK: ret <4 x float> %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp2.v4f32
+// CHECK: ret <4 x float> [[EXP2]]
float4 test_exp2_uint4(uint4 p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float {{.*}}test_exp2_int64_t
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn float @llvm.exp2.f32(
-// CHECK: ret float %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.exp2.f32(
+// CHECK: ret float [[EXP2]]
float test_exp2_int64_t(int64_t p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> {{.*}}test_exp2_int64_t2
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp2.v2f32
-// CHECK: ret <2 x float> %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp2.v2f32
+// CHECK: ret <2 x float> [[EXP2]]
float2 test_exp2_int64_t2(int64_t2 p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> {{.*}}test_exp2_int64_t3
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp2.v3f32
-// CHECK: ret <3 x float> %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp2.v3f32
+// CHECK: ret <3 x float> [[EXP2]]
float3 test_exp2_int64_t3(int64_t3 p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> {{.*}}test_exp2_int64_t4
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp2.v4f32
-// CHECK: ret <4 x float> %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp2.v4f32
+// CHECK: ret <4 x float> [[EXP2]]
float4 test_exp2_int64_t4(int64_t4 p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float {{.*}}test_exp2_uint64_t
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn float @llvm.exp2.f32(
-// CHECK: ret float %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.exp2.f32(
+// CHECK: ret float [[EXP2]]
float test_exp2_uint64_t(uint64_t p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> {{.*}}test_exp2_uint64_t2
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp2.v2f32
-// CHECK: ret <2 x float> %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp2.v2f32
+// CHECK: ret <2 x float> [[EXP2]]
float2 test_exp2_uint64_t2(uint64_t2 p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> {{.*}}test_exp2_uint64_t3
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp2.v3f32
-// CHECK: ret <3 x float> %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp2.v3f32
+// CHECK: ret <3 x float> [[EXP2]]
float3 test_exp2_uint64_t3(uint64_t3 p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> {{.*}}test_exp2_uint64_t4
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp2.v4f32
-// CHECK: ret <4 x float> %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp2.v4f32
+// CHECK: ret <4 x float> [[EXP2]]
float4 test_exp2_uint64_t4(uint64_t4 p0) { return exp2(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/exp2.hlsl b/clang/test/CodeGenHLSL/builtins/exp2.hlsl
index ed8cfcf..b4d9c41 100644
--- a/clang/test/CodeGenHLSL/builtins/exp2.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/exp2.hlsl
@@ -6,47 +6,47 @@
// RUN: FileCheck %s --check-prefixes=CHECK,NO_HALF
// NATIVE_HALF-LABEL: define hidden noundef nofpclass(nan inf) half @_Z14test_exp2_half
-// NATIVE_HALF: %elt.exp2 = call reassoc nnan ninf nsz arcp afn half @llvm.exp2.f16(
-// NATIVE_HALF: ret half %elt.exp2
+// NATIVE_HALF: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.exp2.f16(
+// NATIVE_HALF: ret half [[EXP2]]
// NO_HALF-LABEL: define hidden noundef nofpclass(nan inf) float @_Z14test_exp2_half
-// NO_HALF: %elt.exp2 = call reassoc nnan ninf nsz arcp afn float @llvm.exp2.f32(
-// NO_HALF: ret float %elt.exp2
+// NO_HALF: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.exp2.f32(
+// NO_HALF: ret float [[EXP2]]
half test_exp2_half(half p0) { return exp2(p0); }
// NATIVE_HALF-LABEL: define hidden noundef nofpclass(nan inf) <2 x half> @_Z15test_exp2_half2
-// NATIVE_HALF: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <2 x half> @llvm.exp2.v2f16
-// NATIVE_HALF: ret <2 x half> %elt.exp2
+// NATIVE_HALF: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x half> @llvm.exp2.v2f16
+// NATIVE_HALF: ret <2 x half> [[EXP2]]
// NO_HALF-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> @_Z15test_exp2_half2
-// NO_HALF: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp2.v2f32(
-// NO_HALF: ret <2 x float> %elt.exp2
+// NO_HALF: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp2.v2f32(
+// NO_HALF: ret <2 x float> [[EXP2]]
half2 test_exp2_half2(half2 p0) { return exp2(p0); }
// NATIVE_HALF-LABEL: define hidden noundef nofpclass(nan inf) <3 x half> @_Z15test_exp2_half3
-// NATIVE_HALF: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <3 x half> @llvm.exp2.v3f16
-// NATIVE_HALF: ret <3 x half> %elt.exp2
+// NATIVE_HALF: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x half> @llvm.exp2.v3f16
+// NATIVE_HALF: ret <3 x half> [[EXP2]]
// NO_HALF-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> @_Z15test_exp2_half3
-// NO_HALF: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp2.v3f32(
-// NO_HALF: ret <3 x float> %elt.exp2
+// NO_HALF: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp2.v3f32(
+// NO_HALF: ret <3 x float> [[EXP2]]
half3 test_exp2_half3(half3 p0) { return exp2(p0); }
// NATIVE_HALF-LABEL: define hidden noundef nofpclass(nan inf) <4 x half> @_Z15test_exp2_half4
-// NATIVE_HALF: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <4 x half> @llvm.exp2.v4f16
-// NATIVE_HALF: ret <4 x half> %elt.exp2
+// NATIVE_HALF: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x half> @llvm.exp2.v4f16
+// NATIVE_HALF: ret <4 x half> [[EXP2]]
// NO_HALF-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> @_Z15test_exp2_half4
-// NO_HALF: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp2.v4f32(
-// NO_HALF: ret <4 x float> %elt.exp2
+// NO_HALF: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp2.v4f32(
+// NO_HALF: ret <4 x float> [[EXP2]]
half4 test_exp2_half4(half4 p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z15test_exp2_float
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn float @llvm.exp2.f32(
-// CHECK: ret float %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.exp2.f32(
+// CHECK: ret float [[EXP2]]
float test_exp2_float(float p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> @_Z16test_exp2_float2
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp2.v2f32
-// CHECK: ret <2 x float> %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp2.v2f32
+// CHECK: ret <2 x float> [[EXP2]]
float2 test_exp2_float2(float2 p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> @_Z16test_exp2_float3
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp2.v3f32
-// CHECK: ret <3 x float> %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp2.v3f32
+// CHECK: ret <3 x float> [[EXP2]]
float3 test_exp2_float3(float3 p0) { return exp2(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> @_Z16test_exp2_float4
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp2.v4f32
-// CHECK: ret <4 x float> %elt.exp2
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp2.v4f32
+// CHECK: ret <4 x float> [[EXP2]]
float4 test_exp2_float4(float4 p0) { return exp2(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/f16tof32-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/f16tof32-builtin.hlsl
new file mode 100644
index 0000000..65dba66
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/f16tof32-builtin.hlsl
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple \
+// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
+// RUN: -o - | FileCheck %s
+
+// CHECK: define hidden noundef nofpclass(nan inf) float
+// CHECK: %hlsl.f16tof32 = call reassoc nnan ninf nsz arcp afn float @llvm.dx.legacyf16tof32.i32(i32 %0)
+// CHECK: ret float %hlsl.f16tof32
+// CHECK: declare float @llvm.dx.legacyf16tof32.i32(i32)
+float test_scalar(uint p0) { return __builtin_hlsl_elementwise_f16tof32(p0); }
+
+// CHECK: define hidden noundef nofpclass(nan inf) <2 x float>
+// CHECK: %hlsl.f16tof32 = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.dx.legacyf16tof32.v2i32(<2 x i32> %0)
+// CHECK: ret <2 x float> %hlsl.f16tof32
+// CHECK: declare <2 x float> @llvm.dx.legacyf16tof32.v2i32(<2 x i32>)
+float2 test_uint2(uint2 p0) { return __builtin_hlsl_elementwise_f16tof32(p0); }
+
+// CHECK: define hidden noundef nofpclass(nan inf) <3 x float> @_Z10test_uint3Dv3_j(<3 x i32> noundef %p0) #0 {
+// CHECK: %hlsl.f16tof32 = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.dx.legacyf16tof32.v3i32(<3 x i32> %0)
+// CHECK: ret <3 x float> %hlsl.f16tof32
+// CHECK: declare <3 x float> @llvm.dx.legacyf16tof32.v3i32(<3 x i32>)
+float3 test_uint3(uint3 p0) { return __builtin_hlsl_elementwise_f16tof32(p0); }
+
+// CHECK: define hidden noundef nofpclass(nan inf) <4 x float> @_Z10test_uint4Dv4_j(<4 x i32> noundef %p0) #0 {
+// CHECK: %hlsl.f16tof32 = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.dx.legacyf16tof32.v4i32(<4 x i32> %0)
+// CHECK: ret <4 x float> %hlsl.f16tof32
+// CHECK: declare <4 x float> @llvm.dx.legacyf16tof32.v4i32(<4 x i32>)
+float4 test_uint4(uint4 p0) { return __builtin_hlsl_elementwise_f16tof32(p0); }
+
+
+
diff --git a/clang/test/CodeGenHLSL/builtins/f16tof32.hlsl b/clang/test/CodeGenHLSL/builtins/f16tof32.hlsl
new file mode 100644
index 0000000..b68bc19
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/f16tof32.hlsl
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple \
+// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
+// RUN: -o - | FileCheck %s
+
+// CHECK: define hidden noundef nofpclass(nan inf) float
+// CHECK: %hlsl.f16tof32 = call reassoc nnan ninf nsz arcp afn float @llvm.dx.legacyf16tof32.i32(i32 %0)
+// CHECK: ret float %hlsl.f16tof32
+// CHECK: declare float @llvm.dx.legacyf16tof32.i32(i32)
+float test_scalar(uint p0) { return f16tof32(p0); }
+
+// CHECK: define hidden noundef nofpclass(nan inf) <2 x float>
+// CHECK: %hlsl.f16tof32 = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.dx.legacyf16tof32.v2i32(<2 x i32> %0)
+// CHECK: ret <2 x float> %hlsl.f16tof32
+// CHECK: declare <2 x float> @llvm.dx.legacyf16tof32.v2i32(<2 x i32>)
+float2 test_uint2(uint2 p0) { return f16tof32(p0); }
+
+// CHECK: define hidden noundef nofpclass(nan inf) <3 x float> @_Z10test_uint3Dv3_j(<3 x i32> noundef %p0) #0 {
+// CHECK: %hlsl.f16tof32 = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.dx.legacyf16tof32.v3i32(<3 x i32> %0)
+// CHECK: ret <3 x float> %hlsl.f16tof32
+// CHECK: declare <3 x float> @llvm.dx.legacyf16tof32.v3i32(<3 x i32>)
+float3 test_uint3(uint3 p0) { return f16tof32(p0); }
+
+// CHECK: define hidden noundef nofpclass(nan inf) <4 x float> @_Z10test_uint4Dv4_j(<4 x i32> noundef %p0) #0 {
+// CHECK: %hlsl.f16tof32 = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.dx.legacyf16tof32.v4i32(<4 x i32> %0)
+// CHECK: ret <4 x float> %hlsl.f16tof32
+// CHECK: declare <4 x float> @llvm.dx.legacyf16tof32.v4i32(<4 x i32>)
+float4 test_uint4(uint4 p0) { return f16tof32(p0); }
+
+
+
diff --git a/clang/test/CodeGenHLSL/builtins/faceforward.hlsl b/clang/test/CodeGenHLSL/builtins/faceforward.hlsl
index 70459d8..261454e 100644
--- a/clang/test/CodeGenHLSL/builtins/faceforward.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/faceforward.hlsl
@@ -1,9 +1,9 @@
// RUN: %clang_cc1 -finclude-default-header -triple \
// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type -fnative-int16-type \
-// RUN: -emit-llvm -o - | FileCheck %s
+// RUN: -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,DXCHECK
// RUN: %clang_cc1 -finclude-default-header -triple \
// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type -fnative-int16-type \
-// RUN: -emit-llvm -o - | FileCheck %s --check-prefix=SPVCHECK
+// RUN: -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,SPVCHECK
// CHECK-LABEL: test_faceforward_half
// CHECK: %hlsl.dot.i = fmul reassoc nnan ninf nsz arcp afn half %{{.*}}, %{{.*}}
@@ -11,42 +11,31 @@
// CHECK: %fneg.i = fneg reassoc nnan ninf nsz arcp afn half %{{.*}}
// CHECK: %hlsl.select.i = select reassoc nnan ninf nsz arcp afn i1 %cmp.i, half %{{.*}}, half %fneg.i
// CHECK: ret half %hlsl.select.i
-// SPVCHECK-LABEL: test_faceforward_half
-// SPVCHECK: %spv.faceforward.i = call reassoc nnan ninf nsz arcp afn noundef half @llvm.spv.faceforward.f16(half %{{.*}}, half %{{.*}}, half %{{.*}})
-// SPVCHECK: ret half %spv.faceforward.i
half test_faceforward_half(half N, half I, half Ng) { return faceforward(N, I, Ng); }
// CHECK-LABEL: test_faceforward_half2
-// CHECK: %hlsl.dot.i = call reassoc nnan ninf nsz arcp afn half @llvm.dx.fdot.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}})
+// DXCHECK: %hlsl.dot.i = call reassoc nnan ninf nsz arcp afn half @llvm.[[ICF:dx]].fdot.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}})
+// SPVCHECK: %hlsl.dot.i = call reassoc nnan ninf nsz arcp afn half @llvm.[[ICF:spv]].fdot.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}})
// CHECK: %cmp.i = fcmp reassoc nnan ninf nsz arcp afn olt half %hlsl.dot.i, 0xH0000
// CHECK: %fneg.i = fneg reassoc nnan ninf nsz arcp afn <2 x half> %{{.*}}
// CHECK: %hlsl.select.i = select reassoc nnan ninf nsz arcp afn i1 %cmp.i, <2 x half> %{{.*}}, <2 x half> %fneg.i
// CHECK: ret <2 x half> %hlsl.select.i
-// SPVCHECK-LABEL: test_faceforward_half2
-// SPVCHECK: %spv.faceforward.i = call reassoc nnan ninf nsz arcp afn noundef <2 x half> @llvm.spv.faceforward.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}}, <2 x half> %{{.*}})
-// SPVCHECK: ret <2 x half> %spv.faceforward.i
half2 test_faceforward_half2(half2 N, half2 I, half2 Ng) { return faceforward(N, I, Ng); }
// CHECK-LABEL: test_faceforward_half3
-// CHECK: %hlsl.dot.i = call reassoc nnan ninf nsz arcp afn half @llvm.dx.fdot.v3f16(<3 x half> %{{.*}}, <3 x half> %{{.*}})
+// CHECK: %hlsl.dot.i = call reassoc nnan ninf nsz arcp afn half @llvm.[[ICF]].fdot.v3f16(<3 x half> %{{.*}}, <3 x half> %{{.*}})
// CHECK: %cmp.i = fcmp reassoc nnan ninf nsz arcp afn olt half %hlsl.dot.i, 0xH0000
// CHECK: %fneg.i = fneg reassoc nnan ninf nsz arcp afn <3 x half> %{{.*}}
// CHECK: %hlsl.select.i = select reassoc nnan ninf nsz arcp afn i1 %cmp.i, <3 x half> %{{.*}}, <3 x half> %fneg.i
// CHECK: ret <3 x half> %hlsl.select.i
-// SPVCHECK-LABEL: test_faceforward_half3
-// SPVCHECK: %spv.faceforward.i = call reassoc nnan ninf nsz arcp afn noundef <3 x half> @llvm.spv.faceforward.v3f16(<3 x half> %{{.*}}, <3 x half> %{{.*}}, <3 x half> %{{.*}})
-// SPVCHECK: ret <3 x half> %spv.faceforward.i
half3 test_faceforward_half3(half3 N, half3 I, half3 Ng) { return faceforward(N, I, Ng); }
// CHECK-LABEL: test_faceforward_half4
-// CHECK: %hlsl.dot.i = call reassoc nnan ninf nsz arcp afn half @llvm.dx.fdot.v4f16(<4 x half> %{{.*}}, <4 x half> %{{.*}})
+// CHECK: %hlsl.dot.i = call reassoc nnan ninf nsz arcp afn half @llvm.[[ICF]].fdot.v4f16(<4 x half> %{{.*}}, <4 x half> %{{.*}})
// CHECK: %cmp.i = fcmp reassoc nnan ninf nsz arcp afn olt half %hlsl.dot.i, 0xH0000
// CHECK: %fneg.i = fneg reassoc nnan ninf nsz arcp afn <4 x half> %{{.*}}
// CHECK: %hlsl.select.i = select reassoc nnan ninf nsz arcp afn i1 %cmp.i, <4 x half> %{{.*}}, <4 x half> %fneg.i
// CHECK: ret <4 x half> %hlsl.select.i
-// SPVCHECK-LABEL: test_faceforward_half4
-// SPVCHECK: %spv.faceforward.i = call reassoc nnan ninf nsz arcp afn noundef <4 x half> @llvm.spv.faceforward.v4f16(<4 x half> %{{.*}}, <4 x half> %{{.*}}, <4 x half> %{{.*}})
-// SPVCHECK: ret <4 x half> %spv.faceforward.i
half4 test_faceforward_half4(half4 N, half4 I, half4 Ng) { return faceforward(N, I, Ng); }
// CHECK-LABEL: test_faceforward_float
@@ -55,40 +44,28 @@ half4 test_faceforward_half4(half4 N, half4 I, half4 Ng) { return faceforward(N,
// CHECK: %fneg.i = fneg reassoc nnan ninf nsz arcp afn float %{{.*}}
// CHECK: %hlsl.select.i = select reassoc nnan ninf nsz arcp afn i1 %cmp.i, float %{{.*}}, float %fneg.i
// CHECK: ret float %hlsl.select.i
-// SPVCHECK-LABEL: test_faceforward_float
-// SPVCHECK: %spv.faceforward.i = call reassoc nnan ninf nsz arcp afn noundef float @llvm.spv.faceforward.f32(float %{{.*}}, float %{{.*}}, float %{{.*}})
-// SPVCHECK: ret float %spv.faceforward.i
float test_faceforward_float(float N, float I, float Ng) { return faceforward(N, I, Ng); }
// CHECK-LABEL: test_faceforward_float2
-// CHECK: %hlsl.dot.i = call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}})
+// CHECK: %hlsl.dot.i = call reassoc nnan ninf nsz arcp afn float @llvm.[[ICF]].fdot.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}})
// CHECK: %cmp.i = fcmp reassoc nnan ninf nsz arcp afn olt float %hlsl.dot.i, 0.000000e+00
// CHECK: %fneg.i = fneg reassoc nnan ninf nsz arcp afn <2 x float> %{{.*}}
// CHECK: %hlsl.select.i = select reassoc nnan ninf nsz arcp afn i1 %cmp.i, <2 x float> %{{.*}}, <2 x float> %fneg.i
// CHECK: ret <2 x float> %hlsl.select.i
-// SPVCHECK-LABEL: test_faceforward_float2
-// SPVCHECK: %spv.faceforward.i = call reassoc nnan ninf nsz arcp afn noundef <2 x float> @llvm.spv.faceforward.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}})
-// SPVCHECK: ret <2 x float> %spv.faceforward.i
float2 test_faceforward_float2(float2 N, float2 I, float2 Ng) { return faceforward(N, I, Ng); }
// CHECK-LABEL: test_faceforward_float3
-// CHECK: %hlsl.dot.i = call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}})
+// CHECK: %hlsl.dot.i = call reassoc nnan ninf nsz arcp afn float @llvm.[[ICF]].fdot.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}})
// CHECK: %cmp.i = fcmp reassoc nnan ninf nsz arcp afn olt float %hlsl.dot.i, 0.000000e+00
// CHECK: %fneg.i = fneg reassoc nnan ninf nsz arcp afn <3 x float> %{{.*}}
// CHECK: %hlsl.select.i = select reassoc nnan ninf nsz arcp afn i1 %cmp.i, <3 x float> %{{.*}}, <3 x float> %fneg.i
// CHECK: ret <3 x float> %hlsl.select.i
-// SPVCHECK-LABEL: test_faceforward_float3
-// SPVCHECK: %spv.faceforward.i = call reassoc nnan ninf nsz arcp afn noundef <3 x float> @llvm.spv.faceforward.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}}, <3 x float> %{{.*}})
-// SPVCHECK: ret <3 x float> %spv.faceforward.i
float3 test_faceforward_float3(float3 N, float3 I, float3 Ng) { return faceforward(N, I, Ng); }
// CHECK-LABEL: test_faceforward_float4
-// CHECK: %hlsl.dot.i = call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}})
+// CHECK: %hlsl.dot.i = call reassoc nnan ninf nsz arcp afn float @llvm.[[ICF]].fdot.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}})
// CHECK: %cmp.i = fcmp reassoc nnan ninf nsz arcp afn olt float %hlsl.dot.i, 0.000000e+00
// CHECK: %fneg.i = fneg reassoc nnan ninf nsz arcp afn <4 x float> %{{.*}}
// CHECK: %hlsl.select.i = select reassoc nnan ninf nsz arcp afn i1 %cmp.i, <4 x float> %{{.*}}, <4 x float> %fneg.i
// CHECK: ret <4 x float> %hlsl.select.i
-// SPVCHECK-LABEL: test_faceforward_float4
-// SPVCHECK: %spv.faceforward.i = call reassoc nnan ninf nsz arcp afn noundef <4 x float> @llvm.spv.faceforward.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
-// SPVCHECK: ret <4 x float> %spv.faceforward.i
float4 test_faceforward_float4(float4 N, float4 I, float4 Ng) { return faceforward(N, I, Ng); }
diff --git a/clang/test/CodeGenHLSL/builtins/firstbithigh.hlsl b/clang/test/CodeGenHLSL/builtins/firstbithigh.hlsl
index 368d652..51b0f81 100644
--- a/clang/test/CodeGenHLSL/builtins/firstbithigh.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/firstbithigh.hlsl
@@ -1,161 +1,260 @@
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
-// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type -fnative-int16-type \
-// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s -DTARGET=dx
+// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \
+// RUN: -fnative-int16-type -emit-llvm -O1 -o - | FileCheck %s -DTARGET=dx \
+// RUN: --check-prefixes=CHECK,DXCHECK
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
-// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type -fnative-int16-type \
-// RUN: -emit-llvm -disable-llvm-passes \
-// RUN: -o - | FileCheck %s -DTARGET=spv
+// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \
+// RUN: -fnative-int16-type -emit-llvm -O1 -o - | FileCheck %s -DTARGET=spv
#ifdef __HLSL_ENABLE_16_BIT
// CHECK-LABEL: test_firstbithigh_ushort
-// CHECK: call i32 @llvm.[[TARGET]].firstbituhigh.i16
+// CHECK: [[FBH:%.*]] = tail call {{.*}}i32 @llvm.[[TARGET]].firstbituhigh.i16
+// DXCHECK-NEXT: [[SUB:%.*]] = sub i32 15, [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq i32 [[FBH]], -1
+// DXCHECK-NEXT: select i1 %cmp.i, i32 -1, i32 [[SUB]]
+// CHECK-NEXT: ret i32
uint test_firstbithigh_ushort(uint16_t p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_ushort2
-// CHECK: call <2 x i32> @llvm.[[TARGET]].firstbituhigh.v2i16
+// CHECK: [[FBH:%.*]] = tail call {{.*}}<2 x i32> @llvm.[[TARGET]].firstbituhigh.v2i16
+// DXCHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> splat (i32 15), [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <2 x i32> [[FBH]], splat (i32 -1)
+// DXCHECK-NEXT: select <2 x i1> %cmp.i, <2 x i32> splat (i32 -1), <2 x i32> [[SUB]]
+// CHECK-NEXT: ret <2 x i32>
uint2 test_firstbithigh_ushort2(uint16_t2 p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_ushort3
-// CHECK: call <3 x i32> @llvm.[[TARGET]].firstbituhigh.v3i16
+// CHECK: [[FBH:%.*]] = tail call {{.*}}<3 x i32> @llvm.[[TARGET]].firstbituhigh.v3i16
+// DXCHECK-NEXT: [[SUB:%.*]] = sub <3 x i32> splat (i32 15), [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <3 x i32> [[FBH]], splat (i32 -1)
+// DXCHECK-NEXT: select <3 x i1> %cmp.i, <3 x i32> splat (i32 -1), <3 x i32> [[SUB]]
+// CHECK-NEXT: ret <3 x i32>
uint3 test_firstbithigh_ushort3(uint16_t3 p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_ushort4
-// CHECK: call <4 x i32> @llvm.[[TARGET]].firstbituhigh.v4i16
+// CHECK: [[FBH:%.*]] = tail call {{.*}}<4 x i32> @llvm.[[TARGET]].firstbituhigh.v4i16
+// DXCHECK-NEXT: [[SUB:%.*]] = sub <4 x i32> splat (i32 15), [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <4 x i32> [[FBH]], splat (i32 -1)
+// DXCHECK-NEXT: select <4 x i1> %cmp.i, <4 x i32> splat (i32 -1), <4 x i32> [[SUB]]
+// CHECK-NEXT: ret <4 x i32>
uint4 test_firstbithigh_ushort4(uint16_t4 p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_short
-// CHECK: call i32 @llvm.[[TARGET]].firstbitshigh.i16
+// CHECK: [[FBH:%.*]] = tail call {{.*}}i32 @llvm.[[TARGET]].firstbitshigh.i16
+// DXCHECK-NEXT: [[SUB:%.*]] = sub i32 15, [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq i32 [[FBH]], -1
+// DXCHECK-NEXT: select i1 %cmp.i, i32 -1, i32 [[SUB]]
+// CHECK-NEXT: ret i32
uint test_firstbithigh_short(int16_t p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_short2
-// CHECK: call <2 x i32> @llvm.[[TARGET]].firstbitshigh.v2i16
+// CHECK: [[FBH:%.*]] = tail call {{.*}}<2 x i32> @llvm.[[TARGET]].firstbitshigh.v2i16
+// DXCHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> splat (i32 15), [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <2 x i32> [[FBH]], splat (i32 -1)
+// DXCHECK-NEXT: select <2 x i1> %cmp.i, <2 x i32> splat (i32 -1), <2 x i32> [[SUB]]
+// CHECK-NEXT: ret <2 x i32>
uint2 test_firstbithigh_short2(int16_t2 p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_short3
-// CHECK: call <3 x i32> @llvm.[[TARGET]].firstbitshigh.v3i16
+// CHECK: [[FBH:%.*]] = tail call {{.*}}<3 x i32> @llvm.[[TARGET]].firstbitshigh.v3i16
+// DXCHECK-NEXT: [[SUB:%.*]] = sub <3 x i32> splat (i32 15), [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <3 x i32> [[FBH]], splat (i32 -1)
+// DXCHECK-NEXT: select <3 x i1> %cmp.i, <3 x i32> splat (i32 -1), <3 x i32> [[SUB]]
+// CHECK-NEXT: ret <3 x i32>
uint3 test_firstbithigh_short3(int16_t3 p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_short4
-// CHECK: call <4 x i32> @llvm.[[TARGET]].firstbitshigh.v4i16
+// CHECK: [[FBH:%.*]] = tail call {{.*}}<4 x i32> @llvm.[[TARGET]].firstbitshigh.v4i16
+// DXCHECK-NEXT: [[SUB:%.*]] = sub <4 x i32> splat (i32 15), [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <4 x i32> [[FBH]], splat (i32 -1)
+// DXCHECK-NEXT: select <4 x i1> %cmp.i, <4 x i32> splat (i32 -1), <4 x i32> [[SUB]]
+// CHECK-NEXT: ret <4 x i32>
uint4 test_firstbithigh_short4(int16_t4 p0) {
return firstbithigh(p0);
}
#endif // __HLSL_ENABLE_16_BIT
// CHECK-LABEL: test_firstbithigh_uint
-// CHECK: call i32 @llvm.[[TARGET]].firstbituhigh.i32
+// CHECK: [[FBH:%.*]] = tail call {{.*}}i32 @llvm.[[TARGET]].firstbituhigh.i32
+// DXCHECK-NEXT: [[SUB:%.*]] = sub i32 31, [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq i32 [[FBH]], -1
+// DXCHECK-NEXT: select i1 %cmp.i, i32 -1, i32 [[SUB]]
+// CHECK-NEXT: ret i32
uint test_firstbithigh_uint(uint p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_uint2
-// CHECK: call <2 x i32> @llvm.[[TARGET]].firstbituhigh.v2i32
+// CHECK: [[FBH:%.*]] = tail call {{.*}}<2 x i32> @llvm.[[TARGET]].firstbituhigh.v2i32
+// DXCHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> splat (i32 31), [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <2 x i32> [[FBH]], splat (i32 -1)
+// DXCHECK-NEXT: select <2 x i1> %cmp.i, <2 x i32> splat (i32 -1), <2 x i32> [[SUB]]
+// CHECK-NEXT: ret <2 x i32>
uint2 test_firstbithigh_uint2(uint2 p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_uint3
-// CHECK: call <3 x i32> @llvm.[[TARGET]].firstbituhigh.v3i32
+// CHECK: [[FBH:%.*]] = tail call {{.*}}<3 x i32> @llvm.[[TARGET]].firstbituhigh.v3i32
+// DXCHECK-NEXT: [[SUB:%.*]] = sub <3 x i32> splat (i32 31), [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <3 x i32> [[FBH]], splat (i32 -1)
+// DXCHECK-NEXT: select <3 x i1> %cmp.i, <3 x i32> splat (i32 -1), <3 x i32> [[SUB]]
+// CHECK-NEXT: ret <3 x i32>
uint3 test_firstbithigh_uint3(uint3 p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_uint4
-// CHECK: call <4 x i32> @llvm.[[TARGET]].firstbituhigh.v4i32
+// CHECK: [[FBH:%.*]] = tail call {{.*}}<4 x i32> @llvm.[[TARGET]].firstbituhigh.v4i32
+// DXCHECK-NEXT: [[SUB:%.*]] = sub <4 x i32> splat (i32 31), [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <4 x i32> [[FBH]], splat (i32 -1)
+// DXCHECK-NEXT: select <4 x i1> %cmp.i, <4 x i32> splat (i32 -1), <4 x i32> [[SUB]]
+// CHECK-NEXT: ret <4 x i32>
uint4 test_firstbithigh_uint4(uint4 p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_ulong
-// CHECK: call i32 @llvm.[[TARGET]].firstbituhigh.i64
+// CHECK: [[FBH:%.*]] = tail call {{.*}}i32 @llvm.[[TARGET]].firstbituhigh.i64
+// DXCHECK-NEXT: [[SUB:%.*]] = sub i32 63, [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq i32 [[FBH]], -1
+// DXCHECK-NEXT: select i1 %cmp.i, i32 -1, i32 [[SUB]]
+// CHECK-NEXT: ret i32
uint test_firstbithigh_ulong(uint64_t p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_ulong2
-// CHECK: call <2 x i32> @llvm.[[TARGET]].firstbituhigh.v2i64
+// CHECK: [[FBH:%.*]] = tail call {{.*}}<2 x i32> @llvm.[[TARGET]].firstbituhigh.v2i64
+// DXCHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> splat (i32 63), [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <2 x i32> [[FBH]], splat (i32 -1)
+// DXCHECK-NEXT: select <2 x i1> %cmp.i, <2 x i32> splat (i32 -1), <2 x i32> [[SUB]]
+// CHECK-NEXT: ret <2 x i32>
uint2 test_firstbithigh_ulong2(uint64_t2 p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_ulong3
-// CHECK: call <3 x i32> @llvm.[[TARGET]].firstbituhigh.v3i64
+// CHECK: [[FBH:%.*]] = tail call {{.*}}<3 x i32> @llvm.[[TARGET]].firstbituhigh.v3i64
+// DXCHECK-NEXT: [[SUB:%.*]] = sub <3 x i32> splat (i32 63), [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <3 x i32> [[FBH]], splat (i32 -1)
+// DXCHECK-NEXT: select <3 x i1> %cmp.i, <3 x i32> splat (i32 -1), <3 x i32> [[SUB]]
+// CHECK-NEXT: ret <3 x i32>
uint3 test_firstbithigh_ulong3(uint64_t3 p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_ulong4
-// CHECK: call <4 x i32> @llvm.[[TARGET]].firstbituhigh.v4i64
+// CHECK: [[FBH:%.*]] = tail call {{.*}}<4 x i32> @llvm.[[TARGET]].firstbituhigh.v4i64
+// DXCHECK-NEXT: [[SUB:%.*]] = sub <4 x i32> splat (i32 63), [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <4 x i32> [[FBH]], splat (i32 -1)
+// DXCHECK-NEXT: select <4 x i1> %cmp.i, <4 x i32> splat (i32 -1), <4 x i32> [[SUB]]
+// CHECK-NEXT: ret <4 x i32>
uint4 test_firstbithigh_ulong4(uint64_t4 p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_int
-// CHECK: call i32 @llvm.[[TARGET]].firstbitshigh.i32
+// CHECK: [[FBH:%.*]] = tail call {{.*}}i32 @llvm.[[TARGET]].firstbitshigh.i32
+// DXCHECK-NEXT: [[SUB:%.*]] = sub i32 31, [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq i32 [[FBH]], -1
+// DXCHECK-NEXT: select i1 %cmp.i, i32 -1, i32 [[SUB]]
+// CHECK-NEXT: ret i32
uint test_firstbithigh_int(int p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_int2
-// CHECK: call <2 x i32> @llvm.[[TARGET]].firstbitshigh.v2i32
+// CHECK: [[FBH:%.*]] = tail call {{.*}}<2 x i32> @llvm.[[TARGET]].firstbitshigh.v2i32
+// DXCHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> splat (i32 31), [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <2 x i32> [[FBH]], splat (i32 -1)
+// DXCHECK-NEXT: select <2 x i1> %cmp.i, <2 x i32> splat (i32 -1), <2 x i32> [[SUB]]
+// CHECK-NEXT: ret <2 x i32>
uint2 test_firstbithigh_int2(int2 p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_int3
-// CHECK: call <3 x i32> @llvm.[[TARGET]].firstbitshigh.v3i32
+// CHECK: [[FBH:%.*]] = tail call {{.*}}<3 x i32> @llvm.[[TARGET]].firstbitshigh.v3i32
+// DXCHECK-NEXT: [[SUB:%.*]] = sub <3 x i32> splat (i32 31), [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <3 x i32> [[FBH]], splat (i32 -1)
+// DXCHECK-NEXT: select <3 x i1> %cmp.i, <3 x i32> splat (i32 -1), <3 x i32> [[SUB]]
+// CHECK-NEXT: ret <3 x i32>
uint3 test_firstbithigh_int3(int3 p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_int4
-// CHECK: call <4 x i32> @llvm.[[TARGET]].firstbitshigh.v4i32
+// CHECK: [[FBH:%.*]] = tail call {{.*}}<4 x i32> @llvm.[[TARGET]].firstbitshigh.v4i32
+// DXCHECK-NEXT: [[SUB:%.*]] = sub <4 x i32> splat (i32 31), [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <4 x i32> [[FBH]], splat (i32 -1)
+// DXCHECK-NEXT: select <4 x i1> %cmp.i, <4 x i32> splat (i32 -1), <4 x i32> [[SUB]]
+// CHECK-NEXT: ret <4 x i32>
uint4 test_firstbithigh_int4(int4 p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_long
-// CHECK: call i32 @llvm.[[TARGET]].firstbitshigh.i64
+// CHECK: [[FBH:%.*]] = tail call {{.*}}i32 @llvm.[[TARGET]].firstbitshigh.i64
+// DXCHECK-NEXT: [[SUB:%.*]] = sub i32 63, [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq i32 [[FBH]], -1
+// DXCHECK-NEXT: select i1 %cmp.i, i32 -1, i32 [[SUB]]
+// CHECK-NEXT: ret i32
uint test_firstbithigh_long(int64_t p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_long2
-// CHECK: call <2 x i32> @llvm.[[TARGET]].firstbitshigh.v2i64
+// CHECK: [[FBH:%.*]] = tail call {{.*}}<2 x i32> @llvm.[[TARGET]].firstbitshigh.v2i64
+// DXCHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> splat (i32 63), [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <2 x i32> [[FBH]], splat (i32 -1)
+// DXCHECK-NEXT: select <2 x i1> %cmp.i, <2 x i32> splat (i32 -1), <2 x i32> [[SUB]]
+// CHECK-NEXT: ret <2 x i32>
uint2 test_firstbithigh_long2(int64_t2 p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_long3
-// CHECK: call <3 x i32> @llvm.[[TARGET]].firstbitshigh.v3i64
+// CHECK: [[FBH:%.*]] = tail call {{.*}}<3 x i32> @llvm.[[TARGET]].firstbitshigh.v3i64
+// DXCHECK-NEXT: [[SUB:%.*]] = sub <3 x i32> splat (i32 63), [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <3 x i32> [[FBH]], splat (i32 -1)
+// DXCHECK-NEXT: select <3 x i1> %cmp.i, <3 x i32> splat (i32 -1), <3 x i32> [[SUB]]
+// CHECK-NEXT: ret <3 x i32>
uint3 test_firstbithigh_long3(int64_t3 p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_long4
-// CHECK: call <4 x i32> @llvm.[[TARGET]].firstbitshigh.v4i64
+// CHECK: [[FBH:%.*]] = tail call {{.*}}<4 x i32> @llvm.[[TARGET]].firstbitshigh.v4i64
+// DXCHECK-NEXT: [[SUB:%.*]] = sub <4 x i32> splat (i32 63), [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <4 x i32> [[FBH]], splat (i32 -1)
+// DXCHECK-NEXT: select <4 x i1> %cmp.i, <4 x i32> splat (i32 -1), <4 x i32> [[SUB]]
+// CHECK-NEXT: ret <4 x i32>
uint4 test_firstbithigh_long4(int64_t4 p0) {
return firstbithigh(p0);
}
// CHECK-LABEL: test_firstbithigh_upcast
-// CHECK: [[FBH:%.*]] = call <4 x i32> @llvm.[[TARGET]].firstbituhigh.v4i32(<4 x i32> %{{.*}})
-// CHECK: [[CONV:%.*]] = zext <4 x i32> [[FBH]] to <4 x i64>
-// CHECK: ret <4 x i64> [[CONV]]
+// CHECK: [[FBH:%.*]] = tail call {{.*}}<4 x i32> @llvm.[[TARGET]].firstbituhigh.v4i32(<4 x i32> %{{.*}})
+// DXCHECK-NEXT: [[SUB:%.*]] = sub <4 x i32> splat (i32 31), [[FBH]]
+// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <4 x i32> [[FBH]], splat (i32 -1)
+// DXCHECK-NEXT: select <4 x i1> %cmp.i, <4 x i32> splat (i32 -1), <4 x i32> [[SUB]]
+// CHECK-NEXT: [[ZEXT:%.*]] = zext <4 x i32> {{.*}} to <4 x i64>
+// CHECK-NEXT: ret <4 x i64> [[ZEXT]]
uint64_t4 test_firstbithigh_upcast(uint4 p0) {
return firstbithigh(p0);
}
diff --git a/clang/test/CodeGenHLSL/builtins/fwidth.hlsl b/clang/test/CodeGenHLSL/builtins/fwidth.hlsl
new file mode 100644
index 0000000..2935fbb
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/fwidth.hlsl
@@ -0,0 +1,118 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-unknown-vulkan1.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: define {{.*}} half @_ZN4hlsl8__detail11fwidth_implIDhEET_S2_
+// CHECK: %hlsl.ddx.coarse = call {{.*}} half @llvm.dx.ddx.coarse.f16(half %{{.*}})
+// CHECK: %{{.*}} = call {{.*}} half @llvm.fabs.f16(half %{{.*}})
+// CHECK: %hlsl.ddy.coarse = call {{.*}} half @llvm.dx.ddy.coarse.f16(half %{{.*}})
+// CHECK: %{{.*}} = call {{.*}} half @llvm.fabs.f16(half %{{.*}})
+// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
+// CHECK: ret half %{{.*}}
+// CHECK-LABEL-SPIRV: half @_Z15test_f16_fwidthDh
+// CHECK-SPIRV: %spv.fwidth = call {{.*}} half @llvm.spv.fwidth.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %spv.fwidth
+half test_f16_fwidth(half val) {
+ return fwidth(val);
+}
+
+// CHECK-LABEL: define {{.*}} <2 x half> @_ZN4hlsl8__detail11fwidth_implIDv2_DhEET_S3_
+// CHECK: %hlsl.ddx.coarse = call {{.*}} <2 x half> @llvm.dx.ddx.coarse.v2f16(<2 x half> %{{.*}})
+// CHECK: %{{.*}} = call {{.*}} <2 x half> @llvm.fabs.v2f16(<2 x half> %{{.*}})
+// CHECK: %hlsl.ddy.coarse = call {{.*}} <2 x half> @llvm.dx.ddy.coarse.v2f16(<2 x half> %{{.*}})
+// CHECK: %{{.*}} = call {{.*}} <2 x half> @llvm.fabs.v2f16(<2 x half> %{{.*}})
+// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
+// CHECK: ret <2 x half> %{{.*}}
+// CHECK-LABEL-SPIRV: <2 x half> @_Z16test_f16_fwidth2Dv2_Dh
+// CHECK-SPIRV: %spv.fwidth = call {{.*}} <2 x half> @llvm.spv.fwidth.v2f16(<2 x half> %{{.*}})
+// CHECK-SPIRV: ret <2 x half> %spv.fwidth
+half2 test_f16_fwidth2(half2 val) {
+ return fwidth(val);
+}
+
+// CHECK-LABEL: define {{.*}} <3 x half> @_ZN4hlsl8__detail11fwidth_implIDv3_DhEET_S3_
+// CHECK: %hlsl.ddx.coarse = call {{.*}} <3 x half> @llvm.dx.ddx.coarse.v3f16(<3 x half> %{{.*}})
+// CHECK: %{{.*}} = call {{.*}} <3 x half> @llvm.fabs.v3f16(<3 x half> %{{.*}})
+// CHECK: %hlsl.ddy.coarse = call {{.*}} <3 x half> @llvm.dx.ddy.coarse.v3f16(<3 x half> %{{.*}})
+// CHECK: %{{.*}} = call {{.*}} <3 x half> @llvm.fabs.v3f16(<3 x half> %{{.*}})
+// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
+// CHECK: ret <3 x half> %{{.*}}
+// CHECK-LABEL-SPIRV: <3 x half> @_Z16test_f16_fwidth3Dv3_Dh
+// CHECK-SPIRV: %spv.fwidth = call {{.*}} <3 x half> @llvm.spv.fwidth.v3f16(<3 x half> %{{.*}})
+// CHECK-SPIRV: ret <3 x half> %spv.fwidth
+half3 test_f16_fwidth3(half3 val) {
+ return fwidth(val);
+}
+
+// CHECK-LABEL: define {{.*}} <4 x half> @_ZN4hlsl8__detail11fwidth_implIDv4_DhEET_S3_
+// CHECK: %hlsl.ddx.coarse = call {{.*}} <4 x half> @llvm.dx.ddx.coarse.v4f16(<4 x half> %{{.*}})
+// CHECK: %{{.*}} = call {{.*}} <4 x half> @llvm.fabs.v4f16(<4 x half> %{{.*}})
+// CHECK: %hlsl.ddy.coarse = call {{.*}} <4 x half> @llvm.dx.ddy.coarse.v4f16(<4 x half> %{{.*}})
+// CHECK: %{{.*}} = call {{.*}} <4 x half> @llvm.fabs.v4f16(<4 x half> %{{.*}})
+// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
+// CHECK: ret <4 x half> %{{.*}}
+// CHECK-LABEL-SPIRV: <4 x half> @_Z16test_f16_fwidth4Dv4_Dh
+// CHECK-SPIRV: %spv.fwidth = call {{.*}} <4 x half> @llvm.spv.fwidth.v4f16(<4 x half> %{{.*}})
+// CHECK-SPIRV: ret <4 x half> %spv.fwidth
+half4 test_f16_fwidth4(half4 val) {
+ return fwidth(val);
+}
+
+// CHECK-LABEL: define {{.*}} float @_ZN4hlsl8__detail11fwidth_implIfEET_S2_
+// CHECK: %hlsl.ddx.coarse = call {{.*}} float @llvm.dx.ddx.coarse.f32(float %{{.*}})
+// CHECK: %{{.*}} = call {{.*}} float @llvm.fabs.f32(float %{{.*}})
+// CHECK: %hlsl.ddy.coarse = call {{.*}} float @llvm.dx.ddy.coarse.f32(float %{{.*}})
+// CHECK: %{{.*}} = call {{.*}} float @llvm.fabs.f32(float %{{.*}})
+// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
+// CHECK: ret float %{{.*}}
+// CHECK-LABEL-SPIRV: float @_Z15test_f32_fwidthf
+// CHECK-SPIRV: %spv.fwidth = call {{.*}} float @llvm.spv.fwidth.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %spv.fwidth
+float test_f32_fwidth(float val) {
+ return fwidth(val);
+}
+
+// CHECK-LABEL: define {{.*}} <2 x float> @_ZN4hlsl8__detail11fwidth_implIDv2_fEET_S3_
+// CHECK: %hlsl.ddx.coarse = call {{.*}} <2 x float> @llvm.dx.ddx.coarse.v2f32(<2 x float> %{{.*}})
+// CHECK: %{{.*}} = call {{.*}} <2 x float> @llvm.fabs.v2f32(<2 x float> %{{.*}})
+// CHECK: %hlsl.ddy.coarse = call {{.*}} <2 x float> @llvm.dx.ddy.coarse.v2f32(<2 x float> %{{.*}})
+// CHECK: %{{.*}} = call {{.*}} <2 x float> @llvm.fabs.v2f32(<2 x float> %{{.*}})
+// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
+// CHECK: ret <2 x float> %{{.*}}
+// CHECK-LABEL-SPIRV: <2 x float> @_Z16test_f32_fwidth2Dv2_f
+// CHECK-SPIRV: %spv.fwidth = call {{.*}} <2 x float> @llvm.spv.fwidth.v2f32(<2 x float> %{{.*}})
+// CHECK-SPIRV: ret <2 x float> %spv.fwidth
+float2 test_f32_fwidth2(float2 val) {
+ return fwidth(val);
+}
+
+// CHECK-LABEL: define {{.*}} <3 x float> @_ZN4hlsl8__detail11fwidth_implIDv3_fEET_S3_
+// CHECK: %hlsl.ddx.coarse = call {{.*}} <3 x float> @llvm.dx.ddx.coarse.v3f32(<3 x float> %{{.*}})
+// CHECK: %{{.*}} = call {{.*}} <3 x float> @llvm.fabs.v3f32(<3 x float> %{{.*}})
+// CHECK: %hlsl.ddy.coarse = call {{.*}} <3 x float> @llvm.dx.ddy.coarse.v3f32(<3 x float> %{{.*}})
+// CHECK: %{{.*}} = call {{.*}} <3 x float> @llvm.fabs.v3f32(<3 x float> %{{.*}})
+// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
+// CHECK: ret <3 x float> %{{.*}}
+// CHECK-LABEL-SPIRV: <3 x float> @_Z16test_f32_fwidth3Dv3_f
+// CHECK-SPIRV: %spv.fwidth = call {{.*}} <3 x float> @llvm.spv.fwidth.v3f32(<3 x float> %{{.*}})
+// CHECK-SPIRV: ret <3 x float> %spv.fwidth
+float3 test_f32_fwidth3(float3 val) {
+ return fwidth(val);
+}
+
+// CHECK-LABEL: define {{.*}} <4 x float> @_ZN4hlsl8__detail11fwidth_implIDv4_fEET_S3_
+// CHECK: %hlsl.ddx.coarse = call {{.*}} <4 x float> @llvm.dx.ddx.coarse.v4f32(<4 x float> %{{.*}})
+// CHECK: %{{.*}} = call {{.*}} <4 x float> @llvm.fabs.v4f32(<4 x float> %{{.*}})
+// CHECK: %hlsl.ddy.coarse = call {{.*}} <4 x float> @llvm.dx.ddy.coarse.v4f32(<4 x float> %{{.*}})
+// CHECK: %{{.*}} = call {{.*}} <4 x float> @llvm.fabs.v4f32(<4 x float> %{{.*}})
+// CHECK: %{{.*}} = fadd {{.*}} %{{.*}}, %{{.*}}
+// CHECK: ret <4 x float> %{{.*}}
+// CHECK-LABEL-SPIRV: <4 x float> @_Z16test_f32_fwidth4Dv4_f
+// CHECK-SPIRV: %spv.fwidth = call {{.*}} <4 x float> @llvm.spv.fwidth.v4f32(<4 x float> %{{.*}})
+// CHECK-SPIRV: ret <4 x float> %spv.fwidth
+float4 test_f32_fwidth4(float4 val) {
+ return fwidth(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ldexp.hlsl b/clang/test/CodeGenHLSL/builtins/ldexp.hlsl
index 012adc5..2dec126 100644
--- a/clang/test/CodeGenHLSL/builtins/ldexp.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/ldexp.hlsl
@@ -1,49 +1,49 @@
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -fnative-int16-type -emit-llvm -disable-llvm-passes -o - | FileCheck %s
// CHECK-LABEL: define linkonce_odr hidden noundef nofpclass(nan inf) half @_ZN4hlsl8__detail10ldexp_implIDhEET_S2_S2_
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn half @llvm.exp2.f16(half %{{.*}})
-// CHECK: %mul = fmul reassoc nnan ninf nsz arcp afn half %elt.exp2, %{{.*}}
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.exp2.f16(half %{{.*}})
+// CHECK: %mul = fmul reassoc nnan ninf nsz arcp afn half [[EXP2]], %{{.*}}
// CHECK: ret half %mul
half test_ldexp_half(half X, half Exp) { return ldexp(X, Exp); }
// CHECK-LABEL: define linkonce_odr hidden noundef nofpclass(nan inf) <2 x half> @_ZN4hlsl8__detail10ldexp_implIDv2_DhEET_S3_S3_
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <2 x half> @llvm.exp2.v2f16(<2 x half> %{{.*}})
-// CHECK: %mul = fmul reassoc nnan ninf nsz arcp afn <2 x half> %elt.exp2, %{{.*}}
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x half> @llvm.exp2.v2f16(<2 x half> %{{.*}})
+// CHECK: %mul = fmul reassoc nnan ninf nsz arcp afn <2 x half> [[EXP2]], %{{.*}}
// CHECK: ret <2 x half> %mul
half2 test_ldexp_half2(half2 X, half2 Exp) { return ldexp(X, Exp); }
// CHECK-LABEL: define linkonce_odr hidden noundef nofpclass(nan inf) <3 x half> @_ZN4hlsl8__detail10ldexp_implIDv3_DhEET_S3_S3_
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <3 x half> @llvm.exp2.v3f16(<3 x half> %{{.*}})
-// CHECK: %mul = fmul reassoc nnan ninf nsz arcp afn <3 x half> %elt.exp2, %{{.*}}
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x half> @llvm.exp2.v3f16(<3 x half> %{{.*}})
+// CHECK: %mul = fmul reassoc nnan ninf nsz arcp afn <3 x half> [[EXP2]], %{{.*}}
// CHECK: ret <3 x half> %mul
half3 test_ldexp_half3(half3 X, half3 Exp) { return ldexp(X, Exp); }
// CHECK-LABEL: define linkonce_odr hidden noundef nofpclass(nan inf) <4 x half> @_ZN4hlsl8__detail10ldexp_implIDv4_DhEET_S3_S3_
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <4 x half> @llvm.exp2.v4f16(<4 x half> %{{.*}})
-// CHECK: %mul = fmul reassoc nnan ninf nsz arcp afn <4 x half> %elt.exp2, %{{.*}}
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x half> @llvm.exp2.v4f16(<4 x half> %{{.*}})
+// CHECK: %mul = fmul reassoc nnan ninf nsz arcp afn <4 x half> [[EXP2]], %{{.*}}
// CHECK: ret <4 x half> %mul
half4 test_ldexp_half4(half4 X, half4 Exp) { return ldexp(X, Exp); }
// CHECK-LABEL: define linkonce_odr hidden noundef nofpclass(nan inf) float @_ZN4hlsl8__detail10ldexp_implIfEET_S2_S2_
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn float @llvm.exp2.f32(float %{{.*}})
-// CHECK: %mul = fmul reassoc nnan ninf nsz arcp afn float %elt.exp2, %{{.*}}
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.exp2.f32(float %{{.*}})
+// CHECK: %mul = fmul reassoc nnan ninf nsz arcp afn float [[EXP2]], %{{.*}}
// CHECK: ret float %mul
float test_ldexp_float(float X, float Exp) { return ldexp(X, Exp); }
// CHECK-LABEL: define linkonce_odr hidden noundef nofpclass(nan inf) <2 x float> @_ZN4hlsl8__detail10ldexp_implIDv2_fEET_S3_S3_
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp2.v2f32(<2 x float> %{{.*}})
-// CHECK: %mul = fmul reassoc nnan ninf nsz arcp afn <2 x float> %elt.exp2, %{{.*}}
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.exp2.v2f32(<2 x float> %{{.*}})
+// CHECK: %mul = fmul reassoc nnan ninf nsz arcp afn <2 x float> [[EXP2]], %{{.*}}
// CHECK: ret <2 x float> %mul
float2 test_ldexp_float2(float2 X, float2 Exp) { return ldexp(X, Exp); }
// CHECK-LABEL: define linkonce_odr hidden noundef nofpclass(nan inf) <3 x float> @_ZN4hlsl8__detail10ldexp_implIDv3_fEET_S3_S3_
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp2.v3f32(<3 x float> %{{.*}})
-// CHECK: %mul = fmul reassoc nnan ninf nsz arcp afn <3 x float> %elt.exp2, %{{.*}}
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.exp2.v3f32(<3 x float> %{{.*}})
+// CHECK: %mul = fmul reassoc nnan ninf nsz arcp afn <3 x float> [[EXP2]], %{{.*}}
// CHECK: ret <3 x float> %mul
float3 test_ldexp_float3(float3 X, float3 Exp) { return ldexp(X, Exp); }
// CHECK-LABEL: define linkonce_odr hidden noundef nofpclass(nan inf) <4 x float> @_ZN4hlsl8__detail10ldexp_implIDv4_fEET_S3_S3_
-// CHECK: %elt.exp2 = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp2.v4f32(<4 x float> %{{.*}})
-// CHECK: %mul = fmul reassoc nnan ninf nsz arcp afn <4 x float> %elt.exp2, %{{.*}}
+// CHECK: [[EXP2:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.exp2.v4f32(<4 x float> %{{.*}})
+// CHECK: %mul = fmul reassoc nnan ninf nsz arcp afn <4 x float> [[EXP2]], %{{.*}}
// CHECK: ret <4 x float> %mul
float4 test_ldexp_float4(float4 X, float4 Exp) { return ldexp(X, Exp); }
diff --git a/clang/test/CodeGenHLSL/builtins/lit.hlsl b/clang/test/CodeGenHLSL/builtins/lit.hlsl
index c0b109a..364c2e8 100644
--- a/clang/test/CodeGenHLSL/builtins/lit.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/lit.hlsl
@@ -7,11 +7,12 @@
// CHECK: %vecinit2.i = insertelement <4 x half> %{{.*}}, half 0xH3C00, i32 3
// CHECK: %cmp4.i = fcmp reassoc nnan ninf nsz arcp afn olt half %{{.*}}, 0xH0000
// CHECK: %hlsl.or.i = or i1 %{{.*}}, %cmp4.i
-// CHECK: %elt.log.i = call reassoc nnan ninf nsz arcp afn half @llvm.log.f16(half %{{.*}})
-// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn half %elt.log.i, %{{.*}}
-// CHECK: %elt.exp.i = call reassoc nnan ninf nsz arcp afn half @llvm.exp.f16(half %mul.i)
+// CHECK: [[LOG:%.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.log.f16(half %{{.*}})
+// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn half [[LOG]], %{{.*}}
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.exp.f16(half %mul.i)
// CHECK: %hlsl.select7.i = select reassoc nnan ninf nsz arcp afn i1 %{{.*}}, half 0xH0000, half %{{.*}}
-// CHECK: %vecins.i = insertelement <4 x half> %{{.*}}, half %hlsl.select7.i, i32 2
+// CHECK: [[PTR:%.*]] = getelementptr <4 x half>, ptr %Result.i, i32 0, i32 2
+// CHECK: store half %hlsl.select7.i, ptr [[PTR]], align 2
// CHECK: ret <4 x half> %{{.*}}
half4 test_lit_half(half NDotL, half NDotH, half M) { return lit(NDotL, NDotH, M); }
@@ -22,10 +23,11 @@ half4 test_lit_half(half NDotL, half NDotH, half M) { return lit(NDotL, NDotH, M
// CHECK: %vecinit2.i = insertelement <4 x float> %{{.*}}, float 1.000000e+00, i32 3
// CHECK: %cmp4.i = fcmp reassoc nnan ninf nsz arcp afn olt float %{{.*}}, 0.000000e+00
// CHECK: %hlsl.or.i = or i1 %{{.*}}, %cmp4.i
-// CHECK: %elt.log.i = call reassoc nnan ninf nsz arcp afn float @llvm.log.f32(float %{{.*}})
-// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn float %elt.log.i, %{{.*}}
-// CHECK: %elt.exp.i = call reassoc nnan ninf nsz arcp afn float @llvm.exp.f32(float %mul.i)
+// CHECK: [[LOG:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.log.f32(float %{{.*}})
+// CHECK: %mul.i = fmul reassoc nnan ninf nsz arcp afn float [[LOG]], %{{.*}}
+// CHECK: [[EXP:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.exp.f32(float %mul.i)
// CHECK: %hlsl.select7.i = select reassoc nnan ninf nsz arcp afn i1 %{{.*}}, float 0.000000e+00, float %{{.*}}
-// CHECK: %vecins.i = insertelement <4 x float> %{{.*}}, float %hlsl.select7.i, i32 2
+// CHECK: [[PTR:%.*]] = getelementptr <4 x float>, ptr %Result.i, i32 0, i32 2
+// CHECK: store float %hlsl.select7.i, ptr [[PTR]], align 4
// CHECK: ret <4 x float> %{{.*}}
float4 test_lit_float(float NDotL, float NDotH, float M) { return lit(NDotL, NDotH, M); }
diff --git a/clang/test/CodeGenHLSL/builtins/round-overloads.hlsl b/clang/test/CodeGenHLSL/builtins/round-overloads.hlsl
index 3b07fce..5719d9d 100644
--- a/clang/test/CodeGenHLSL/builtins/round-overloads.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/round-overloads.hlsl
@@ -3,86 +3,86 @@
// RUN: FileCheck %s --check-prefixes=CHECK
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float {{.*}}test_round_double
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn float @llvm.roundeven.f32(
-// CHECK: ret float %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.roundeven.f32(
+// CHECK: ret float [[ROUNDEVEN]]
float test_round_double(double p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> {{.*}}test_round_double2
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.roundeven.v2f32
-// CHECK: ret <2 x float> %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.roundeven.v2f32
+// CHECK: ret <2 x float> [[ROUNDEVEN]]
float2 test_round_double2(double2 p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> {{.*}}test_round_double3
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.roundeven.v3f32
-// CHECK: ret <3 x float> %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.roundeven.v3f32
+// CHECK: ret <3 x float> [[ROUNDEVEN]]
float3 test_round_double3(double3 p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> {{.*}}test_round_double4
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.roundeven.v4f32
-// CHECK: ret <4 x float> %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.roundeven.v4f32
+// CHECK: ret <4 x float> [[ROUNDEVEN]]
float4 test_round_double4(double4 p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float {{.*}}test_round_int
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn float @llvm.roundeven.f32(
-// CHECK: ret float %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.roundeven.f32(
+// CHECK: ret float [[ROUNDEVEN]]
float test_round_int(int p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> {{.*}}test_round_int2
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.roundeven.v2f32
-// CHECK: ret <2 x float> %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.roundeven.v2f32
+// CHECK: ret <2 x float> [[ROUNDEVEN]]
float2 test_round_int2(int2 p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> {{.*}}test_round_int3
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.roundeven.v3f32
-// CHECK: ret <3 x float> %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.roundeven.v3f32
+// CHECK: ret <3 x float> [[ROUNDEVEN]]
float3 test_round_int3(int3 p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> {{.*}}test_round_int4
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.roundeven.v4f32
-// CHECK: ret <4 x float> %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.roundeven.v4f32
+// CHECK: ret <4 x float> [[ROUNDEVEN]]
float4 test_round_int4(int4 p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float {{.*}}test_round_uint
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn float @llvm.roundeven.f32(
-// CHECK: ret float %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.roundeven.f32(
+// CHECK: ret float [[ROUNDEVEN]]
float test_round_uint(uint p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> {{.*}}test_round_uint2
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.roundeven.v2f32
-// CHECK: ret <2 x float> %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.roundeven.v2f32
+// CHECK: ret <2 x float> [[ROUNDEVEN]]
float2 test_round_uint2(uint2 p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> {{.*}}test_round_uint3
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.roundeven.v3f32
-// CHECK: ret <3 x float> %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.roundeven.v3f32
+// CHECK: ret <3 x float> [[ROUNDEVEN]]
float3 test_round_uint3(uint3 p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> {{.*}}test_round_uint4
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.roundeven.v4f32
-// CHECK: ret <4 x float> %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.roundeven.v4f32
+// CHECK: ret <4 x float> [[ROUNDEVEN]]
float4 test_round_uint4(uint4 p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float {{.*}}test_round_int64_t
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn float @llvm.roundeven.f32(
-// CHECK: ret float %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.roundeven.f32(
+// CHECK: ret float [[ROUNDEVEN]]
float test_round_int64_t(int64_t p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> {{.*}}test_round_int64_t2
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.roundeven.v2f32
-// CHECK: ret <2 x float> %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.roundeven.v2f32
+// CHECK: ret <2 x float> [[ROUNDEVEN]]
float2 test_round_int64_t2(int64_t2 p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> {{.*}}test_round_int64_t3
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.roundeven.v3f32
-// CHECK: ret <3 x float> %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.roundeven.v3f32
+// CHECK: ret <3 x float> [[ROUNDEVEN]]
float3 test_round_int64_t3(int64_t3 p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> {{.*}}test_round_int64_t4
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.roundeven.v4f32
-// CHECK: ret <4 x float> %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.roundeven.v4f32
+// CHECK: ret <4 x float> [[ROUNDEVEN]]
float4 test_round_int64_t4(int64_t4 p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float {{.*}}test_round_uint64_t
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn float @llvm.roundeven.f32(
-// CHECK: ret float %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.roundeven.f32(
+// CHECK: ret float [[ROUNDEVEN]]
float test_round_uint64_t(uint64_t p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> {{.*}}test_round_uint64_t2
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.roundeven.v2f32
-// CHECK: ret <2 x float> %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.roundeven.v2f32
+// CHECK: ret <2 x float> [[ROUNDEVEN]]
float2 test_round_uint64_t2(uint64_t2 p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> {{.*}}test_round_uint64_t3
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.roundeven.v3f32
-// CHECK: ret <3 x float> %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.roundeven.v3f32
+// CHECK: ret <3 x float> [[ROUNDEVEN]]
float3 test_round_uint64_t3(uint64_t3 p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> {{.*}}test_round_uint64_t4
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.roundeven.v4f32
-// CHECK: ret <4 x float> %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.roundeven.v4f32
+// CHECK: ret <4 x float> [[ROUNDEVEN]]
float4 test_round_uint64_t4(uint64_t4 p0) { return round(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/round.hlsl b/clang/test/CodeGenHLSL/builtins/round.hlsl
index 0d4afee6..8161b0c 100644
--- a/clang/test/CodeGenHLSL/builtins/round.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/round.hlsl
@@ -6,47 +6,47 @@
// RUN: FileCheck %s --check-prefixes=CHECK,NO_HALF
// NATIVE_HALF-LABEL: define hidden noundef nofpclass(nan inf) half @_Z15test_round_half
-// NATIVE_HALF: %elt.roundeven = call reassoc nnan ninf nsz arcp afn half @llvm.roundeven.f16(
-// NATIVE_HALF: ret half %elt.roundeven
+// NATIVE_HALF: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn half @llvm.roundeven.f16(
+// NATIVE_HALF: ret half [[ROUNDEVEN]]
// NO_HALF-LABEL: define hidden noundef nofpclass(nan inf) float @_Z15test_round_half
-// NO_HALF: %elt.roundeven = call reassoc nnan ninf nsz arcp afn float @llvm.roundeven.f32(
-// NO_HALF: ret float %elt.roundeven
+// NO_HALF: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.roundeven.f32(
+// NO_HALF: ret float [[ROUNDEVEN]]
half test_round_half(half p0) { return round(p0); }
// NATIVE_HALF-LABEL: define hidden noundef nofpclass(nan inf) <2 x half> @_Z16test_round_half2
-// NATIVE_HALF: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <2 x half> @llvm.roundeven.v2f16
-// NATIVE_HALF: ret <2 x half> %elt.roundeven
+// NATIVE_HALF: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x half> @llvm.roundeven.v2f16
+// NATIVE_HALF: ret <2 x half> [[ROUNDEVEN:%.*]]
// NO_HALF-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> @_Z16test_round_half2
-// NO_HALF: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.roundeven.v2f32(
-// NO_HALF: ret <2 x float> %elt.roundeven
+// NO_HALF: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.roundeven.v2f32(
+// NO_HALF: ret <2 x float> [[ROUNDEVEN]]
half2 test_round_half2(half2 p0) { return round(p0); }
// NATIVE_HALF-LABEL: define hidden noundef nofpclass(nan inf) <3 x half> @_Z16test_round_half3
-// NATIVE_HALF: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <3 x half> @llvm.roundeven.v3f16
-// NATIVE_HALF: ret <3 x half> %elt.roundeven
+// NATIVE_HALF: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x half> @llvm.roundeven.v3f16
+// NATIVE_HALF: ret <3 x half> [[ROUNDEVEN:%.*]]
// NO_HALF-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> @_Z16test_round_half3
-// NO_HALF: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.roundeven.v3f32(
-// NO_HALF: ret <3 x float> %elt.roundeven
+// NO_HALF: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.roundeven.v3f32(
+// NO_HALF: ret <3 x float> [[ROUNDEVEN]]
half3 test_round_half3(half3 p0) { return round(p0); }
// NATIVE_HALF-LABEL: define hidden noundef nofpclass(nan inf) <4 x half> @_Z16test_round_half4
-// NATIVE_HALF: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <4 x half> @llvm.roundeven.v4f16
-// NATIVE_HALF: ret <4 x half> %elt.roundeven
+// NATIVE_HALF: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x half> @llvm.roundeven.v4f16
+// NATIVE_HALF: ret <4 x half> [[ROUNDEVEN:%.*]]
// NO_HALF-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> @_Z16test_round_half4
-// NO_HALF: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.roundeven.v4f32(
-// NO_HALF: ret <4 x float> %elt.roundeven
+// NO_HALF: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.roundeven.v4f32(
+// NO_HALF: ret <4 x float> [[ROUNDEVEN]]
half4 test_round_half4(half4 p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z16test_round_float
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn float @llvm.roundeven.f32(
-// CHECK: ret float %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.roundeven.f32(
+// CHECK: ret float [[ROUNDEVEN]]
float test_round_float(float p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <2 x float> @_Z17test_round_float2
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.roundeven.v2f32
-// CHECK: ret <2 x float> %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.roundeven.v2f32
+// CHECK: ret <2 x float> [[ROUNDEVEN]]
float2 test_round_float2(float2 p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <3 x float> @_Z17test_round_float3
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.roundeven.v3f32
-// CHECK: ret <3 x float> %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.roundeven.v3f32
+// CHECK: ret <3 x float> [[ROUNDEVEN]]
float3 test_round_float3(float3 p0) { return round(p0); }
// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> @_Z17test_round_float4
-// CHECK: %elt.roundeven = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.roundeven.v4f32
-// CHECK: ret <4 x float> %elt.roundeven
+// CHECK: [[ROUNDEVEN:%.*]] = call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.roundeven.v4f32
+// CHECK: ret <4 x float> [[ROUNDEVEN]]
float4 test_round_float4(float4 p0) { return round(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/select.hlsl b/clang/test/CodeGenHLSL/builtins/select.hlsl
index 7590b4a..e516984 100644
--- a/clang/test/CodeGenHLSL/builtins/select.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/select.hlsl
@@ -20,16 +20,6 @@ struct S test_select_infer_struct(bool cond0, struct S tVal, struct S fVal) {
return select(cond0, tVal, fVal);
}
-// CHECK-LABEL: test_select_infer_array
-// CHECK: [[TRUE_VAL:%.*]] = load [3 x i32], ptr {{%.*}}, align 4
-// CHECK: [[FALSE_VAL:%.*]] = load [3 x i32], ptr {{%.*}}, align 4
-// CHECK: [[SELECT:%.*]] = select i1 {{%.*}}, [3 x i32] [[TRUE_VAL]], [3 x i32] [[FALSE_VAL]]
-// CHECK: store [3 x i32] [[SELECT]], ptr {{%.*}}, align 4
-// CHECK: ret void
-int test_select_infer_array(bool cond, int tVal[3], int fVal[3])[3] {
- return select(cond, tVal, fVal);
-}
-
// CHECK-LABEL: test_select_bool_vector
// CHECK: [[SELECT:%.*]] = select i1 {{%.*}}, <2 x i32> {{%.*}}, <2 x i32> {{%.*}}
// CHECK: ret <2 x i32> [[SELECT]]
@@ -38,24 +28,24 @@ int2 test_select_bool_vector(bool cond0, int2 tVal, int2 fVal) {
}
// CHECK-LABEL: test_select_vector_1
-// CHECK: [[SELECT:%.*]] = select <1 x i1> {{%.*}}, <1 x i32> {{%.*}}, <1 x i32> {{%.*}}
+// CHECK: [[SELECT:%.*]] = select i1 {{%.*}}, <1 x i32> {{%.*}}, <1 x i32> {{%.*}}
// CHECK: ret <1 x i32> [[SELECT]]
int1 test_select_vector_1(bool1 cond0, int1 tVals, int1 fVals) {
- return select<int,1>(cond0, tVals, fVals);
+ return select(cond0, tVals, fVals);
}
// CHECK-LABEL: test_select_vector_2
// CHECK: [[SELECT:%.*]] = select <2 x i1> {{%.*}}, <2 x i32> {{%.*}}, <2 x i32> {{%.*}}
// CHECK: ret <2 x i32> [[SELECT]]
int2 test_select_vector_2(bool2 cond0, int2 tVals, int2 fVals) {
- return select<int,2>(cond0, tVals, fVals);
+ return select(cond0, tVals, fVals);
}
// CHECK-LABEL: test_select_vector_3
// CHECK: [[SELECT:%.*]] = select <3 x i1> {{%.*}}, <3 x i32> {{%.*}}, <3 x i32> {{%.*}}
// CHECK: ret <3 x i32> [[SELECT]]
int3 test_select_vector_3(bool3 cond0, int3 tVals, int3 fVals) {
- return select<int,3>(cond0, tVals, fVals);
+ return select(cond0, tVals, fVals);
}
// CHECK-LABEL: test_select_vector_4
@@ -86,10 +76,54 @@ int4 test_select_vector_vector_scalar(bool4 cond0, int4 tVals, int fVal) {
// CHECK-LABEL: test_select_vector_scalar_scalar
// CHECK: [[SPLAT_SRC1:%.*]] = insertelement <4 x i32> poison, i32 {{%.*}}, i64 0
// CHECK: [[SPLAT1:%.*]] = shufflevector <4 x i32> [[SPLAT_SRC1]], <4 x i32> poison, <4 x i32> zeroinitializer
-// CHECK: [[SPLAT_SRC2:%.*]] = insertelement <4 x i32> poison, i32 %3, i64 0
+// CHECK: [[SPLAT_SRC2:%.*]] = insertelement <4 x i32> poison, i32 {{%.*}}, i64 0
// CHECK: [[SPLAT2:%.*]] = shufflevector <4 x i32> [[SPLAT_SRC2]], <4 x i32> poison, <4 x i32> zeroinitializer
// CHECK: [[SELECT:%.*]] = select <4 x i1> {{%.*}}, <4 x i32> [[SPLAT1]], <4 x i32> [[SPLAT2]]
// CHECK: ret <4 x i32> [[SELECT]]
int4 test_select_vector_scalar_scalar(bool4 cond0, int tVal, int fVal) {
return select(cond0, tVal, fVal);
}
+
+// CHECK-LABEL: test_select_nonbool_cond_vector_4
+// CHECK: [[TMP0:%.*]] = load <4 x i32>, ptr %cond0.addr, align 16
+// CHECK: [[TOBOOL:%.*]] = icmp ne <4 x i32> [[TMP0]], zeroinitializer
+// CHECK: [[SELECT:%.*]] = select <4 x i1> [[TOBOOL]], <4 x i1> {{%.*}}, <4 x i1> {{%.*}}
+// CHECK: ret <4 x i1> [[SELECT]]
+bool4 test_select_nonbool_cond_vector_4(int4 cond0, bool4 tVal, bool4 fVal) {
+ return select(cond0, tVal, fVal);
+}
+
+// CHECK-LABEL: test_select_nonbool_cond_vector_scalar_vector
+// CHECK: [[TMP0:%.*]] = load <3 x i32>, ptr %cond0.addr, align 16
+// CHECK: [[TOBOOL:%.*]] = icmp ne <3 x i32> [[TMP0]], zeroinitializer
+// CHECK: [[SPLAT_SRC1:%.*]] = insertelement <3 x i32> poison, i32 {{%.*}}, i64 0
+// CHECK: [[SPLAT1:%.*]] = shufflevector <3 x i32> [[SPLAT_SRC1]], <3 x i32> poison, <3 x i32> zeroinitializer
+// CHECK: [[SELECT:%.*]] = select <3 x i1> [[TOBOOL]], <3 x i32> [[SPLAT1]], <3 x i32> {{%.*}}
+// CHECK: ret <3 x i32> [[SELECT]]
+int3 test_select_nonbool_cond_vector_scalar_vector(int3 cond0, int tVal, int3 fVal) {
+ return select(cond0, tVal, fVal);
+}
+
+// CHECK-LABEL: test_select_nonbool_cond_vector_vector_scalar
+// CHECK: [[TMP0:%.*]] = load <2 x i32>, ptr %cond0.addr, align 8
+// CHECK: [[TOBOOL:%.*]] = icmp ne <2 x i32> [[TMP0]], zeroinitializer
+// CHECK: [[SPLAT_SRC1:%.*]] = insertelement <2 x i32> poison, i32 {{%.*}}, i64 0
+// CHECK: [[SPLAT1:%.*]] = shufflevector <2 x i32> [[SPLAT_SRC1]], <2 x i32> poison, <2 x i32> zeroinitializer
+// CHECK: [[SELECT:%.*]] = select <2 x i1> [[TOBOOL]], <2 x i32> {{%.*}}, <2 x i32> [[SPLAT1]]
+// CHECK: ret <2 x i32> [[SELECT]]
+int2 test_select_nonbool_cond_vector_vector_scalar(int2 cond0, int2 tVal, int fVal) {
+ return select(cond0, tVal, fVal);
+}
+
+// CHECK-LABEL: test_select_nonbool_cond_vector_scalar_scalar
+// CHECK: [[TMP0:%.*]] = load <4 x i32>, ptr %cond0.addr, align 16
+// CHECK: [[TOBOOL:%.*]] = icmp ne <4 x i32> [[TMP0]], zeroinitializer
+// CHECK: [[SPLAT_SRC1:%.*]] = insertelement <4 x i32> poison, i32 {{%.*}}, i64 0
+// CHECK: [[SPLAT1:%.*]] = shufflevector <4 x i32> [[SPLAT_SRC1]], <4 x i32> poison, <4 x i32> zeroinitializer
+// CHECK: [[SPLAT_SRC2:%.*]] = insertelement <4 x i32> poison, i32 {{%.*}}, i64 0
+// CHECK: [[SPLAT2:%.*]] = shufflevector <4 x i32> [[SPLAT_SRC2]], <4 x i32> poison, <4 x i32> zeroinitializer
+// CHECK: [[SELECT:%.*]] = select <4 x i1> [[TOBOOL]], <4 x i32> [[SPLAT1]], <4 x i32> [[SPLAT2]]
+// CHECK: ret <4 x i32> [[SELECT]]
+int4 test_select_nonbool_cond_vector_scalar_scalar(int4 cond0, int tVal, int fVal) {
+ return select(cond0, tVal, fVal);
+}
diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl
index 1f248d0..54c386c 100644
--- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl
+++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl
@@ -104,6 +104,44 @@ export float TestLoad() {
// CHECK-NEXT: %[[VAL:.*]] = load float, ptr %[[PTR]]
// CHECK-NEXT: ret float %[[VAL]]
+export float TestLoadWithStatus() {
+ uint s1;
+ uint s2;
+ float ret = RWSB1.Load(1, s1) + SB1.Load(2, s2);
+ ret += float(s1 + s2);
+ return ret;
+}
+
+// CHECK: define noundef nofpclass(nan inf) float @TestLoadWithStatus()()
+// CHECK: call {{.*}} float @hlsl::RWStructuredBuffer<float>::Load(unsigned int, unsigned int&)(ptr {{.*}} @RWSB1, i32 noundef 1, ptr {{.*}} %tmp)
+// CHECK: call {{.*}} float @hlsl::StructuredBuffer<float>::Load(unsigned int, unsigned int&)(ptr {{.*}} @SB1, i32 noundef 2, ptr {{.*}} %tmp1)
+// CHECK: add
+// CHECK: ret float
+
+// CHECK: define {{.*}} float @hlsl::RWStructuredBuffer<float>::Load(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer", ptr %{{.*}}, i32 0, i32 0
+// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 0), ptr %__handle
+// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
+// CHECK-NEXT: %[[LOADED_STATUS_ADDR:.*]] = load ptr, ptr %Status.addr
+// DXIL-NEXT: %[[STRUCT:.*]] = call { float, i1 } @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %[[HANDLE]], i32 %[[INDEX]], i32 0)
+// CHECK-NEXT: %[[VALUE:.*]] = extractvalue { float, i1 } %[[STRUCT]], 0
+// CHECK-NEXT: %[[STATUS_TEMP:.*]] = extractvalue { float, i1 } %[[STRUCT]], 1
+// CHECK-NEXT: %[[STATUS_EXT:.*]] = zext i1 %[[STATUS_TEMP]] to i32
+// CHECK-NEXT: store i32 %[[STATUS_EXT]], ptr %[[LOADED_STATUS_ADDR]], align 4
+// CHECK-NEXT: ret float %[[VALUE]]
+
+// CHECK: define {{.*}} float @hlsl::StructuredBuffer<float>::Load(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %{{.*}}, i32 0, i32 0
+// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 0, 0), ptr %__handle
+// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
+// CHECK-NEXT: %[[LOADED_STATUS_ADDR:.*]] = load ptr, ptr %Status.addr, align 4
+// DXIL-NEXT: %[[STRUCT:.*]] = call { float, i1 } @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0) %[[HANDLE]], i32 %[[INDEX]], i32 0)
+// CHECK-NEXT: %[[VALUE:.*]] = extractvalue { float, i1 } %[[STRUCT]], 0
+// CHECK-NEXT: %[[STATUS_TEMP:.*]] = extractvalue { float, i1 } %[[STRUCT]], 1
+// CHECK-NEXT: %[[STATUS_EXT:.*]] = zext i1 %[[STATUS_TEMP]] to i32
+// CHECK-NEXT: store i32 %[[STATUS_EXT]], ptr %[[LOADED_STATUS_ADDR]], align 4
+// CHECK-NEXT: ret float %[[VALUE]]
+
export uint TestGetDimensions() {
uint dim1, dim2, dim3, stride1, stride2, stride3;
SB1.GetDimensions(dim1, stride1);
diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl
index 25fa759..157bae2 100644
--- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl
+++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl
@@ -65,6 +65,43 @@ export float TestLoad() {
// CHECK-NEXT: %[[VAL:.*]] = load <2 x i32>, ptr %[[BUFPTR]]
// CHECK-NEXT: ret <2 x i32> %[[VAL]]
+export float TestLoadWithStatus() {
+ uint status;
+ uint status2;
+ float val = ROSB1.Load(10, status).x + ROSB2.Load(20, status2).x;
+ return val + float(status + status2);
+}
+
+// CHECK: define {{.*}} float @TestLoadWithStatus()()
+// CHECK: call {{.*}} float @hlsl::RasterizerOrderedStructuredBuffer<float>::Load(unsigned int, unsigned int&)(ptr {{.*}} @ROSB1, i32 noundef 10, ptr {{.*}} %tmp)
+// CHECK: call {{.*}} <2 x i32> @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::Load(unsigned int, unsigned int&)(ptr {{.*}} @ROSB2, i32 noundef 20, ptr {{.*}} %tmp2)
+// CHECK: ret
+
+// CHECK: define {{.*}} float @hlsl::RasterizerOrderedStructuredBuffer<float>::Load(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer", ptr {{.*}}, i32 0, i32 0
+// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 1), ptr %__handle
+// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
+// CHECK-NEXT: %[[LOADED_STATUS_ADDR:.*]] = load ptr, ptr %Status.addr, align 4
+// DXIL-NEXT: %[[STRUCT:.*]] = call { float, i1 } @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %[[HANDLE]], i32 %[[INDEX]], i32 0)
+// CHECK-NEXT: %[[VALUE:.*]] = extractvalue { float, i1 } %[[STRUCT]], 0
+// CHECK-NEXT: %[[STATUS_TEMP:.*]] = extractvalue { float, i1 } %[[STRUCT]], 1
+// CHECK-NEXT: %[[STATUS_EXT:.*]] = zext i1 %[[STATUS_TEMP]] to i32
+// CHECK-NEXT: store i32 %[[STATUS_EXT]], ptr %[[LOADED_STATUS_ADDR]], align 4
+// CHECK-NEXT: ret float %[[VALUE]]
+
+// CHECK: define {{.*}} <2 x i32> @hlsl::RasterizerOrderedStructuredBuffer<int vector[2]>::Load(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer.0", ptr {{.*}}, i32 0, i32 0
+// CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <2 x i32>, 1, 1), ptr %__handle
+// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
+// CHECK-NEXT: %[[LOADED_STATUS_ADDR:.*]] = load ptr, ptr %Status.addr, align 4
+// DXIL-NEXT: %[[STRUCT:.*]] = call { <2 x i32>, i1 } @llvm.dx.resource.load.rawbuffer.v2i32.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1) %[[HANDLE]], i32 %[[INDEX]], i32 0)
+// CHECK-NEXT: %[[VALUE:.*]] = extractvalue { <2 x i32>, i1 } %[[STRUCT]], 0
+// CHECK-NEXT: %[[STATUS_TEMP:.*]] = extractvalue { <2 x i32>, i1 } %[[STRUCT]], 1
+// CHECK-NEXT: %[[STATUS_EXT:.*]] = zext i1 %[[STATUS_TEMP]] to i32
+// CHECK-NEXT: store i32 %[[STATUS_EXT]], ptr %[[LOADED_STATUS_ADDR]], align 4
+// CHECK-NEXT: ret <2 x i32> %[[VALUE]]
+
+
export uint TestGetDimensions() {
uint dim1, dim2, stride1, stride2;
ROSB1.GetDimensions(dim1, stride1);
diff --git a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl
index fdc1ef0..499f5b1 100644
--- a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl
+++ b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl
@@ -38,6 +38,44 @@ export float TestLoad() {
// CHECK-NEXT: %[[VEC:.*]] = load <4 x i32>, ptr %[[PTR]]
// CHECK-NEXT: ret <4 x i32> %[[VEC]]
+export float TestLoadWithStatus() {
+ uint s1;
+ uint s2;
+ float ret = Buf.Load(1, s1) + float(RWBuf.Load(2, s2).y);
+ ret += float(s1 + s2);
+ return ret;
+}
+
+// CHECK: define noundef nofpclass(nan inf) float @TestLoadWithStatus()()
+// CHECK: call {{.*}} float @hlsl::Buffer<float>::Load(unsigned int, unsigned int&)(ptr {{.*}} @Buf, i32 noundef 1, ptr {{.*}} %tmp)
+// CHECK: call {{.*}} <4 x i32> @hlsl::RWBuffer<unsigned int vector[4]>::Load(unsigned int, unsigned int&)(ptr {{.*}} @RWBuf, i32 noundef 2, ptr {{.*}} %tmp1)
+// CHECK: add
+// CHECK: ret float
+
+// CHECK: define {{.*}} float @hlsl::Buffer<float>::Load(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::Buffer", ptr %{{.*}}, i32 0, i32 0
+// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", float, 0, 0, 0), ptr %__handle
+// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
+// CHECK-NEXT: %[[LOADED_STATUS_ADDR:.*]] = load ptr, ptr %Status.addr
+// DXIL-NEXT: %[[STRUCT:.*]] = call { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0) %[[HANDLE]], i32 %[[INDEX]])
+// CHECK-NEXT: %[[VALUE:.*]] = extractvalue { float, i1 } %[[STRUCT]], 0
+// CHECK-NEXT: %[[STATUS_TEMP:.*]] = extractvalue { float, i1 } %[[STRUCT]], 1
+// CHECK-NEXT: %[[STATUS_EXT:.*]] = zext i1 %[[STATUS_TEMP]] to i32
+// CHECK-NEXT: store i32 %[[STATUS_EXT]], ptr %[[LOADED_STATUS_ADDR]], align 4
+// CHECK-NEXT: ret float %[[VALUE]]
+
+// CHECK: define {{.*}} <4 x i32> @hlsl::RWBuffer<unsigned int vector[4]>::Load(unsigned int, unsigned int&)(ptr {{.*}} %this, i32 noundef %Index, ptr {{.*}} %Status)
+// CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %{{.*}}, i32 0, i32 0
+// DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), ptr %__handle
+// CHECK-NEXT: %[[INDEX:.*]] = load i32, ptr %Index.addr
+// CHECK-NEXT: %[[LOADED_STATUS_ADDR:.*]] = load ptr, ptr %Status.addr
+// DXIL-NEXT: %[[STRUCT:.*]] = call { <4 x i32>, i1 } @llvm.dx.resource.load.typedbuffer.v4i32.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0) %[[HANDLE]], i32 %[[INDEX]])
+// CHECK-NEXT: %[[VALUE:.*]] = extractvalue { <4 x i32>, i1 } %[[STRUCT]], 0
+// CHECK-NEXT: %[[STATUS_TEMP:.*]] = extractvalue { <4 x i32>, i1 } %[[STRUCT]], 1
+// CHECK-NEXT: %[[STATUS_EXT:.*]] = zext i1 %[[STATUS_TEMP]] to i32
+// CHECK-NEXT: store i32 %[[STATUS_EXT]], ptr %[[LOADED_STATUS_ADDR]], align 4
+// CHECK-NEXT: ret <4 x i32> %[[VALUE]]
+
export uint TestGetDimensions() {
uint dim1, dim2;
Buf.GetDimensions(dim1);
diff --git a/clang/test/CodeGenHLSL/resources/cbuffer.hlsl b/clang/test/CodeGenHLSL/resources/cbuffer.hlsl
index c8efe0d..b72cf58 100644
--- a/clang/test/CodeGenHLSL/resources/cbuffer.hlsl
+++ b/clang/test/CodeGenHLSL/resources/cbuffer.hlsl
@@ -1,37 +1,123 @@
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-compute -fnative-half-type -fnative-int16-type -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
-// CHECK: %__cblayout_CBScalars = type <{ float, double, half, i64, i32, i16, i32, i64 }>
-// CHECK: %__cblayout_CBVectors = type <{ <3 x float>, <3 x double>, <2 x half>, <3 x i64>, <4 x i32>, <3 x i16>, <3 x i64> }>
-// CHECK: %__cblayout_CBArrays = type <{ [3 x float], [2 x <3 x double>], [2 x [2 x half]], [3 x i64], [2 x [3 x [4 x <4 x i32>]]], [1 x i16], [2 x i64], [4 x i32] }>
-// CHECK: %__cblayout_CBStructs = type <{ target("dx.Layout", %A, 8, 0), target("dx.Layout", %B, 14, 0, 8),
-// CHECK-SAME: target("dx.Layout", %C, 24, 0, 16), [5 x target("dx.Layout", %A, 8, 0)],
-// CHECK-SAME: target("dx.Layout", %__cblayout_D, 94, 0), half, <3 x i16> }>
+// CHECK: %__cblayout_CBScalars = type <{
+// CHECK-SAME: float, target("dx.Padding", 4), double,
+// CHECK-SAME: half, target("dx.Padding", 6), i64,
+// CHECK-SAME: i32, i16, target("dx.Padding", 2), i32, target("dx.Padding", 4),
+// CHECK-SAME: i64
+// CHECK-SAME: }>
+
+// CHECK: %__cblayout_CBVectors = type <{
+// CHECK-SAME: <3 x float>, target("dx.Padding", 4),
+// CHECK-SAME: <3 x double>, <2 x half>, target("dx.Padding", 4),
+// CHECK-SAME: <3 x i64>, target("dx.Padding", 8),
+// CHECK-SAME: <4 x i32>,
+// CHECK-SAME: <3 x i16>, target("dx.Padding", 10),
+// CHECK-SAME: <3 x i64>
+// CHECK-SAME: }>
+
+// CHECK: %__cblayout_CBArrays = type <{
+// CHECK-SAME: <{ [2 x <{ float, target("dx.Padding", 12) }>], float }>, target("dx.Padding", 12),
+// CHECK-SAME: <{ [1 x <{ <3 x double>, target("dx.Padding", 8) }>], <3 x double> }>, target("dx.Padding", 8),
+// CHECK-SAME: <{ [1 x <{
+// CHECK-SAME: <{ [1 x <{ half, target("dx.Padding", 14) }>], half }>, target("dx.Padding", 14) }>],
+// CHECK-SAME: <{ [1 x <{ half, target("dx.Padding", 14) }>], half }>
+// CHECK-SAME: }>, target("dx.Padding", 14),
+// CHECK-SAME: <{ [2 x <{ i64, target("dx.Padding", 8) }>], i64 }>, target("dx.Padding", 8),
+// CHECK-SAME: [2 x [3 x [4 x <4 x i32>]]]
+// CHECK-SAME: [1 x i16], target("dx.Padding", 14),
+// CHECK-SAME: <{ [1 x <{ i64, target("dx.Padding", 8) }>], i64 }>, target("dx.Padding", 8),
+// CHECK-SAME: <{ [3 x <{ i32, target("dx.Padding", 12) }>], i32 }>
+// CHECK-SAME: }>
+
+// CHECK: %__cblayout_CBStructs = type <{
+// CHECK-SAME: %A, target("dx.Padding", 8),
+
+// TODO: We should have target("dx.Padding", 2) padding after %B, but we don't
+// correctly handle 2- and 3-element vectors inside structs yet because of
+// DataLayout rules. See https://github.com/llvm/llvm-project/issues/123968.
+//
+// CHECK-SAME: %B,
+
+// CHECK-SAME: %C, target("dx.Padding", 8),
+// CHECK-SAME: <{ [4 x <{ %A, target("dx.Padding", 8) }>], %A }>, target("dx.Padding", 8),
+// CHECK-SAME: %__cblayout_D, half,
+// CHECK-SAME: <3 x i16>
+// CHECK-SAME: }>
// CHECK: %A = type <{ <2 x float> }>
// CHECK: %B = type <{ <2 x float>, <3 x i16> }>
-// CHECK: %C = type <{ i32, target("dx.Layout", %A, 8, 0) }>
-// CHECK: %__cblayout_D = type <{ [2 x [3 x target("dx.Layout", %B, 14, 0, 8)]] }>
+// CHECK: %C = type <{ i32, target("dx.Padding", 12), %A }>
+
+// CHECK: %__cblayout_D = type <{
+// CHECK-SAME: <{ [1 x <{
+// CHECK-SAME: <{ [2 x <{ %B, target("dx.Padding", 2) }>], %B }>, target("dx.Padding", 2)
+// CHECK-SAME: }>],
+// CHECK-SAME: <{ [2 x <{ %B, target("dx.Padding", 2) }>], %B }> }>
+// CHECK-SAME: }>
+
+// CHECK: %__cblayout_CBClasses = type <{
+// CHECK-SAME: %K, target("dx.Padding", 12),
+// CHECK-SAME: %L, target("dx.Padding", 8),
+// CHECK-SAME: %M, target("dx.Padding", 12),
+// CHECK-SAME: <{ [9 x <{ %K, target("dx.Padding", 12) }>], %K }>
+// CHECK-SAME: }>
-// CHECK: %__cblayout_CBClasses = type <{ target("dx.Layout", %K, 4, 0), target("dx.Layout", %L, 8, 0, 4),
-// CHECK-SAME: target("dx.Layout", %M, 68, 0), [10 x target("dx.Layout", %K, 4, 0)] }>
// CHECK: %K = type <{ float }>
// CHECK: %L = type <{ float, float }>
-// CHECK: %M = type <{ [5 x target("dx.Layout", %K, 4, 0)] }>
-
-// CHECK: %__cblayout_CBMix = type <{ [2 x target("dx.Layout", %Test, 8, 0, 4)], float, [3 x [2 x <2 x float>]], float,
-// CHECK-SAME: target("dx.Layout", %anon, 4, 0), double, target("dx.Layout", %anon.0, 8, 0), float, <1 x double>, i16 }>
+// CHECK: %M = type <{ <{ [4 x <{ %K, target("dx.Padding", 12) }>], %K }> }>
+
+// CHECK: %__cblayout_CBMix = type <{
+// CHECK-SAME: <{ [1 x <{ %Test, target("dx.Padding", 8) }>], %Test }>, float, target("dx.Padding", 4)
+// CHECK-SAME: <{ [2 x <{
+// CHECK-SAME: <{ [1 x <{ <2 x float>, target("dx.Padding", 8) }>], <2 x float> }>, target("dx.Padding", 8) }>],
+// CHECK-SAME: <{ [1 x <{ <2 x float>, target("dx.Padding", 8) }>], <2 x float> }>
+// CHECK-SAME: }>, float, target("dx.Padding", 4),
+// CHECK-SAME: %anon, target("dx.Padding", 4), double,
+// CHECK-SAME: %anon.0, float, target("dx.Padding", 4),
+// CHECK-SAME: <1 x double>, i16
+// CHECK-SAME: }>
// CHECK: %Test = type <{ float, float }>
// CHECK: %anon = type <{ float }>
// CHECK: %anon.0 = type <{ <2 x i32> }>
-// CHECK: %__cblayout_CB_A = type <{ [2 x double], [3 x <3 x float>], float, [3 x double], half, [1 x <2 x double>], float, [2 x <3 x half>], <3 x half> }>
-// CHECK: %__cblayout_CB_B = type <{ [3 x <3 x double>], <3 x half> }>
-// CHECK: %__cblayout_CB_C = type <{ i32, target("dx.Layout", %F, 96, 0, 16, 28, 32, 56, 64, 80, 84, 90), half, target("dx.Layout", %G, 258, 0, 48, 64, 256), double }>
-
-// CHECK: %F = type <{ double, <3 x float>, float, <3 x double>, half, <2 x double>, float, <3 x half>, <3 x half> }>
-// CHECK: %G = type <{ target("dx.Layout", %E, 36, 0, 8, 16, 20, 22, 24, 32), [1 x float], [2 x target("dx.Layout", %F, 96, 0, 16, 28, 32, 56, 64, 80, 84, 90)], half }>
-// CHECK: %E = type <{ float, double, float, half, i16, i64, i32 }>
+// CHECK: %__cblayout_CB_A = type <{
+// CHECK-SAME: <{ [1 x <{ double, target("dx.Padding", 8) }>], double }>, target("dx.Padding", 8),
+// CHECK-SAME: <{ [2 x <{ <3 x float>, target("dx.Padding", 4) }>], <3 x float> }>, float,
+// CHECK-SAME: <{ [2 x <{ double, target("dx.Padding", 8) }>], double }>, half, target("dx.Padding", 6),
+// CHECK-SAME: [1 x <2 x double>],
+// CHECK-SAME: float, target("dx.Padding", 12),
+// CHECK-SAME: <{ [1 x <{ <3 x half>, target("dx.Padding", 10) }>], <3 x half> }>, <3 x half>
+// CHECK-SAME: }>
+
+// CHECK: %__cblayout_CB_B = type <{
+// CHECK-SAME: <{ [2 x <{ <3 x double>, target("dx.Padding", 8) }>], <3 x double> }>, <3 x half>
+// CHECK-SAME: }>
+
+// CHECK: %__cblayout_CB_C = type <{
+// CHECK-SAME: i32, target("dx.Padding", 12),
+// CHECK-SAME: %F,
+// CHECK-SAME: half, target("dx.Padding", 14),
+// CHECK-SAME: %G, target("dx.Padding", 6), double
+// CHECK-SAME: }>
+
+// CHECK: %F = type <{
+// CHECK-SAME: double, target("dx.Padding", 8),
+// CHECK-SAME: <3 x float>, float,
+// CHECK-SAME: <3 x double>, half, target("dx.Padding", 6),
+// CHECK-SAME: <2 x double>,
+// CHECK-SAME: float, <3 x half>, <3 x half>
+// CHECK-SAME: }>
+
+// CHECK: %G = type <{
+// CHECK-SAME: %E, target("dx.Padding", 12),
+// CHECK-SAME: [1 x float], target("dx.Padding", 12),
+// CHECK-SAME: [2 x %F],
+// CHECK-SAME: half
+// CHECK-SAME: }>
+
+// CHECK: %E = type <{ float, target("dx.Padding", 4), double, float, half, i16, i64, i32 }>
cbuffer CBScalars : register(b1, space5) {
float a1;
@@ -44,8 +130,7 @@ cbuffer CBScalars : register(b1, space5) {
int64_t a8;
}
-// CHECK: @CBScalars.cb = global target("dx.CBuffer", target("dx.Layout", %__cblayout_CBScalars,
-// CHECK-SAME: 56, 0, 8, 16, 24, 32, 36, 40, 48))
+// CHECK: @CBScalars.cb = global target("dx.CBuffer", %__cblayout_CBScalars)
// CHECK: @a1 = external hidden addrspace(2) global float, align 4
// CHECK: @a2 = external hidden addrspace(2) global double, align 8
// CHECK: @a3 = external hidden addrspace(2) global half, align 2
@@ -67,8 +152,7 @@ cbuffer CBVectors {
// FIXME: add a bool vectors after llvm-project/llvm#91639 is added
}
-// CHECK: @CBVectors.cb = global target("dx.CBuffer", target("dx.Layout", %__cblayout_CBVectors,
-// CHECK-SAME: 136, 0, 16, 40, 48, 80, 96, 112))
+// CHECK: @CBVectors.cb = global target("dx.CBuffer", %__cblayout_CBVectors)
// CHECK: @b1 = external hidden addrspace(2) global <3 x float>, align 16
// CHECK: @b2 = external hidden addrspace(2) global <3 x double>, align 32
// CHECK: @b3 = external hidden addrspace(2) global <2 x half>, align 4
@@ -89,16 +173,15 @@ cbuffer CBArrays : register(b2) {
bool c8[4];
}
-// CHECK: @CBArrays.cb = global target("dx.CBuffer", target("dx.Layout", %__cblayout_CBArrays,
-// CHECK-SAME: 708, 0, 48, 112, 176, 224, 608, 624, 656))
-// CHECK: @c1 = external hidden addrspace(2) global [3 x float], align 4
-// CHECK: @c2 = external hidden addrspace(2) global [2 x <3 x double>], align 32
-// CHECK: @c3 = external hidden addrspace(2) global [2 x [2 x half]], align 2
-// CHECK: @c4 = external hidden addrspace(2) global [3 x i64], align 8
+// CHECK: @CBArrays.cb = global target("dx.CBuffer", %__cblayout_CBArrays)
+// CHECK: @c1 = external hidden addrspace(2) global <{ [2 x <{ float, target("dx.Padding", 12) }>], float }>, align 4
+// CHECK: @c2 = external hidden addrspace(2) global <{ [1 x <{ <3 x double>, target("dx.Padding", 8) }>], <3 x double> }>, align 32
+// CHECK: @c3 = external hidden addrspace(2) global <{ [1 x <{ <{ [1 x <{ half, target("dx.Padding", 14) }>], half }>, target("dx.Padding", 14) }>], <{ [1 x <{ half, target("dx.Padding", 14) }>], half }> }>, align 2
+// CHECK: @c4 = external hidden addrspace(2) global <{ [2 x <{ i64, target("dx.Padding", 8) }>], i64 }>, align 8
// CHECK: @c5 = external hidden addrspace(2) global [2 x [3 x [4 x <4 x i32>]]], align 16
// CHECK: @c6 = external hidden addrspace(2) global [1 x i16], align 2
-// CHECK: @c7 = external hidden addrspace(2) global [2 x i64], align 8
-// CHECK: @c8 = external hidden addrspace(2) global [4 x i32], align 4
+// CHECK: @c7 = external hidden addrspace(2) global <{ [1 x <{ i64, target("dx.Padding", 8) }>], i64 }>, align 8
+// CHECK: @c8 = external hidden addrspace(2) global <{ [3 x <{ i32, target("dx.Padding", 12) }>], i32 }>, align 4
// CHECK: @CBArrays.str = private unnamed_addr constant [9 x i8] c"CBArrays\00", align 1
typedef uint32_t4 uint32_t8[2];
@@ -110,8 +193,7 @@ cbuffer CBTypedefArray : register(space2) {
T2 t2[2];
}
-// CHECK: @CBTypedefArray.cb = global target("dx.CBuffer", target("dx.Layout", %__cblayout_CBTypedefArray,
-// CHECK-SAME: 128, 0, 64))
+// CHECK: @CBTypedefArray.cb = global target("dx.CBuffer", %__cblayout_CBTypedefArray)
// CHECK: @t1 = external hidden addrspace(2) global [2 x [2 x <4 x i32>]], align 16
// CHECK: @t2 = external hidden addrspace(2) global [2 x [2 x <4 x i32>]], align 16
// CHECK: @CBTypedefArray.str = private unnamed_addr constant [15 x i8] c"CBTypedefArray\00", align 1
@@ -135,13 +217,12 @@ struct D {
Empty es;
};
-// CHECK: @CBStructs.cb = global target("dx.CBuffer", target("dx.Layout", %__cblayout_CBStructs,
-// CHECK-SAME: 246, 0, 16, 32, 64, 144, 238, 240))
-// CHECK: @a = external hidden addrspace(2) global target("dx.Layout", %A, 8, 0), align 1
-// CHECK: @b = external hidden addrspace(2) global target("dx.Layout", %B, 14, 0, 8), align 1
-// CHECK: @c = external hidden addrspace(2) global target("dx.Layout", %C, 24, 0, 16), align 1
-// CHECK: @array_of_A = external hidden addrspace(2) global [5 x target("dx.Layout", %A, 8, 0)], align 1
-// CHECK: @d = external hidden addrspace(2) global target("dx.Layout", %__cblayout_D, 94, 0), align 1
+// CHECK: @CBStructs.cb = global target("dx.CBuffer", %__cblayout_CBStructs)
+// CHECK: @a = external hidden addrspace(2) global %A, align 1
+// CHECK: @b = external hidden addrspace(2) global %B, align 1
+// CHECK: @c = external hidden addrspace(2) global %C, align 1
+// CHECK: @array_of_A = external hidden addrspace(2) global <{ [4 x <{ %A, target("dx.Padding", 8) }>], %A }>, align 1
+// CHECK: @d = external hidden addrspace(2) global %__cblayout_D, align 1
// CHECK: @e = external hidden addrspace(2) global half, align 2
// CHECK: @f = external hidden addrspace(2) global <3 x i16>, align 8
// CHECK: @CBStructs.str = private unnamed_addr constant [10 x i8] c"CBStructs\00", align 1
@@ -176,27 +257,25 @@ cbuffer CBClasses {
K ka[10];
};
-// CHECK: @CBClasses.cb = global target("dx.CBuffer", target("dx.Layout", %__cblayout_CBClasses,
-// CHECK-SAME: 260, 0, 16, 32, 112))
-// CHECK: @k = external hidden addrspace(2) global target("dx.Layout", %K, 4, 0), align 1
-// CHECK: @l = external hidden addrspace(2) global target("dx.Layout", %L, 8, 0, 4), align 1
-// CHECK: @m = external hidden addrspace(2) global target("dx.Layout", %M, 68, 0), align 1
-// CHECK: @ka = external hidden addrspace(2) global [10 x target("dx.Layout", %K, 4, 0)], align 1
+// CHECK: @CBClasses.cb = global target("dx.CBuffer", %__cblayout_CBClasses)
+// CHECK: @k = external hidden addrspace(2) global %K, align 1
+// CHECK: @l = external hidden addrspace(2) global %L, align 1
+// CHECK: @m = external hidden addrspace(2) global %M, align 1
+// CHECK: @ka = external hidden addrspace(2) global <{ [9 x <{ %K, target("dx.Padding", 12) }>], %K }>, align 1
// CHECK: @CBClasses.str = private unnamed_addr constant [10 x i8] c"CBClasses\00", align 1
struct Test {
float a, b;
};
-// CHECK: @CBMix.cb = global target("dx.CBuffer", target("dx.Layout", %__cblayout_CBMix,
-// CHECK-SAME: 170, 0, 24, 32, 120, 128, 136, 144, 152, 160, 168))
-// CHECK: @test = external hidden addrspace(2) global [2 x target("dx.Layout", %Test, 8, 0, 4)], align 1
+// CHECK: @CBMix.cb = global target("dx.CBuffer", %__cblayout_CBMix)
+// CHECK: @test = external hidden addrspace(2) global <{ [1 x <{ %Test, target("dx.Padding", 8) }>], %Test }>, align 1
// CHECK: @f1 = external hidden addrspace(2) global float, align 4
-// CHECK: @f2 = external hidden addrspace(2) global [3 x [2 x <2 x float>]], align 8
+// CHECK: @f2 = external hidden addrspace(2) global <{ [2 x <{ <{ [1 x <{ <2 x float>, target("dx.Padding", 8) }>], <2 x float> }>, target("dx.Padding", 8) }>], <{ [1 x <{ <2 x float>, target("dx.Padding", 8) }>], <2 x float> }> }>, align 8
// CHECK: @f3 = external hidden addrspace(2) global float, align 4
-// CHECK: @f4 = external hidden addrspace(2) global target("dx.Layout", %anon, 4, 0), align 1
+// CHECK: @f4 = external hidden addrspace(2) global %anon, align 1
// CHECK: @f5 = external hidden addrspace(2) global double, align 8
-// CHECK: @f6 = external hidden addrspace(2) global target("dx.Layout", %anon.0, 8, 0), align 1
+// CHECK: @f6 = external hidden addrspace(2) global %anon.0, align 1
// CHECK: @f7 = external hidden addrspace(2) global float, align 4
// CHECK: @f8 = external hidden addrspace(2) global <1 x double>, align 8
// CHECK: @f9 = external hidden addrspace(2) global i16, align 2
@@ -215,7 +294,7 @@ cbuffer CBMix {
uint16_t f9;
};
-// CHECK: @CB_A.cb = global target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_A, 188, 0, 32, 76, 80, 120, 128, 144, 160, 182))
+// CHECK: @CB_A.cb = global target("dx.CBuffer", %__cblayout_CB_A)
cbuffer CB_A {
double B0[2];
@@ -229,7 +308,7 @@ cbuffer CB_A {
half3 B8;
}
-// CHECK: @CB_B.cb = global target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_B, 94, 0, 88))
+// CHECK: @CB_B.cb = global target("dx.CBuffer", %__cblayout_CB_B)
cbuffer CB_B {
double3 B9[3];
half3 B10;
@@ -264,7 +343,7 @@ struct G {
half C3;
};
-// CHECK: @CB_C.cb = global target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_C, 400, 0, 16, 112, 128, 392))
+// CHECK: @CB_C.cb = global target("dx.CBuffer", %__cblayout_CB_C)
cbuffer CB_C {
int D0;
F D1;
@@ -275,63 +354,63 @@ cbuffer CB_C {
// CHECK: define internal void @_init_buffer_CBScalars.cb()
// CHECK-NEXT: entry:
-// CHECK-NEXT: %CBScalars.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBScalars, 56, 0, 8, 16, 24, 32, 36, 40, 48))
-// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBScalarss_56_0_8_16_24_32_36_40_48tt(i32 5, i32 1, i32 1, i32 0, ptr @CBScalars.str)
-// CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBScalars, 56, 0, 8, 16, 24, 32, 36, 40, 48)) %CBScalars.cb_h, ptr @CBScalars.cb, align 4
+// CHECK-NEXT: %CBScalars.cb_h = call target("dx.CBuffer", %__cblayout_CBScalars)
+// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.CBuffer_s___cblayout_CBScalarsst(i32 5, i32 1, i32 1, i32 0, ptr @CBScalars.str)
+// CHECK-NEXT: store target("dx.CBuffer", %__cblayout_CBScalars) %CBScalars.cb_h, ptr @CBScalars.cb, align 4
// CHECK: define internal void @_init_buffer_CBVectors.cb()
// CHECK-NEXT: entry:
-// CHECK-NEXT: %CBVectors.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBVectors, 136, 0, 16, 40, 48, 80, 96, 112))
-// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBVectorss_136_0_16_40_48_80_96_112tt(i32 0, i32 0, i32 1, i32 0, ptr @CBVectors.str)
-// CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBVectors, 136, 0, 16, 40, 48, 80, 96, 112)) %CBVectors.cb_h, ptr @CBVectors.cb, align 4
+// CHECK-NEXT: %CBVectors.cb_h = call target("dx.CBuffer", %__cblayout_CBVectors)
+// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_s___cblayout_CBVectorsst(i32 0, i32 0, i32 1, i32 0, ptr @CBVectors.str)
+// CHECK-NEXT: store target("dx.CBuffer", %__cblayout_CBVectors) %CBVectors.cb_h, ptr @CBVectors.cb, align 4
// CHECK: define internal void @_init_buffer_CBArrays.cb()
// CHECK-NEXT: entry:
-// CHECK-NEXT: %CBArrays.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBArrays, 708, 0, 48, 112, 176, 224, 608, 624, 656))
-// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBArrayss_708_0_48_112_176_224_608_624_656tt(i32 0, i32 2, i32 1, i32 0, ptr @CBArrays.str)
-// CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBArrays, 708, 0, 48, 112, 176, 224, 608, 624, 656)) %CBArrays.cb_h, ptr @CBArrays.cb, align 4
+// CHECK-NEXT: %CBArrays.cb_h = call target("dx.CBuffer", %__cblayout_CBArrays)
+// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.CBuffer_s___cblayout_CBArraysst(i32 0, i32 2, i32 1, i32 0, ptr @CBArrays.str)
+// CHECK-NEXT: store target("dx.CBuffer", %__cblayout_CBArrays) %CBArrays.cb_h, ptr @CBArrays.cb, align 4
// CHECK: define internal void @_init_buffer_CBTypedefArray.cb()
// CHECK-NEXT: entry:
-// CHECK-NEXT: %CBTypedefArray.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBTypedefArray, 128, 0, 64))
-// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBTypedefArrays_128_0_64tt(i32 1, i32 2, i32 1, i32 0, ptr @CBTypedefArray.str)
-// CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBTypedefArray, 128, 0, 64)) %CBTypedefArray.cb_h, ptr @CBTypedefArray.cb, align 4
+// CHECK-NEXT: %CBTypedefArray.cb_h = call target("dx.CBuffer", %__cblayout_CBTypedefArray)
+// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_s___cblayout_CBTypedefArrayst(i32 1, i32 2, i32 1, i32 0, ptr @CBTypedefArray.str)
+// CHECK-NEXT: store target("dx.CBuffer", %__cblayout_CBTypedefArray) %CBTypedefArray.cb_h, ptr @CBTypedefArray.cb, align 4
// CHECK: define internal void @_init_buffer_CBStructs.cb()
// CHECK-NEXT: entry:
-// CHECK-NEXT: %CBStructs.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBStructs, 246, 0, 16, 32, 64, 144, 238, 240))
-// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBStructss_246_0_16_32_64_144_238_240tt(i32 2, i32 0, i32 1, i32 0, ptr @CBStructs.str)
-// CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBStructs, 246, 0, 16, 32, 64, 144, 238, 240)) %CBStructs.cb_h, ptr @CBStructs.cb, align 4
+// CHECK-NEXT: %CBStructs.cb_h = call target("dx.CBuffer", %__cblayout_CBStructs)
+// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_s___cblayout_CBStructsst(i32 2, i32 0, i32 1, i32 0, ptr @CBStructs.str)
+// CHECK-NEXT: store target("dx.CBuffer", %__cblayout_CBStructs) %CBStructs.cb_h, ptr @CBStructs.cb, align 4
// CHECK: define internal void @_init_buffer_CBClasses.cb()
// CHECK-NEXT: entry:
-// CHECK-NEXT: %CBClasses.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBClasses, 260, 0, 16, 32, 112))
-// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBClassess_260_0_16_32_112tt(i32 3, i32 0, i32 1, i32 0, ptr @CBClasses.str)
-// CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBClasses, 260, 0, 16, 32, 112)) %CBClasses.cb_h, ptr @CBClasses.cb, align 4
+// CHECK-NEXT: %CBClasses.cb_h = call target("dx.CBuffer", %__cblayout_CBClasses)
+// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_s___cblayout_CBClassesst(i32 3, i32 0, i32 1, i32 0, ptr @CBClasses.str)
+// CHECK-NEXT: store target("dx.CBuffer", %__cblayout_CBClasses) %CBClasses.cb_h, ptr @CBClasses.cb, align 4
// CHECK: define internal void @_init_buffer_CBMix.cb()
// CHECK-NEXT: entry:
-// CHECK-NEXT: %CBMix.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBMix, 170, 0, 24, 32, 120, 128, 136, 144, 152, 160, 168))
-// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBMixs_170_0_24_32_120_128_136_144_152_160_168tt(i32 4, i32 0, i32 1, i32 0, ptr @CBMix.str)
-// CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CBMix, 170, 0, 24, 32, 120, 128, 136, 144, 152, 160, 168)) %CBMix.cb_h, ptr @CBMix.cb, align 4
+// CHECK-NEXT: %CBMix.cb_h = call target("dx.CBuffer", %__cblayout_CBMix)
+// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_s___cblayout_CBMixst(i32 4, i32 0, i32 1, i32 0, ptr @CBMix.str)
+// CHECK-NEXT: store target("dx.CBuffer", %__cblayout_CBMix) %CBMix.cb_h, ptr @CBMix.cb, align 4
// CHECK: define internal void @_init_buffer_CB_A.cb()
// CHECK-NEXT: entry:
-// CHECK-NEXT: %CB_A.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_A, 188, 0, 32, 76, 80, 120, 128, 144, 160, 182))
-// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB_As_188_0_32_76_80_120_128_144_160_182tt(i32 5, i32 0, i32 1, i32 0, ptr @CB_A.str)
-// CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_A, 188, 0, 32, 76, 80, 120, 128, 144, 160, 182)) %CB_A.cb_h, ptr @CB_A.cb, align 4
+// CHECK-NEXT: %CB_A.cb_h = call target("dx.CBuffer", %__cblayout_CB_A)
+// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_s___cblayout_CB_Ast(i32 5, i32 0, i32 1, i32 0, ptr @CB_A.str)
+// CHECK-NEXT: store target("dx.CBuffer", %__cblayout_CB_A) %CB_A.cb_h, ptr @CB_A.cb, align 4
// CHECK: define internal void @_init_buffer_CB_B.cb()
// CHECK-NEXT: entry:
-// CHECK-NEXT: %CB_B.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_B, 94, 0, 88))
-// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB_Bs_94_0_88tt(i32 6, i32 0, i32 1, i32 0, ptr @CB_B.str)
-// CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_B, 94, 0, 88)) %CB_B.cb_h, ptr @CB_B.cb, align 4
+// CHECK-NEXT: %CB_B.cb_h = call target("dx.CBuffer", %__cblayout_CB_B)
+// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_s___cblayout_CB_Bst(i32 6, i32 0, i32 1, i32 0, ptr @CB_B.str)
+// CHECK-NEXT: store target("dx.CBuffer", %__cblayout_CB_B) %CB_B.cb_h, ptr @CB_B.cb, align 4
// CHECK: define internal void @_init_buffer_CB_C.cb()
// CHECK-NEXT: entry:
-// CHECK-NEXT: %CB_C.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_C, 400, 0, 16, 112, 128, 392))
-// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB_Cs_400_0_16_112_128_392tt(i32 7, i32 0, i32 1, i32 0, ptr @CB_C.str)
-// CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_C, 400, 0, 16, 112, 128, 392)) %CB_C.cb_h, ptr @CB_C.cb, align 4
+// CHECK-NEXT: %CB_C.cb_h = call target("dx.CBuffer", %__cblayout_CB_C)
+// CHECK-SAME: @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_s___cblayout_CB_Cst(i32 7, i32 0, i32 1, i32 0, ptr @CB_C.str)
+// CHECK-NEXT: store target("dx.CBuffer", %__cblayout_CB_C) %CB_C.cb_h, ptr @CB_C.cb, align 4
RWBuffer<float> Buf;
diff --git a/clang/test/CodeGenHLSL/resources/cbuffer_and_namespaces.hlsl b/clang/test/CodeGenHLSL/resources/cbuffer_and_namespaces.hlsl
index b7bdce3..1fe0a68 100644
--- a/clang/test/CodeGenHLSL/resources/cbuffer_and_namespaces.hlsl
+++ b/clang/test/CodeGenHLSL/resources/cbuffer_and_namespaces.hlsl
@@ -4,18 +4,18 @@
// CHECK: %"n0::n1::__cblayout_A" = type <{ float }>
// CHECK: %"n0::__cblayout_B" = type <{ float }>
-// CHECK: %"n0::n2::__cblayout_C" = type <{ float, target("dx.Layout", %"n0::Foo", 4, 0) }>
+// CHECK: %"n0::n2::__cblayout_C" = type <{ float, target("dx.Padding", 12), %"n0::Foo" }>
// CHECK: %"n0::Foo" = type <{ float }>
-// CHECK: @A.cb = global target("dx.CBuffer", target("dx.Layout", %"n0::n1::__cblayout_A", 4, 0))
+// CHECK: @A.cb = global target("dx.CBuffer", %"n0::n1::__cblayout_A")
// CHECK: @_ZN2n02n11aE = external hidden addrspace(2) global float, align 4
-// CHECK: @B.cb = global target("dx.CBuffer", target("dx.Layout", %"n0::__cblayout_B", 4, 0))
+// CHECK: @B.cb = global target("dx.CBuffer", %"n0::__cblayout_B")
// CHECK: @_ZN2n01aE = external hidden addrspace(2) global float, align 4
-// CHECK: @C.cb = global target("dx.CBuffer", target("dx.Layout", %"n0::n2::__cblayout_C", 20, 0, 16))
+// CHECK: @C.cb = global target("dx.CBuffer", %"n0::n2::__cblayout_C")
// CHECK: @_ZN2n02n21aE = external hidden addrspace(2) global float, align 4
-// CHECK: external hidden addrspace(2) global target("dx.Layout", %"n0::Foo", 4, 0), align 1
+// CHECK: external hidden addrspace(2) global %"n0::Foo", align 1
namespace n0 {
struct Foo {
diff --git a/clang/test/CodeGenHLSL/resources/cbuffer_geps.hlsl b/clang/test/CodeGenHLSL/resources/cbuffer_geps.hlsl
new file mode 100644
index 0000000..7a0b458
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/cbuffer_geps.hlsl
@@ -0,0 +1,117 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-compute -fnative-half-type -fnative-int16-type -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
+
+// Capture the anonymous struct types for check lines below.
+// CHECK: [[ANON_1:%.*]] = type <{ float, target("dx.Padding", 12), <4 x i32> }>
+// CHECK: [[ANON_2:%.*]] = type <{ <2 x i32>, target("dx.Padding", 8), <{ [3 x <{ %ArrayAndScalar, target("dx.Padding", 12) }>], %ArrayAndScalar }>
+
+template <typename T> void use(T);
+
+cbuffer CBArrays : register(b2) {
+ float c1[30];
+ double3 c2[20];
+ float16_t c3[10][20];
+ uint64_t c4[30];
+ int4 c5[20][30][40];
+ uint16_t c6[10];
+ int64_t c7[20];
+ bool c8[40];
+}
+
+// CHECK-LABEL: define hidden void @_Z8cbarraysv()
+void cbarrays() {
+ // CHECK: load float, ptr addrspace(2) @c1, align 16
+ use(c1[0]);
+ // CHECK: load float, ptr addrspace(2) getelementptr (<{ float, target("dx.Padding", 12) }>, ptr addrspace(2) @c1, i32 7, i32 0), align 16
+ use(c1[7]);
+ // CHECK: load float, ptr addrspace(2) getelementptr (<{ float, target("dx.Padding", 12) }>, ptr addrspace(2) @c1, i32 29, i32 0), align 16
+ use(c1[29]);
+
+ // CHECK: load <3 x double>, ptr addrspace(2) getelementptr (<{ <3 x double>, target("dx.Padding", 8) }>, ptr addrspace(2) @c2, i32 8, i32 0), align 32
+ use(c2[8]);
+ // CHECK: load half, ptr addrspace(2) getelementptr (<{ half, target("dx.Padding", 14) }>, ptr addrspace(2) getelementptr (<{ <{ [19 x <{ half, target("dx.Padding", 14) }>], half }>, target("dx.Padding", 14) }>, ptr addrspace(2) @c3, i32 9, i32 0), i32 5, i32 0), align 16
+ use(c3[9][5]);
+ // CHECK: load i64, ptr addrspace(2) getelementptr (<{ i64, target("dx.Padding", 8) }>, ptr addrspace(2) @c4, i32 6, i32 0), align 16
+ use(c4[6]);
+ // CHECK: load <4 x i32>, ptr addrspace(2) getelementptr inbounds ([40 x <4 x i32>], ptr addrspace(2) getelementptr inbounds ([30 x [40 x <4 x i32>]], ptr addrspace(2) getelementptr inbounds ([20 x [30 x [40 x <4 x i32>]]], ptr addrspace(2) @c5, i32 0, i32 1), i32 0, i32 12), i32 0, i32 15), align 16
+ use(c5[1][12][15]);
+ // CHECK: load i16, ptr addrspace(2) getelementptr (<{ i16, target("dx.Padding", 14) }>, ptr addrspace(2) @c6, i32 4, i32 0), align 16
+ use(c6[4]);
+ // CHECK: load i64, ptr addrspace(2) getelementptr (<{ i64, target("dx.Padding", 8) }>, ptr addrspace(2) @c7, i32 17, i32 0), align 16
+ use(c7[17]);
+ // CHECK: load i32, ptr addrspace(2) getelementptr (<{ i32, target("dx.Padding", 12) }>, ptr addrspace(2) @c8, i32 30, i32 0), align 16
+ use(c8[30]);
+}
+
+struct A {
+ float2 a1;
+};
+
+struct B : A {
+ uint16_t3 b1;
+};
+
+struct C {
+ int c1;
+ A c2;
+};
+
+struct D {
+ B d1[4][6];
+};
+
+cbuffer CBStructs {
+ A s1;
+ B s2;
+ C s3;
+ A s4[5];
+ D s5;
+};
+
+// CHECK-LABEL: define hidden void @_Z9cbstructsv()
+void cbstructs() {
+ // CHECK: load <2 x float>, ptr addrspace(2) @s1, align 8
+ use(s1.a1);
+ // CHECK: load <3 x i16>, ptr addrspace(2) getelementptr inbounds nuw (%B, ptr addrspace(2) @s2, i32 0, i32 1), align 2
+ use(s2.b1);
+ // CHECK: load <2 x float>, ptr addrspace(2) getelementptr inbounds nuw (%C, ptr addrspace(2) @s3, i32 0, i32 1), align 8
+ use(s3.c2.a1);
+ // CHECK: load <2 x float>, ptr addrspace(2) getelementptr (<{ %A, target("dx.Padding", 8) }>, ptr addrspace(2) @s4, i32 2, i32 0), align 8
+ use(s4[2].a1);
+ // CHECK: load <3 x i16>, ptr addrspace(2) getelementptr inbounds nuw (%B, ptr addrspace(2) getelementptr (<{ %B, target("dx.Padding", 2) }>, ptr addrspace(2) getelementptr (<{ <{ [5 x <{ %B, target("dx.Padding", 2) }>], %B }>, target("dx.Padding", 2) }>, ptr addrspace(2) @s5, i32 3, i32 0), i32 5, i32 0), i32 0, i32 1), align 2
+ use(s5.d1[3][5].b1);
+}
+
+struct Scalars {
+ float a, b;
+};
+
+struct ArrayAndScalar {
+ uint4 x[5];
+ float y;
+};
+
+cbuffer CBMix {
+ Scalars m1[3];
+ float m2;
+ ArrayAndScalar m3;
+ float2 m4[5][4];
+ struct { float c; uint4 d; } m5;
+ struct { int2 i; ArrayAndScalar j[4]; } m6;
+ vector<double, 1> m7;
+};
+
+// CHECK-LABEL: define hidden void @_Z5cbmixv()
+void cbmix() {
+ // CHECK: load float, ptr addrspace(2) getelementptr inbounds nuw (%Scalars, ptr addrspace(2) getelementptr (<{ %Scalars, target("dx.Padding", 8) }>, ptr addrspace(2) @m1, i32 2, i32 0), i32 0, i32 1), align 4
+ use(m1[2].b);
+ // CHECK: load float, ptr addrspace(2) getelementptr inbounds nuw (%ArrayAndScalar, ptr addrspace(2) @m3, i32 0, i32 1), align 4
+ use(m3.y);
+ // CHECK: load <2 x float>, ptr addrspace(2) getelementptr (<{ <2 x float>, target("dx.Padding", 8) }>, ptr addrspace(2) getelementptr (<{ <{ [3 x <{ <2 x float>, target("dx.Padding", 8) }>], <2 x float> }>, target("dx.Padding", 8) }>, ptr addrspace(2) @m4, i32 2, i32 0), i32 3, i32 0), align 16
+ use(m4[2][3]);
+ // CHECK: load <4 x i32>, ptr addrspace(2) getelementptr inbounds nuw ([[ANON_1]], ptr addrspace(2) @m5, i32 0, i32 1), align 16
+ use(m5.d);
+ // CHECK: load <4 x i32>, ptr addrspace(2) getelementptr inbounds ([5 x <4 x i32>], ptr addrspace(2) getelementptr (<{ %ArrayAndScalar, target("dx.Padding", 12) }>, ptr addrspace(2) getelementptr inbounds nuw ([[ANON_2]], ptr addrspace(2) @m6, i32 0, i32 1), i32 2, i32 0), i32 0, i32 2), align 16
+ use(m6.j[2].x[2]);
+ // CHECK: load <1 x double>, ptr addrspace(2) @m7, align 8
+ use(m7);
+}
diff --git a/clang/test/CodeGenHLSL/resources/cbuffer_with_packoffset.hlsl b/clang/test/CodeGenHLSL/resources/cbuffer_with_packoffset.hlsl
index 7bedd63..68e263b 100644
--- a/clang/test/CodeGenHLSL/resources/cbuffer_with_packoffset.hlsl
+++ b/clang/test/CodeGenHLSL/resources/cbuffer_with_packoffset.hlsl
@@ -2,13 +2,24 @@
// RUN: dxil-pc-shadermodel6.3-compute %s \
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s
-// CHECK: %__cblayout_CB = type <{ float, double, <2 x i32> }>
-// CHECK: %__cblayout_CB_1 = type <{ float, <2 x float> }>
-
-// CHECK: @CB.cb = global target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 176, 16, 168, 88))
-// CHECK: @a = external hidden addrspace(2) global float, align 4
-// CHECK: @b = external hidden addrspace(2) global double, align 8
-// CHECK: @c = external hidden addrspace(2) global <2 x i32>, align 8
+// CHECK: %__cblayout_CB = type <{
+// CHECK-SAME: target("dx.Padding", 16),
+// CHECK-SAME: float,
+// CHECK-SAME: target("dx.Padding", 68),
+// CHECK-SAME: <2 x i32>,
+// CHECK-SAME target("dx.Padding", 72),
+// CHECK-SAME: double
+// CHECK-SAME: }>
+// CHECK: %__cblayout_CB_1 = type <{
+// CHECK-SAME: target("dx.Padding", 80),
+// CHECK-SAME: <2 x float>,
+// CHECK-SAME: float
+// CHECK-SAME: }>
+
+// CHECK-DAG: @CB.cb = global target("dx.CBuffer", %__cblayout_CB)
+// CHECK-DAG: @a = external hidden addrspace(2) global float, align 4
+// CHECK-DAG: @b = external hidden addrspace(2) global double, align 8
+// CHECK-DAG: @c = external hidden addrspace(2) global <2 x i32>, align 8
// CHECK: @CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1
cbuffer CB : register(b1, space3) {
@@ -17,9 +28,9 @@ cbuffer CB : register(b1, space3) {
int2 c : packoffset(c5.z);
}
-// CHECK: @CB.cb.1 = global target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_1, 92, 88, 80))
-// CHECK: @x = external hidden addrspace(2) global float, align 4
-// CHECK: @y = external hidden addrspace(2) global <2 x float>, align 8
+// CHECK-DAG: @CB.cb.1 = global target("dx.CBuffer", %__cblayout_CB_1)
+// CHECK-DAG: @x = external hidden addrspace(2) global float, align 4
+// CHECK-DAG: @y = external hidden addrspace(2) global <2 x float>, align 8
// Missing packoffset annotation will produce a warning.
// Element x will be placed after the element y that has an explicit packoffset.
@@ -30,8 +41,7 @@ cbuffer CB : register(b0) {
// CHECK: define internal void @_init_buffer_CB.cb()
// CHECK-NEXT: entry:
-// CHECK-NEXT: %CB.cb_h = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 176, 16, 168, 88))
-// CHECK-SAME: @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_176_16_168_88tt(i32 3, i32 1, i32 1, i32 0, ptr @CB.str)
+// CHECK-NEXT: %CB.cb_h = call target("dx.CBuffer", %__cblayout_CB) @llvm.dx.resource.handlefrombinding.tdx.CBuffer_s___cblayout_CBst(i32 3, i32 1, i32 1, i32 0, ptr @CB.str)
float foo() {
// CHECK: load float, ptr addrspace(2) @a, align 4
@@ -48,5 +58,5 @@ void main() {
}
// CHECK: !hlsl.cbs = !{![[CB1:[0-9]+]], ![[CB2:[0-9]+]]}
-// CHECK: ![[CB1]] = !{ptr @CB.cb, ptr addrspace(2) @a, ptr addrspace(2) @b, ptr addrspace(2) @c}
-// CHECK: ![[CB2]] = !{ptr @CB.cb.1, ptr addrspace(2) @x, ptr addrspace(2) @y}
+// CHECK: ![[CB1]] = !{ptr @CB.cb, ptr addrspace(2) @a, ptr addrspace(2) @c, ptr addrspace(2) @b}
+// CHECK: ![[CB2]] = !{ptr @CB.cb.1, ptr addrspace(2) @y, ptr addrspace(2) @x}
diff --git a/clang/test/CodeGenHLSL/resources/cbuffer_with_static_global_and_function.hlsl b/clang/test/CodeGenHLSL/resources/cbuffer_with_static_global_and_function.hlsl
index fa3405d..b8c7bab 100644
--- a/clang/test/CodeGenHLSL/resources/cbuffer_with_static_global_and_function.hlsl
+++ b/clang/test/CodeGenHLSL/resources/cbuffer_with_static_global_and_function.hlsl
@@ -2,7 +2,7 @@
// CHECK: %__cblayout_A = type <{ float }>
-// CHECK: @A.cb = global target("dx.CBuffer", target("dx.Layout", %__cblayout_A, 4, 0))
+// CHECK: @A.cb = global target("dx.CBuffer", %__cblayout_A)
// CHECK: @a = external hidden addrspace(2) global float, align 4
// CHECK-DAG: @_ZL1b = internal global float 3.000000e+00, align 4
// CHECK-NOT: @B.cb
diff --git a/clang/test/CodeGenHLSL/resources/default_cbuffer.hlsl b/clang/test/CodeGenHLSL/resources/default_cbuffer.hlsl
index ad4d92f..5333dad 100644
--- a/clang/test/CodeGenHLSL/resources/default_cbuffer.hlsl
+++ b/clang/test/CodeGenHLSL/resources/default_cbuffer.hlsl
@@ -1,19 +1,18 @@
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-compute -fnative-half-type -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,DXIL
// RUN: %clang_cc1 -finclude-default-header -triple spirv-pc-vulkan1.3-compute -fnative-half-type -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,SPIRV
-// DXIL: %"__cblayout_$Globals" = type <{ float, float, target("dx.Layout", %__cblayout_S, 4, 0) }>
-// SPIRV: %"__cblayout_$Globals" = type <{ float, float, target("spirv.Layout", %__cblayout_S, 4, 0) }>
+// CHECK: %"__cblayout_$Globals" = type <{ float, float, target("{{.*}}.Padding", 8), %__cblayout_S }>
// CHECK: %__cblayout_S = type <{ float }>
-// DXIL-DAG: @"$Globals.cb" = global target("dx.CBuffer", target("dx.Layout", %"__cblayout_$Globals", 20, 0, 4, 16))
+// DXIL-DAG: @"$Globals.cb" = global target("dx.CBuffer", %"__cblayout_$Globals")
// DXIL-DAG: @a = external hidden addrspace(2) global float
// DXIL-DAG: @g = external hidden addrspace(2) global float
-// DXIL-DAG: @h = external hidden addrspace(2) global target("dx.Layout", %__cblayout_S, 4, 0), align 4
+// DXIL-DAG: @h = external hidden addrspace(2) global %__cblayout_S, align 4
-// SPIRV-DAG: @"$Globals.cb" = global target("spirv.VulkanBuffer", target("spirv.Layout", %"__cblayout_$Globals", 20, 0, 4, 16), 2, 0)
+// SPIRV-DAG: @"$Globals.cb" = global target("spirv.VulkanBuffer", %"__cblayout_$Globals", 2, 0)
// SPIRV-DAG: @a = external hidden addrspace(12) global float
// SPIRV-DAG: @g = external hidden addrspace(12) global float
-// SPIRV-DAG: @h = external hidden addrspace(12) global target("spirv.Layout", %__cblayout_S, 4, 0), align 8
+// SPIRV-DAG: @h = external hidden addrspace(12) global %__cblayout_S, align 8
struct EmptyStruct {
};
diff --git a/clang/test/CodeGenHLSL/resources/default_cbuffer_with_layout.hlsl b/clang/test/CodeGenHLSL/resources/default_cbuffer_with_layout.hlsl
index 1b2cb0e..7be1f90 100644
--- a/clang/test/CodeGenHLSL/resources/default_cbuffer_with_layout.hlsl
+++ b/clang/test/CodeGenHLSL/resources/default_cbuffer_with_layout.hlsl
@@ -1,17 +1,26 @@
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-compute -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
-// CHECK: %"__cblayout_$Globals" = type <{ i32, float, [4 x double], <4 x i32>, <4 x float>,
-// CHECK-SAME: target("dx.Layout", %S, 8, 0) }>
+// CHECK: %"__cblayout_$Globals" = type <{
+// CHECK-SAME: float,
+// CHECK-SAME: target("dx.Padding", 12),
+// CHECK-SAME: <{ [3 x <{ double, target("dx.Padding", 8) }>], double }>,
+// CHECK-SAME: target("dx.Padding", 8),
+// CHECK-SAME: <4 x i32>,
+// CHECK-SAME: %S
+// CHECK-SAME: i32,
+// CHECK-SAME: target("dx.Padding", 4),
+// CHECK-SAME: <4 x float>
+// CHECK-SAME: }>
+
// CHECK: %S = type <{ <2 x float> }>
+// CHECK-DAG: @"$Globals.cb" = global target("dx.CBuffer", %"__cblayout_$Globals")
+// CHECK-DAG: @a = external hidden addrspace(2) global i32, align 4
// CHECK-DAG: @b = external hidden addrspace(2) global float, align 4
+// CHECK-DAG: @c = external hidden addrspace(2) global <{ [3 x <{ double, target("dx.Padding", 8) }>], double }>, align 8
// CHECK-DAG: @d = external hidden addrspace(2) global <4 x i32>, align 16
-// CHECK-DAG: @"$Globals.cb" = global target("dx.CBuffer",
-// CHECK-DAG-SAME: target("dx.Layout", %"__cblayout_$Globals", 144, 120, 16, 32, 64, 128, 112))
-// CHECK-DAG: @a = external hidden addrspace(2) global i32, align 4
-// CHECK-DAG: @c = external hidden addrspace(2) global [4 x double], align 8
// CHECK-DAG: @e = external hidden addrspace(2) global <4 x float>, align 16
-// CHECK-DAG: @s = external hidden addrspace(2) global target("dx.Layout", %S, 8, 0), align 1
+// CHECK-DAG: @s = external hidden addrspace(2) global %S, align 1
struct S {
float2 v;
@@ -19,8 +28,8 @@ struct S {
int a;
float b : register(c1);
+int4 d : register(c6);
double c[4] : register(c2);
-int4 d : register(c4);
float4 e;
S s : register(c7);
@@ -32,5 +41,4 @@ void main() {
}
// CHECK: !hlsl.cbs = !{![[CB:.*]]}
-// CHECK: ![[CB]] = !{ptr @"$Globals.cb", ptr addrspace(2) @a, ptr addrspace(2) @b, ptr addrspace(2) @c,
-// CHECK-SAME: ptr addrspace(2) @d, ptr addrspace(2) @e, ptr addrspace(2) @s}
+// CHECK: ![[CB]] = !{ptr @"$Globals.cb", ptr addrspace(2) @b, ptr addrspace(2) @c, ptr addrspace(2) @d, ptr addrspace(2) @s, ptr addrspace(2) @a, ptr addrspace(2) @e}
diff --git a/clang/test/CodeGenHLSL/semantics/DispatchThreadID-noindex.hlsl b/clang/test/CodeGenHLSL/semantics/DispatchThreadID-noindex.hlsl
index 9ed5457..b41bb0b 100644
--- a/clang/test/CodeGenHLSL/semantics/DispatchThreadID-noindex.hlsl
+++ b/clang/test/CodeGenHLSL/semantics/DispatchThreadID-noindex.hlsl
@@ -4,5 +4,5 @@
[shader("compute")]
[numthreads(8,8,1)]
void foo(uint Idx : SV_DispatchThreadID1) {
- // expected-error@-1 {{semantic SV_DispatchThreadID does not allow indexing}}
+ // expected-error@-1 {{semantic 'SV_DispatchThreadID' does not allow indexing}}
}
diff --git a/clang/test/CodeGenHLSL/semantics/DispatchThreadID.hlsl b/clang/test/CodeGenHLSL/semantics/DispatchThreadID.hlsl
index 7aeb877..b0abaed 100644
--- a/clang/test/CodeGenHLSL/semantics/DispatchThreadID.hlsl
+++ b/clang/test/CodeGenHLSL/semantics/DispatchThreadID.hlsl
@@ -24,4 +24,3 @@ void foo(uint Idx : SV_DispatchThreadID) {}
[shader("compute")]
[numthreads(8,8,1)]
void bar(uint2 Idx : SV_DispatchThreadID) {}
-
diff --git a/clang/test/CodeGenHLSL/semantics/SV_GroupID-noindex.hlsl b/clang/test/CodeGenHLSL/semantics/SV_GroupID-noindex.hlsl
index 8fa0b07..795e880 100644
--- a/clang/test/CodeGenHLSL/semantics/SV_GroupID-noindex.hlsl
+++ b/clang/test/CodeGenHLSL/semantics/SV_GroupID-noindex.hlsl
@@ -4,6 +4,11 @@
[shader("compute")]
[numthreads(8,8,1)]
void foo(uint Idx : SV_GroupID1) {
- // expected-error@-1 {{semantic SV_GroupID does not allow indexing}}
+ // expected-error@-1 {{semantic 'SV_GroupID' does not allow indexing}}
}
+[shader("compute")]
+[numthreads(8,8,1)]
+void bar(uint Idx : SV_GROUPID1) {
+ // expected-error@-1 {{semantic 'SV_GROUPID' does not allow indexing}}
+}
diff --git a/clang/test/CodeGenHLSL/semantics/SV_GroupThreadID-noindex.hlsl b/clang/test/CodeGenHLSL/semantics/SV_GroupThreadID-noindex.hlsl
index da72e85..1fd5ae4 100644
--- a/clang/test/CodeGenHLSL/semantics/SV_GroupThreadID-noindex.hlsl
+++ b/clang/test/CodeGenHLSL/semantics/SV_GroupThreadID-noindex.hlsl
@@ -4,5 +4,5 @@
[shader("compute")]
[numthreads(8,8,1)]
void foo(uint Idx : SV_GroupThreadID1) {
- // expected-error@-1 {{semantic SV_GroupThreadID does not allow indexing}}
+ // expected-error@-1 {{semantic 'SV_GroupThreadID' does not allow indexing}}
}
diff --git a/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
index 1bba87e..b7d2283 100644
--- a/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
+++ b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
@@ -1,10 +1,21 @@
-// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-SPIRV
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-DXIL
-// CHECK: @SV_Position = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations !0
+// CHECK-SPIRV: @SV_Position = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations ![[#MD_0:]]
// CHECK: define void @main() {{.*}} {
-float4 main(float4 p : SV_Position) {
- // CHECK: %[[#P:]] = load <4 x float>, ptr addrspace(7) @SV_Position, align 16
- // CHECK: %[[#R:]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> %[[#P]])
+float4 main(float4 p : SV_Position) : A {
+ // CHECK-SPIRV: %[[#P:]] = load <4 x float>, ptr addrspace(7) @SV_Position, align 16
+ // CHECK-SPIRV: %[[#R:]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> %[[#P]])
+ // CHECK-SPIRV: store <4 x float> %[[#R]], ptr addrspace(8) @A0, align 16
+
+ // CHECK-DXIL: %SV_Position0 = call <4 x float> @llvm.dx.load.input.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison)
+ // CHECK-DXIL: %[[#TMP:]] = call <4 x float> @_Z4mainDv4_f(<4 x float> %SV_Position0)
+ // CHECK-DXIL: call void @llvm.dx.store.output.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison, <4 x float> %[[#TMP]])
return p;
}
+
+// CHECK-SPIRV-DAG: ![[#MD_0]] = !{![[#MD_1:]]}
+// CHECK-SPIRV-DAG: ![[#MD_1]] = !{i32 11, i32 15}
+// | `-> BuiltIn Position
+// `-> SPIR-V decoration 'FragCoord'
diff --git a/clang/test/CodeGenHLSL/semantics/SV_Position.vs.hlsl b/clang/test/CodeGenHLSL/semantics/SV_Position.vs.hlsl
new file mode 100644
index 0000000..0156c0b
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/SV_Position.vs.hlsl
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple dxil-unknown-shadermodel6.8-vertex -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck --check-prefix=CHECK-DXIL %s
+// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-vertex -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck --check-prefix=CHECK-SPIRV %s
+
+// CHECK-SPIRV: @SV_Position0 = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations ![[#MD_0:]]
+// CHECK-SPIRV: @SV_Position = external hidden thread_local addrspace(8) global <4 x float>, !spirv.Decorations ![[#MD_2:]]
+
+// CHECK: define void @main() {{.*}} {
+float4 main(float4 p : SV_Position) : SV_Position {
+ // CHECK-SPIRV: %[[#P:]] = load <4 x float>, ptr addrspace(7) @SV_Position0, align 16
+ // CHECK-SPIRV: %[[#R:]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> %[[#P]])
+ // CHECK-SPIRV: store <4 x float> %[[#R]], ptr addrspace(8) @SV_Position, align 16
+
+ // CHECK-DXIL: %SV_Position0 = call <4 x float> @llvm.dx.load.input.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison)
+ // CHECK-DXIL: %[[#TMP:]] = call <4 x float> @_Z4mainDv4_f(<4 x float> %SV_Position0)
+ // CHECK-DXIL: call void @llvm.dx.store.output.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison, <4 x float> %[[#TMP]])
+ return p;
+}
+
+// CHECK-SPIRV-DAG: ![[#MD_0]] = !{![[#MD_1:]]}
+// CHECK-SPIRV-DAG: ![[#MD_2]] = !{![[#MD_3:]]}
+// CHECK-SPIRV-DAG: ![[#MD_1]] = !{i32 30, i32 0}
+// | `-> Location 0
+// `-> SPIR-V decoration 'Location'
+// CHECK-SPIRV-DAG: ![[#MD_3]] = !{i32 11, i32 0}
+// | `-> BuiltIn Position
+// `-> SPIR-V decoration 'BuiltIn'
diff --git a/clang/test/CodeGenHLSL/semantics/SV_Target.ps.hlsl b/clang/test/CodeGenHLSL/semantics/SV_Target.ps.hlsl
new file mode 100644
index 0000000..4dc622a
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/SV_Target.ps.hlsl
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-SPIRV
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-DXIL
+
+// CHECK-SPIRV: @SV_Target0 = external hidden thread_local addrspace(8) global <4 x float>, !spirv.Decorations ![[#MD_2:]]
+
+// CHECK: define void @main() {{.*}} {
+float4 main(float4 p : SV_Position) : SV_Target {
+ // CHECK-SPIRV: %[[#R:]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> %[[#]])
+ // CHECK-SPIRV: store <4 x float> %[[#R]], ptr addrspace(8) @SV_Target0, align 16
+
+ // CHECK-DXIL: %[[#TMP:]] = call <4 x float> @_Z4mainDv4_f(<4 x float> %SV_Position0)
+ // CHECK-DXIL: call void @llvm.dx.store.output.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison, <4 x float> %[[#TMP]])
+ return p;
+}
+
+// CHECK-SPIRV-DAG: ![[#MD_2]] = !{![[#MD_3:]]}
+// CHECK-SPIRV-DAG: ![[#MD_3]] = !{i32 30, i32 0}
+// | `-> Location index
+// `-> SPIR-V decoration 'Location'
diff --git a/clang/test/CodeGenHLSL/semantics/semantic-struct-2-output.hlsl b/clang/test/CodeGenHLSL/semantics/semantic-struct-2-output.hlsl
new file mode 100644
index 0000000..2f8dc97
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/semantic-struct-2-output.hlsl
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK-DX,CHECK
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK-VK,CHECK
+
+
+struct Input {
+ float Idx : SV_Position0;
+ float Gid : SV_Position1;
+};
+
+struct Output {
+ float a : A;
+ float b : B;
+};
+
+// Make sure SV_DispatchThreadID translated into dx.thread.id.
+
+// CHECK-DX: define hidden void @_Z3foo5Input(ptr dead_on_unwind noalias writable sret(%struct.Output) align 1 %agg.result, ptr noundef byval(%struct.Input) align 1 %input)
+// CHECK-VK: define hidden spir_func void @_Z3foo5Input(ptr dead_on_unwind noalias writable sret(%struct.Output) align 1 %agg.result, ptr noundef byval(%struct.Input) align 1 %input)
+
+// CHECK: %Idx = getelementptr inbounds nuw %struct.Input, ptr %input, i32 0, i32 0
+// CHECK: %[[#tmp:]] = load float, ptr %Idx, align 1
+// CHECK: %a = getelementptr inbounds nuw %struct.Output, ptr %agg.result, i32 0, i32 0
+// CHECK: store float %[[#tmp]], ptr %a, align 1
+// CHECK: %Gid = getelementptr inbounds nuw %struct.Input, ptr %input, i32 0, i32 1
+// CHECK: %[[#tmp:]] = load float, ptr %Gid, align 1
+// CHECK: %b = getelementptr inbounds nuw %struct.Output, ptr %agg.result, i32 0, i32 1
+// CHECK: store float %[[#tmp]], ptr %b, align 1
+
+Output foo(Input input) {
+ Output o;
+ o.a = input.Idx;
+ o.b = input.Gid;
+ return o;
+}
+
diff --git a/clang/test/CodeGenHLSL/semantics/semantic.arbitrary.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.arbitrary.hlsl
new file mode 100644
index 0000000..96d5b99
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/semantic.arbitrary.hlsl
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -triple spirv-unknown-vulkan-vertex -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV -DTARGET=spv
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-vertex -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL -DTARGET=dx
+
+// CHECK-SPIRV-DAG: @AAA0 = external hidden thread_local addrspace(7) externally_initialized constant float, !spirv.Decorations ![[#METADATA_0:]]
+// CHECK-SPIRV-DAG: @B0 = external hidden thread_local addrspace(7) externally_initialized constant i32, !spirv.Decorations ![[#METADATA_2:]]
+// CHECK-SPIRV-DAG: @CC0 = external hidden thread_local addrspace(7) externally_initialized constant <2 x float>, !spirv.Decorations ![[#METADATA_4:]]
+
+
+// FIXME: replace `float2 c` with a matrix when available.
+void main(float a : AAA, int b : B, float2 c : CC) {
+ float tmp = a + b + c.x + c.y;
+}
+// CHECK-SPIRV: define internal spir_func void @_Z4mainfiDv2_f(float noundef nofpclass(nan inf) %a, i32 noundef %b, <2 x float> noundef nofpclass(nan inf) %c) #0 {
+
+// CHECK: define void @main()
+
+// CHECK-DXIL: %AAA0 = call float @llvm.dx.load.input.f32(i32 4, i32 0, i32 0, i8 0, i32 poison)
+// CHECK-DXIL: %B0 = call i32 @llvm.dx.load.input.i32(i32 4, i32 0, i32 0, i8 0, i32 poison)
+// CHECK-DXIL %CC0 = call <2 x float> @llvm.dx.load.input.v2f32(i32 4, i32 0, i32 0, i8 0, i32 poison)
+// CHECK-DXIL: call void @_Z4mainfiDv2_f(float %AAA0, i32 %B0, <2 x float> %CC0)
+
+// CHECK-SPIRV: %[[#AAA0:]] = load float, ptr addrspace(7) @AAA0, align 4
+// CHECK-SPIRV: %[[#B0:]] = load i32, ptr addrspace(7) @B0, align 4
+// CHECK-SPIRV: %[[#CC0:]] = load <2 x float>, ptr addrspace(7) @CC0, align 8
+// CHECK-SPIRV: call spir_func void @_Z4mainfiDv2_f(float %[[#AAA0]], i32 %[[#B0]], <2 x float> %[[#CC0]]) [ "convergencectrl"(token %0) ]
+
+
+// CHECK-SPIRV-DAG: ![[#METADATA_0]] = !{![[#METADATA_1:]]}
+// CHECK-SPIRV-DAG: ![[#METADATA_2]] = !{![[#METADATA_3:]]}
+// CHECK-SPIRV-DAG: ![[#METADATA_4]] = !{![[#METADATA_5:]]}
+
+// CHECK-SPIRV-DAG: ![[#METADATA_1]] = !{i32 30, i32 0}
+// CHECK-SPIRV-DAG: ![[#METADATA_3]] = !{i32 30, i32 1}
+// CHECK-SPIRV-DAG: ![[#METADATA_5]] = !{i32 30, i32 2}
+// | `- Location index
+// `-> Decoration "Location"
diff --git a/clang/test/CodeGenHLSL/semantics/semantic.array.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.array.hlsl
new file mode 100644
index 0000000..f57ac607
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/semantic.array.hlsl
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV -DTARGET=spv
+// RUN: %clang_cc1 -triple dxil-px-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL -DTARGET=dx
+
+struct S0 {
+ float4 position[2];
+ float4 color;
+};
+
+// CHECK: %struct.S0 = type { [2 x <4 x float>], <4 x float> }
+
+// CHECK-SPIRV: @A0 = external hidden thread_local addrspace(7) externally_initialized constant [2 x <4 x float>], !spirv.Decorations ![[#MD_0:]]
+// CHECK-SPIRV: @A2 = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations ![[#MD_2:]]
+
+// CHECK: define void @main0()
+// CHECK-DXIL: %A0 = call [2 x <4 x float>] @llvm.dx.load.input.a2v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison)
+// CHECK-DXIL: %[[#TMP0:]] = insertvalue %struct.S0 poison, [2 x <4 x float>] %A0, 0
+// CHECK-DXIL: %A2 = call <4 x float> @llvm.dx.load.input.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison)
+// CHECK-DXIL: %[[#TMP1:]] = insertvalue %struct.S0 %[[#TMP0]], <4 x float> %A2, 1
+
+// CHECK-SPIRV: %[[#A0:]] = load [2 x <4 x float>], ptr addrspace(7) @A0, align 16
+// CHECK-SPIRV: %[[#TMP0:]] = insertvalue %struct.S0 poison, [2 x <4 x float>] %[[#A0]], 0
+// CHECK-SPIRV: %[[#A01:]] = load <4 x float>, ptr addrspace(7) @A2, align 16
+// CHECK-SPIRV: %[[#TMP1:]] = insertvalue %struct.S0 %[[#TMP0]], <4 x float> %[[#A01]], 1
+
+// CHECK: %[[#ARG:]] = alloca %struct.S0, align 16
+// CHECK: store %struct.S0 %[[#TMP1]], ptr %[[#ARG]], align 16
+// CHECK-DXIL: call void @{{.*}}main0{{.*}}(ptr %[[#ARG]])
+// CHECK-SPIRV: call spir_func void @{{.*}}main0{{.*}}(ptr %[[#ARG]])
+[shader("pixel")]
+void main0(S0 p : A) {
+ float tmp = p.position[0] + p.position[1] + p.color;
+}
+
+// CHECK-SPIRV: ![[#MD_0]] = !{![[#MD_1:]]}
+// CHECK-SPIRV: ![[#MD_1]] = !{i32 30, i32 0}
+// CHECK-SPIRV: ![[#MD_2]] = !{![[#MD_3:]]}
+// CHECK-SPIRV: ![[#MD_3]] = !{i32 30, i32 2}
diff --git a/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl
new file mode 100644
index 0000000..d75f4e0
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV -DTARGET=spv
+// RUN: %clang_cc1 -triple dxil-px-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL -DTARGET=dx
+
+struct S0 {
+ float4 position[2];
+ float4 color;
+};
+
+// CHECK-SPIRV-DAG: @A0 = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations ![[#METADATA_0:]]
+
+[shader("pixel")]
+S0 main1(float4 input : A) : B {
+// CHECK: %[[#ARG:]] = alloca %struct.S0, align 16
+// CHECK-SPIRV: %[[#INPUT:]] = load <4 x float>, ptr addrspace(7) @A0, align 16
+// CHECK-DXIL: %A0 = call <4 x float> @llvm.dx.load.input.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison)
+// CHECK-DXIL: call void @{{.*}}main1{{.*}}(ptr %[[#ARG]], <4 x float> %A0)
+// CHECK-SPIRV: call spir_func void @{{.*}}main1{{.*}}(ptr %[[#ARG]], <4 x float> %[[#INPUT]])
+
+ // CHECK: %[[#ST:]] = load %struct.S0, ptr %[[#ARG]], align 16
+ // CHECK: %[[#TMP:]] = extractvalue %struct.S0 %[[#ST]], 0
+ // CHECK-SPIRV: store [2 x <4 x float>] %[[#TMP]], ptr addrspace(8) @B0, align 16
+ // CHECK-DXIL: call void @llvm.dx.store.output.a2v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison, [2 x <4 x float>] %[[#TMP]])
+ // CHECK: %[[#TMP:]] = extractvalue %struct.S0 %[[#ST]], 1
+ // CHECK-SPIRV: store <4 x float> %[[#TMP]], ptr addrspace(8) @B2, align 16
+ // CHECK-DXIL: call void @llvm.dx.store.output.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison, <4 x float> %[[#TMP]])
+
+ S0 output;
+ output.position[0] = input;
+ output.position[1] = input;
+ output.color = input;
+ return output;
+}
+
+// CHECK-SPIRV-DAG: ![[#METADATA_0]] = !{![[#METADATA_1:]]}
+// CHECK-SPIRV-DAG: ![[#METADATA_1]] = !{i32 30, i32 0}
+// | `- Location index
+// `-> Decoration "Location"
diff --git a/clang/test/CodeGenHLSL/semantics/semantic.explicit-location-output-struct.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.explicit-location-output-struct.hlsl
new file mode 100644
index 0000000..c5d8663
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/semantic.explicit-location-output-struct.hlsl
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL
+
+// CHECK-SPIRV: @SV_Position = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations ![[#MD_0:]]
+// CHECK-SPIRV: @SV_Target0 = external hidden thread_local addrspace(8) global <4 x float>, !spirv.Decorations ![[#MD_2:]]
+
+struct Output {
+ [[vk::location(2)]] float4 field : SV_Target;
+};
+
+// CHECK: define void @main() {{.*}} {
+Output main(float4 p : SV_Position) {
+ // CHECK: %[[#OUT:]] = alloca %struct.Output, align 16
+
+ // CHECK-SPIRV: %[[#IN:]] = load <4 x float>, ptr addrspace(7) @SV_Position, align 16
+ // CHECK-SPIRV: call spir_func void @_Z4mainDv4_f(ptr %[[#OUT]], <4 x float> %[[#IN]])
+
+ // CHECK-DXIL: call void @_Z4mainDv4_f(ptr %[[#OUT]], <4 x float> %SV_Position0)
+
+ // CHECK: %[[#TMP:]] = load %struct.Output, ptr %[[#OUT]], align 16
+ // CHECK: %[[#FIELD:]] = extractvalue %struct.Output %[[#TMP]], 0
+
+ // CHECK-SPIRV: store <4 x float> %[[#FIELD]], ptr addrspace(8) @SV_Target0, align 16
+ // CHECK-DXIL: call void @llvm.dx.store.output.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison, <4 x float> %[[#FIELD]])
+ Output o;
+ o.field = p;
+ return o;
+}
+
+// CHECK-SPIRV-DAG: ![[#MD_0]] = !{![[#MD_1:]]}
+// CHECK-SPIRV-DAG: ![[#MD_1]] = !{i32 11, i32 15}
+// | `-> BuiltIn 'FragCoord'
+// `-> SPIR-V decoration 'BuiltIn'
+// CHECK-SPIRV-DAG: ![[#MD_2]] = !{![[#MD_3:]]}
+// CHECK-SPIRV-DAG: ![[#MD_3]] = !{i32 30, i32 2}
+// | `-> Location index
+// `-> SPIR-V decoration 'Location'
diff --git a/clang/test/CodeGenHLSL/semantics/semantic.explicit-location.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.explicit-location.hlsl
new file mode 100644
index 0000000..41e28bf
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/semantic.explicit-location.hlsl
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-SPIRV
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-DXIL
+
+// CHECK-SPIRV: @SV_Target0 = external hidden thread_local addrspace(8) global <4 x float>, !spirv.Decorations ![[#MD_2:]]
+
+// CHECK: define void @main() {{.*}} {
+[[vk::location(2)]] float4 main(float4 p : SV_Position) : SV_Target {
+ // CHECK-SPIRV: %[[#R:]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> %[[#]])
+ // CHECK-SPIRV: store <4 x float> %[[#R]], ptr addrspace(8) @SV_Target0, align 16
+
+ // CHECK-DXIL: %[[#TMP:]] = call <4 x float> @_Z4mainDv4_f(<4 x float> %SV_Position0)
+ // CHECK-DXIL: call void @llvm.dx.store.output.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison, <4 x float> %[[#TMP]])
+ return p;
+}
+
+// CHECK-SPIRV-DAG: ![[#MD_2]] = !{![[#MD_3:]]}
+// CHECK-SPIRV-DAG: ![[#MD_3]] = !{i32 30, i32 2}
+// | `-> Location index
+// `-> SPIR-V decoration 'Location'
diff --git a/clang/test/CodeGenHLSL/semantics/semantic.explicit-mix-builtin.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.explicit-mix-builtin.hlsl
new file mode 100644
index 0000000..bc2ecd9
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/semantic.explicit-mix-builtin.hlsl
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
+
+// The following code is allowed because the `SV_Position` semantic is here
+// translated into a SPIR-V builtin. Meaning there is no implicit `Location`
+// assignment.
+
+struct S2 {
+ float4 a;
+ float4 b;
+};
+
+struct S1 {
+ float4 position : SV_Position;
+ [[vk::location(3)]] float4 color0 : COLOR0;
+};
+
+// CHECK-SPIRV: @SV_Position = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations ![[#MD_0:]]
+// CHECK-SPIRV: @COLOR0 = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations ![[#MD_2:]]
+// CHECK-SPIRV: @SV_Target0 = external hidden thread_local addrspace(8) global <4 x float>, !spirv.Decorations ![[#MD_4:]]
+
+[shader("pixel")]
+float4 main(S1 p) : SV_Target {
+ return p.position + p.color0;
+}
+// CHECK-SPIRV: %[[#SV_POS:]] = load <4 x float>, ptr addrspace(7) @SV_Position, align 16
+// CHECK: %[[#TMP1:]] = insertvalue %struct.S1 poison, <4 x float> %[[#SV_POS]], 0
+// CHECK-SPIRV: %[[#A0:]] = load <4 x float>, ptr addrspace(7) @COLOR0, align 16
+// CHECK: %[[#TMP2:]] = insertvalue %struct.S1 %[[#TMP1]], <4 x float> %[[#A0]], 1
+// CHECK: %[[#P:]] = alloca %struct.S1, align 16
+// CHECK: store %struct.S1 %[[#TMP2]], ptr %[[#P]], align 16
+// CHECK-SPIRV: %[[#R:]] = call spir_func <4 x float> @_Z4main2S1(ptr %[[#P]])
+// CHECK-SPIRV: store <4 x float> %[[#R]], ptr addrspace(8) @SV_Target0, align 16
+
+// CHECK-SPIRV: ![[#MD_0]] = !{![[#MD_1:]]}
+// CHECK-SPIRV: ![[#MD_1]] = !{i32 11, i32 15}
+// CHECK-SPIRV: ![[#MD_2]] = !{![[#MD_3:]]}
+// CHECK-SPIRV: ![[#MD_3]] = !{i32 30, i32 3}
+// CHECK-SPIRV: ![[#MD_4]] = !{![[#MD_5:]]}
+// CHECK-SPIRV: ![[#MD_5]] = !{i32 30, i32 0}
diff --git a/clang/test/CodeGenHLSL/semantics/semantic.explicit-mix-builtin.vs.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.explicit-mix-builtin.vs.hlsl
new file mode 100644
index 0000000..43dc30f
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/semantic.explicit-mix-builtin.vs.hlsl
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-vertex -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s
+
+// This is almost the same as semantic.explicit-mix-builtin.hlsl, except this
+// time we build a vertex shader. This means the SV_Position semantic output
+// is also a BuiltIn, This means we can mix implicit and explicit location
+// assignment.
+struct S1 {
+ float4 position : SV_Position;
+ [[vk::location(3)]] float4 color : A;
+};
+
+// CHECK: @SV_Position0 = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations ![[#MD_0:]]
+// CHECK: @SV_Position = external hidden thread_local addrspace(8) global <4 x float>, !spirv.Decorations ![[#MD_2:]]
+// CHECK: @A0 = external hidden thread_local addrspace(8) global <4 x float>, !spirv.Decorations ![[#MD_0]]
+
+[shader("vertex")]
+S1 main1(float4 position : SV_Position) {
+ S1 output;
+ output.position = position;
+ output.color = position;
+ return output;
+}
+
+// CHECK: ![[#MD_0]] = !{![[#MD_1:]]}
+// CHECK: ![[#MD_1]] = !{i32 30, i32 0}
+// | `-> Location index
+// `-> SPIR-V decoration 'Location'
+// CHECK: ![[#MD_2]] = !{![[#MD_3:]]}
+// CHECK: ![[#MD_3]] = !{i32 11, i32 0}
+// | `-> BuiltIn 'Position'
+// `-> SPIR-V decoration 'BuiltIn'
diff --git a/clang/test/CodeGenHLSL/semantics/semantic.explicit-mix.lib.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.explicit-mix.lib.hlsl
new file mode 100644
index 0000000..456c9bf
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/semantic.explicit-mix.lib.hlsl
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK
+
+// The followiong file contains both implicit and explicit vk::location, but
+// because each entrypoint has only one kind, this is allowed.
+
+[shader("vertex")]
+float4 vs_main(float4 p : SV_Position) : A {
+ return p;
+}
+
+[shader("pixel")]
+float4 ps_main([[vk::location(0)]] float4 p : A) : SV_Target {
+ return p;
+}
+
+// The following function is not marked as being a shader entrypoint, this
+// means the semantics and [[vk::location]] attributes are ignored.
+// Otherwise, the partial explicit location assignment would be illegal.
+float4 not_an_entry([[vk::location(0)]] float4 a : A, float4 b : B) : C {
+ return a + b;
+}
+
+// CHECK: @SV_Position0 = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations ![[#MD_0:]]
+// CHECK: @A0 = external hidden thread_local addrspace(8) global <4 x float>, !spirv.Decorations ![[#MD_0:]]
+// CHECK: @A0.1 = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations ![[#MD_0:]]
+// CHECK: @SV_Target0 = external hidden thread_local addrspace(8) global <4 x float>, !spirv.Decorations ![[#MD_2:]]
+
+
+// CHECK: define void @vs_main()
+// CHECK: %[[#]] = load <4 x float>, ptr addrspace(7) @SV_Position0, align 16
+// CHECK: store <4 x float> %[[#]], ptr addrspace(8) @A0, align 16
+
+// CHECK: define void @ps_main()
+// CHECK: %[[#]] = load <4 x float>, ptr addrspace(7) @A0.1, align 16
+// CHECK: store <4 x float> %[[#]], ptr addrspace(8) @SV_Target0, align 16
+
+// CHECK: ![[#MD_0]] = !{![[#MD_1:]]}
+// CHECK: ![[#MD_1]] = !{i32 30, i32 0}
+// CHECK: ![[#MD_2]] = !{![[#MD_3:]]}
+// CHECK: ![[#MD_3]] = !{i32 30, i32 1}
diff --git a/clang/test/CodeGenHLSL/semantics/semantic.struct.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.struct.hlsl
new file mode 100644
index 0000000..733cf3a
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/semantic.struct.hlsl
@@ -0,0 +1,77 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL -DTARGET=dx
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV -DTARGET=spv
+
+struct S0 {
+ uint Idx : SV_DispatchThreadID;
+};
+
+// CHECK: define void @main0()
+// CHECK-DXIL: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id(i32 0)
+// CHECK-SPIRV: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id.i32(i32 0)
+// CHECK: %[[#TMP:]] = insertvalue %struct.S0 poison, i32 %[[#ID:]], 0
+// CHECK: %[[#ARG:]] = alloca %struct.S0, align 8
+// CHECK: store %struct.S0 %[[#TMP]], ptr %[[#ARG]], align 4
+// CHECK-DXIL: call void @{{.*}}main0{{.*}}(ptr %[[#ARG]])
+// CHECK-SPIRV: call spir_func void @{{.*}}main0{{.*}}(ptr %[[#ARG]])
+[shader("compute")]
+[numthreads(8,8,1)]
+void main0(S0 p) {}
+
+struct S1 {
+ uint2 a : SV_DispatchThreadID;
+ uint2 b : SV_GroupThreadID;
+};
+
+// CHECK: define void @main1()
+// CHECK-DXIL: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id(i32 0)
+// CHECK-SPIRV: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id.i32(i32 0)
+// CHECK: %[[#AX_:]] = insertelement <2 x i32> poison, i32 %[[#ID]], i64 0
+// CHECK-DXIL: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id(i32 1)
+// CHECK-SPIRV: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id.i32(i32 1)
+// CHECK: %[[#AXY:]] = insertelement <2 x i32> %[[#AX_]], i32 %[[#ID]], i64 1
+// CHECK: %[[#S1A_:]] = insertvalue %struct.S1 poison, <2 x i32> %[[#AXY]], 0
+// CHECK-DXIL: %[[#ID_X:]] = call i32 @llvm.[[TARGET]].thread.id.in.group(i32 0)
+// CHECK-SPIRV: %[[#ID_X:]] = call i32 @llvm.[[TARGET]].thread.id.in.group.i32(i32 0)
+// CHECK: %[[#ID_X_:]] = insertelement <2 x i32> poison, i32 %[[#ID_X]], i64 0
+// CHECK-DXIL: %[[#ID_Y:]] = call i32 @llvm.[[TARGET]].thread.id.in.group(i32 1)
+// CHECK-SPIRV: %[[#ID_Y:]] = call i32 @llvm.[[TARGET]].thread.id.in.group.i32(i32 1)
+// CHECK: %[[#ID_XY:]] = insertelement <2 x i32> %[[#ID_X_]], i32 %[[#ID_Y]], i64 1
+// CHECK: %[[#S1AB:]] = insertvalue %struct.S1 %[[#S1A_]], <2 x i32> %[[#ID_XYZ:]], 1
+// CHECK: %[[#ARG:]] = alloca %struct.S1, align 8
+// CHECK: store %struct.S1 %[[#S1AB]], ptr %[[#ARG]], align 8
+// CHECK-DXIL: call void @{{.*}}main1{{.*}}(ptr %[[#ARG]])
+// CHECK-SPIRV: call spir_func void @{{.*}}main1{{.*}}(ptr %[[#ARG]])
+[shader("compute")]
+[numthreads(8,8,1)]
+void main1(S1 p) {}
+
+struct S2C {
+ uint2 b : SV_GroupThreadID;
+};
+
+struct S2 {
+ uint a : SV_DispatchThreadID;
+ S2C child;
+};
+
+// CHECK: define void @main2()
+// CHECK-DXIL: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id(i32 0)
+// CHECK-SPIRV: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id.i32(i32 0)
+// CHECK: %[[#S2A_:]] = insertvalue %struct.S2 poison, i32 %[[#ID:]], 0
+
+// CHECK-DXIL: %[[#ID_X:]] = call i32 @llvm.[[TARGET]].thread.id.in.group(i32 0)
+// CHECK-SPIRV: %[[#ID_X:]] = call i32 @llvm.[[TARGET]].thread.id.in.group.i32(i32 0)
+// CHECK: %[[#ID_X_:]] = insertelement <2 x i32> poison, i32 %[[#ID_X]], i64 0
+// CHECK-DXIL: %[[#ID_Y:]] = call i32 @llvm.[[TARGET]].thread.id.in.group(i32 1)
+// CHECK-SPIRV: %[[#ID_Y:]] = call i32 @llvm.[[TARGET]].thread.id.in.group.i32(i32 1)
+// CHECK: %[[#ID_XY:]] = insertelement <2 x i32> %[[#ID_X_]], i32 %[[#ID_Y]], i64 1
+// CHECK: %[[#S2C:]] = insertvalue %struct.S2C poison, <2 x i32> %[[#ID_XY:]], 0
+
+// CHECK: %[[#S2AB:]] = insertvalue %struct.S2 %[[#S2A_]], %struct.S2C %[[#S2V:]], 1
+// CHECK: %[[#ARG:]] = alloca %struct.S2, align 8
+// CHECK: store %struct.S2 %[[#S2AB]], ptr %[[#ARG]], align 1
+// CHECK-DXIL: call void @{{.*}}main2{{.*}}(ptr %[[#ARG]])
+// CHECK-SPIRV: call spir_func void @{{.*}}main2{{.*}}(ptr %[[#ARG]])
+[shader("compute")]
+[numthreads(8,8,1)]
+void main2(S2 p) {}
diff --git a/clang/test/CodeGenHLSL/semantics/semantic.struct.output.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.struct.output.hlsl
new file mode 100644
index 0000000..0f2444d
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/semantic.struct.output.hlsl
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-vertex -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK-DXIL,CHECK
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-vertex -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK
+
+
+struct Input {
+ // FIXME: change this once we have a valid system semantic as input for VS.
+ float Idx : B2;
+};
+
+struct Output {
+ float a : A4;
+ float b : A2;
+};
+
+// CHECK-SPIRV-DAG: @B2 = external hidden thread_local addrspace(7) externally_initialized constant float, !spirv.Decorations ![[#METADATA_0:]]
+// CHECK-SPIRV-DAG: @A4 = external hidden thread_local addrspace(8) global float, !spirv.Decorations ![[#METADATA_0:]]
+// CHECK-SPIRV-DAG: @A2 = external hidden thread_local addrspace(8) global float, !spirv.Decorations ![[#METADATA_2:]]
+
+// CHECK: %Idx = getelementptr inbounds nuw %struct.Input, ptr %input, i32 0, i32 0
+// CHECK: %[[#tmp:]] = load float, ptr %Idx, align 1
+// CHECK: %a = getelementptr inbounds nuw %struct.Output, ptr %agg.result, i32 0, i32 0
+// CHECK: store float %[[#tmp]], ptr %a, align 1
+
+// CHECK: %Idx1 = getelementptr inbounds nuw %struct.Input, ptr %input, i32 0, i32 0
+// CHECK: %[[#tmp:]] = load float, ptr %Idx1, align 1
+// CHECK: %b = getelementptr inbounds nuw %struct.Output, ptr %agg.result, i32 0, i32 1
+// CHECK: store float %[[#tmp]], ptr %b, align 1
+
+Output main(Input input) {
+ Output o;
+ o.a = input.Idx;
+ o.b = input.Idx;
+ return o;
+}
+
+// Code generated in the entrypoint wrapper:
+
+// CHECK: %[[#OUTPUT:]] = alloca %struct.Output, align 8
+
+// CHECK-SPIRV: call spir_func void @_Z4main5Input(ptr %[[#OUTPUT]], ptr %[[#]])
+// CHECK-DXIL: call void @_Z4main5Input(ptr %[[#OUTPUT]], ptr %[[#]])
+
+// CHECK: %[[#TMP:]] = load %struct.Output, ptr %[[#OUTPUT]], align 4
+// CHECK: %[[#VAL:]] = extractvalue %struct.Output %[[#TMP]], 0
+// CHECK-SPIRV: store float %[[#VAL]], ptr addrspace(8) @A4, align 4
+// CHECK-DXIL: call void @llvm.dx.store.output.f32(i32 4, i32 0, i32 0, i8 0, i32 poison, float %[[#VAL]])
+// CHECK: %[[#VAL:]] = extractvalue %struct.Output %[[#TMP]], 1
+// CHECK-SPIRV: store float %[[#VAL]], ptr addrspace(8) @A2, align 4
+// CHECK-DXIL: call void @llvm.dx.store.output.f32(i32 4, i32 0, i32 0, i8 0, i32 poison, float %[[#VAL]])
+
+// CHECK-SPIRV-DAG: ![[#METADATA_0]] = !{![[#METADATA_1:]]}
+// CHECK-SPIRV-DAG: ![[#METADATA_2]] = !{![[#METADATA_3:]]}
+// CHECK-SPIRV-DAG: ![[#METADATA_1]] = !{i32 30, i32 0}
+// CHECK-SPIRV-DAG: ![[#METADATA_3]] = !{i32 30, i32 1}
+// | `- Location index
+// `-> Decoration "Location"
diff --git a/clang/test/CodeGenHLSL/sret_output.hlsl b/clang/test/CodeGenHLSL/sret_output.hlsl
index eefc9da..e1aa097 100644
--- a/clang/test/CodeGenHLSL/sret_output.hlsl
+++ b/clang/test/CodeGenHLSL/sret_output.hlsl
@@ -1,21 +1,33 @@
// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -triple dxil-pc-shadermodel6.3-library %s \
-// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s
+// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefixes=CHECK-DX,CHECK
+// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -triple spirv-pc-vulkan-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefixes=CHECK-VK,CHECK
-// FIXME: add semantic to a.
-// See https://github.com/llvm/llvm-project/issues/57874
struct S {
- float a;
+ float a : A4;
};
+// CHECK-VK: @A4 = external hidden thread_local addrspace(8) global float, !spirv.Decorations ![[#ATTR0:]]
// Make sure sret parameter is generated.
-// CHECK:define internal void @_Z7ps_mainv(ptr dead_on_unwind noalias writable sret(%struct.S) align 1 %agg.result)
-// FIXME: change it to real value instead of poison value once semantic is add to a.
-// Make sure the function with sret is called.
-// CHECK:call void @_Z7ps_mainv(ptr poison)
-[shader("pixel")]
-S ps_main() {
+// CHECK-DX: define internal void @_Z7vs_mainv(ptr dead_on_unwind noalias writable sret(%struct.S) align 1 %agg.result)
+// CHECK-VK: define internal spir_func void @_Z7vs_mainv(ptr dead_on_unwind noalias writable sret(%struct.S) align 1 %agg.result)
+
+[shader("vertex")]
+S vs_main() {
S s;
s.a = 0;
return s;
};
+
+// CHECK: %[[#alloca:]] = alloca %struct.S, align 8
+// CHECK-DX: call void @_Z7vs_mainv(ptr %[[#alloca]])
+// CHECK-VK: call spir_func void @_Z7vs_mainv(ptr %[[#alloca]])
+// CHECK: %[[#a:]] = load %struct.S, ptr %[[#alloca]], align 4
+// CHECK: %[[#b:]] = extractvalue %struct.S %[[#a]], 0
+// CHECK-DX: call void @llvm.dx.store.output.f32(i32 4, i32 0, i32 0, i8 0, i32 poison, float %[[#b]])
+// CHECK-VK: store float %3, ptr addrspace(8) @A4, align 4
+// CHECK: ret void
+
+// CHECK-VK: ![[#ATTR0]] = !{![[#ATTR1:]]}
+// CHECK-VK: ![[#ATTR1]] = !{i32 30, i32 0}