1 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
2 // RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
3 // RUN: -o - | FileCheck %s
5 // CHECK-LABEL: ToTwoInts
6 // CHECK: [[splat:%.*]] = insertelement <1 x i32> poison, i32 {{.*}}, i64 0
7 // CHECK: [[vec2:%.*]] = shufflevector <1 x i32> [[splat]], <1 x i32> poison, <2 x i32> zeroinitializer
8 // CHECK: ret <2 x i32> [[vec2]]
13 // CHECK-LABEL: ToFourFloats
14 // [[splat:%.*]] = insertelement <1 x float> poison, float {{.*}}, i64 0
15 // [[vec4:%.*]] = shufflevector <1 x float> [[splat]], <1 x float> poison, <4 x i32> zeroinitializer
16 // ret <4 x float> [[vec4]]
17 float4 ToFourFloats(float V){
21 // CHECK-LABEL: FillOne
22 // CHECK: [[vec1Ptr:%.*]] = alloca <1 x i32>, align 4
23 // CHECK: store <1 x i32> splat (i32 1), ptr [[vec1Ptr]], align 4
24 // CHECK: [[vec1:%.*]] = load <1 x i32>, ptr [[vec1Ptr]], align 4
25 // CHECK: [[vec2:%.*]] = shufflevector <1 x i32> [[vec1]], <1 x i32> poison, <2 x i32> zeroinitializer
26 // CHECK: ret <2 x i32> [[vec2]]
31 // CHECK-LABEL: FillOneUnsigned
32 // CHECK: [[vec1Ptr:%.*]] = alloca <1 x i32>, align 4
33 // CHECK: store <1 x i32> splat (i32 1), ptr [[vec1Ptr]], align 4
34 // CHECK: [[vec1:%.*]] = load <1 x i32>, ptr [[vec1Ptr]], align 4
35 // CHECK: [[vec3:%.*]] = shufflevector <1 x i32> [[vec1]], <1 x i32> poison, <3 x i32> zeroinitializer
36 // CHECK: ret <3 x i32> [[vec3]]
37 uint3 FillOneUnsigned(){
41 // CHECK-LABEL: FillOneUnsignedLong
42 // CHECK: [[vec1Ptr:%.*]] = alloca <1 x i64>, align 8
43 // CHECK: store <1 x i64> splat (i64 1), ptr [[vec1Ptr]], align 8
44 // CHECK: [[vec1:%.*]] = load <1 x i64>, ptr [[vec1Ptr]], align 8
45 // CHECK: [[vec4:%.*]] = shufflevector <1 x i64> [[vec1]], <1 x i64> poison, <4 x i32> zeroinitializer
46 // CHECK: ret <4 x i64> [[vec4]]
47 vector<uint64_t,4> FillOneUnsignedLong(){
51 // CHECK-LABEL: FillTwoPointFive
52 // CHECK: [[vec1Ptr:%.*]] = alloca <1 x double>, align 8
53 // CHECK: store <1 x double> splat (double 2.500000e+00), ptr [[vec1Ptr]], align 8
54 // CHECK: [[vec1:%.*]] = load <1 x double>, ptr [[vec1Ptr]], align 8
55 // CHECK: [[vec2:%.*]] = shufflevector <1 x double> [[vec1]], <1 x double> poison, <2 x i32> zeroinitializer
56 // CHECK: ret <2 x double> [[vec2]]
57 double2 FillTwoPointFive(){
61 // CHECK-LABEL: FillOneHalf
62 // CHECK: [[vec1Ptr:%.*]] = alloca <1 x double>, align 8
63 // CHECK: store <1 x double> splat (double 5.000000e-01), ptr [[vec1Ptr]], align 8
64 // CHECK: [[vec1:%.*]] = load <1 x double>, ptr [[vec1Ptr]], align 8
65 // CHECK: [[vec3:%.*]] = shufflevector <1 x double> [[vec1]], <1 x double> poison, <3 x i32> zeroinitializer
66 // CHECK: ret <3 x double> [[vec3]]
67 double3 FillOneHalf(){
71 // CHECK-LABEL: FillTwoPointFiveFloat
72 // CHECK: [[vec1Ptr:%.*]] = alloca <1 x float>, align 4
73 // CHECK: store <1 x float> splat (float 2.500000e+00), ptr [[vec1Ptr]], align 4
74 // CHECK: [[vec1:%.*]] = load <1 x float>, ptr [[vec1Ptr]], align 4
75 // CHECK: [[vec4:%.*]] = shufflevector <1 x float> [[vec1]], <1 x float> poison, <4 x i32> zeroinitializer
76 // CHECK: ret <4 x float> [[vec4]]
77 float4 FillTwoPointFiveFloat(){
81 // The initial codegen for this case is correct but a bit odd. The IR optimizer
82 // cleans this up very nicely.
84 // CHECK-LABEL: FillOneHalfFloat
85 // CHECK: [[vec1Ptr:%.*]] = alloca <1 x float>, align 4
86 // CHECK: store <1 x float> splat (float 5.000000e-01), ptr [[vec1Ptr]], align 4
87 // CHECK: [[vec1:%.*]] = load <1 x float>, ptr [[vec1Ptr]], align 4
88 // CHECK: [[el0:%.*]] = extractelement <1 x float> [[vec1]], i32 0
89 // CHECK: [[vec1Splat:%.*]] = insertelement <1 x float> poison, float [[el0]], i64 0
90 // CHECK: [[vec1Ret:%.*]] = shufflevector <1 x float> [[vec1Splat]], <1 x float> poison, <1 x i32> zeroinitializer
91 // CHECK: ret <1 x float> [[vec1Ret]]
92 vector<float, 1> FillOneHalfFloat(){
96 // The initial codegen for this case is correct but a bit odd. The IR optimizer
97 // cleans this up very nicely.
99 // CHECK-LABEL: HowManyFloats
100 // CHECK: [[VAddr:%.*]] = alloca float, align 4
101 // CHECK: [[vec2Ptr:%.*]] = alloca <2 x float>, align 8
102 // CHECK: [[VVal:%.*]] = load float, ptr [[VAddr]], align 4
103 // CHECK: [[splat:%.*]] = insertelement <1 x float> poison, float [[VVal]], i64 0
104 // CHECK: [[vec2:%.*]] = shufflevector <1 x float> [[splat]], <1 x float> poison, <2 x i32> zeroinitializer
105 // CHECK: store <2 x float> [[vec2]], ptr [[vec2Ptr]], align 8
106 // CHECK: [[vec2:%.*]] = load <2 x float>, ptr [[vec2Ptr]], align 8
107 // CHECK: [[vec2Res:%.*]] = shufflevector <2 x float> [[vec2]], <2 x float> poison, <2 x i32> zeroinitializer
108 // CHECK: ret <2 x float> [[vec2Res]]
109 float2 HowManyFloats(float V) {
113 // This codegen is gnarly because `1.l` is a double, so this creates double
114 // vectors that need to be truncated down to floats. The optimizer cleans this
117 // CHECK-LABEL: AllRighty
118 // CHECK: [[Tmp:%.*]] = alloca <1 x double>, align 8
119 // CHECK: store <1 x double> splat (double 1.000000e+00), ptr [[Tmp]], align 8
120 // CHECK: [[vec1:%.*]] = load <1 x double>, ptr [[Tmp]], align 8
121 // CHECK: [[vec3:%.*]] = shufflevector <1 x double> [[vec1]], <1 x double> poison, <3 x i32> zeroinitializer
122 // CHECK: [[vec3f:%.*]] = fptrunc reassoc nnan ninf nsz arcp afn <3 x double> [[vec3]] to <3 x float>
123 // CHECK: ret <3 x float> [[vec3f]]
129 // CHECK-LABEL: AllRighty2
130 // CHECK: [[vec1Ptr:%.*]] = alloca <1 x float>, align 4
131 // CHECK: store <1 x float> splat (float 1.000000e+00), ptr [[vec1Ptr]], align 4
132 // CHECK: [[vec1:%.*]] = load <1 x float>, ptr [[vec1Ptr]], align 4
133 // CHECK: [[vec3:%.*]] = shufflevector <1 x float> [[vec1]], <1 x float> poison, <3 x i32>
134 // CHECK: ret <3 x float> [[vec3]]
136 float3 AllRighty2() {
140 // CHECK-LABEL: AssignInt
141 // CHECK: [[VAddr:%.*]] = alloca i32, align 4
142 // CHECK: [[XAddr:%.*]] = alloca i32, align 4
144 // Load V into a vector, then extract V out and store it to X.
145 // CHECK: [[V:%.*]] = load i32, ptr [[VAddr]], align 4
146 // CHECK: [[Splat:%.*]] = insertelement <1 x i32> poison, i32 [[V]], i64 0
147 // CHECK: [[VExtVal:%.*]] = extractelement <1 x i32> [[Splat]], i32 0
148 // CHECK: store i32 [[VExtVal]], ptr [[XAddr]], align 4
150 // Load V into two separate vectors, then add the extracted X components.
151 // CHECK: [[V:%.*]] = load i32, ptr [[VAddr]], align 4
152 // CHECK: [[Splat:%.*]] = insertelement <1 x i32> poison, i32 [[V]], i64 0
153 // CHECK: [[LHS:%.*]] = extractelement <1 x i32> [[Splat]], i32 0
155 // CHECK: [[V:%.*]] = load i32, ptr [[VAddr]], align 4
156 // CHECK: [[Splat:%.*]] = insertelement <1 x i32> poison, i32 [[V]], i64 0
157 // CHECK: [[RHS:%.*]] = extractelement <1 x i32> [[Splat]], i32 0
159 // CHECK: [[Sum:%.*]] = add nsw i32 [[LHS]], [[RHS]]
160 // CHECK: store i32 [[Sum]], ptr [[XAddr]], align 4
161 // CHECK: [[X:%.*]] = load i32, ptr [[XAddr]], align 4
162 // CHECK: ret i32 [[X]]
164 int AssignInt(int V){