[flang][cuda] Add c_devloc as intrinsic and inline it during lowering (#120648)
[llvm-project.git] / clang / test / SemaHLSL / Language / UsualArithmeticConversions.hlsl
blobd9f20a4cb79ecbdfd864876a6571f7c583e35d34
1 // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -fnative-half-type %s -DERRORS -Wconversion -Wdouble-promotion -verify
2 // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl2018 -finclude-default-header -fnative-half-type %s -DERRORS -Wconversion -Wdouble-promotion -verify
3 // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -fnative-half-type %s -ast-dump | FileCheck %s
5 #if __HLSL_VERSION <= 2021
6 // expected-warning@*{{support for HLSL language version hlsl2018 is incomplete, recommend using hlsl202x instead}}
7 #endif
9 //----------------------------------------------------------------------------//
10 // Case 1: float4 * int4 and inverse.
12 // In both cases here the int is converted to a float and the computation
13 // produces a float value.
14 //----------------------------------------------------------------------------//
16 // CHECK-LABEL: FunctionDecl {{.*}} used f4f4i4 'float4 (float4, int4)'
17 // CHECK: BinaryOperator {{.*}} 'float4':'vector<float, 4>' '*'
18 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' <LValueToRValue>
19 // CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector<float, 4>' lvalue ParmVar {{.*}} 'A' 'float4':'vector<float, 4>'
20 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' <IntegralToFloating>
21 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int4':'vector<int, 4>' <LValueToRValue>
22 // CHECK-NEXT: DeclRefExpr {{.*}} 'int4':'vector<int, 4>' lvalue ParmVar {{.*}} 'B' 'int4':'vector<int, 4>'
23 export float4 f4f4i4(float4 A, int4 B) {
24   return A * B; // expected-warning{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'float4' (aka 'vector<float, 4>') may lose precision}}
27 // CHECK-LABEL: FunctionDecl {{.*}} used f4i4f4 'float4 (float4, int4)'
28 // CHECK: BinaryOperator {{.*}} 'float4':'vector<float, 4>' '*'
29 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' <IntegralToFloating>
30 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int4':'vector<int, 4>' <LValueToRValue>
31 // CHECK-NEXT: DeclRefExpr {{.*}} 'int4':'vector<int, 4>' lvalue ParmVar {{.*}} 'B' 'int4':'vector<int, 4>'
32 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' <LValueToRValue>
33 // CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector<float, 4>' lvalue ParmVar {{.*}} 'A' 'float4':'vector<float, 4>'
34 export float4 f4i4f4(float4 A, int4 B) {
35   return B * A; // expected-warning{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'float4' (aka 'vector<float, 4>') may lose precision}}
38 //----------------------------------------------------------------------------//
39 // Case 2: float4 * int2 and inverse.
41 // In both cases the float vector is trunctated to a float2 and the integer
42 // vector is converted to a float2.
43 //----------------------------------------------------------------------------//
45 // CHECK-LABEL: FunctionDecl {{.*}} used f2f4i2 'float2 (float4, int2)'
46 // CHECK: BinaryOperator {{.*}} 'vector<float, 2>' '*'
47 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 2>' <HLSLVectorTruncation>
48 // CHECK-NEXT: ImplicitCastExpr {{.*}}'float4':'vector<float, 4>' <LValueToRValue>
49 // CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector<float, 4>' lvalue ParmVar {{.*}} 'A' 'float4':'vector<float, 4>'
50 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 2>' <IntegralToFloating>
51 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int2':'vector<int, 2>' <LValueToRValue>
52 // CHECK-NEXT: DeclRefExpr {{.*}} 'int2':'vector<int, 2>' lvalue ParmVar {{.*}} 'B' 'int2':'vector<int, 2>'
53 export float2 f2f4i2(float4 A, int2 B) {
54   // expected-warning@#f2f4i2 {{implicit conversion from 'int2' (aka 'vector<int, 2>') to 'vector<float, 2>' (vector of 2 'float' values) may lose precision}}
55   // expected-warning@#f2f4i2 {{implicit conversion truncates vector: 'float4' (aka 'vector<float, 4>') to 'vector<float, 2>' (vector of 2 'float' values)}}
56   return A * B; // #f2f4i2
59 // CHECK-LABEL: FunctionDecl {{.*}} used f2i2f4 'float2 (float4, int2)'
60 // CHECK: BinaryOperator {{.*}} 'vector<float, 2>' '*'
61 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 2>' <IntegralToFloating>
62 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int2':'vector<int, 2>' <LValueToRValue>
63 // CHECK-NEXT: DeclRefExpr {{.*}} 'int2':'vector<int, 2>' lvalue ParmVar {{.*}} 'B' 'int2':'vector<int, 2>'
64 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 2>' <HLSLVectorTruncation>
65 // CHECK-NEXT: ImplicitCastExpr {{.*}}'float4':'vector<float, 4>' <LValueToRValue>
66 // CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector<float, 4>' lvalue ParmVar {{.*}} 'A' 'float4':'vector<float, 4>'
67 export float2 f2i2f4(float4 A, int2 B) {
68   // expected-warning@#f2i2f4 {{implicit conversion from 'int2' (aka 'vector<int, 2>') to 'vector<float, 2>' (vector of 2 'float' values) may lose precision}}
69   // expected-warning@#f2i2f4 {{implicit conversion truncates vector: 'float4' (aka 'vector<float, 4>') to 'vector<float, 2>' (vector of 2 'float' values)}}
70   return B * A; // #f2i2f4
73 //----------------------------------------------------------------------------//
74 // Case 3: Integers of mismatched sign, equivalent size, but the unsigned type
75 // has lower conversion rank.
77 // This is the odd-ball case for HLSL that isn't really in spec, but we should
78 // handle gracefully. The lower-ranked unsigned type is converted to the
79 // equivalent unsigned type of higher rank, and the signed type is also
80 // converted to that unsigned type (meaning `unsigned long` becomes `unsinged
81 // long long`, and `long long` becomes `unsigned long long`).
82 //----------------------------------------------------------------------------//
84 // CHECK-LABEL: FunctionDecl {{.*}} used wierdo 'int4 (vector<unsigned long, 4>, vector<long long, 4>)'
85 // CHECK: BinaryOperator {{.*}} 'vector<unsigned long long, 4>' '*'
86 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<unsigned long long, 4>' <IntegralCast>
87 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<unsigned long, 4>' <LValueToRValue>
88 // CHECK-NEXT: DeclRefExpr{{.*}} 'vector<unsigned long, 4>' lvalue ParmVar {{.*}} 'A' 'vector<unsigned long, 4>'
89 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<unsigned long long, 4>' <IntegralCast>
90 // CHECK-NEXT: ImplicitCastExpr{{.*}}> 'vector<long long, 4>' <LValueToRValue>
91 // CHECK-NEXT: DeclRefExpr {{.*}}'vector<long long, 4>' lvalue ParmVar {{.*}} 'B' 'vector<long long, 4>'
92 export int4 wierdo(vector<unsigned long, 4> A, vector<long long, 4> B) {
93   // expected-warning@#wierdo {{implicit conversion loses integer precision: 'vector<unsigned long long, 4>' (vector of 4 'unsigned long long' values) to 'vector<int, 4>' (vector of 4 'int' values)}}
94   // expected-warning@#wierdo {{implicit conversion changes signedness: 'vector<long long, 4>' (vector of 4 'long long' values) to 'vector<unsigned long long, 4>' (vector of 4 'unsigned long long' values)}}
95   return A * B; // #wierdo
98 //----------------------------------------------------------------------------//
99 // Case 4: Compound assignment of float4 with an int4.
101 // In compound assignment the RHS is converted to match the LHS.
102 //----------------------------------------------------------------------------//
104 // CHECK-LABEL: FunctionDecl {{.*}} used f4f4i4compound 'float4 (float4, int4)'
105 // CHECK: CompoundAssignOperator {{.*}} 'float4':'vector<float, 4>' lvalue '+=' ComputeLHSTy='float4':'vector<float, 4>' ComputeResultTy='float4':'vector<float, 4>'
106 // CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector<float, 4>' lvalue ParmVar {{.*}} 'A' 'float4':'vector<float, 4>'
107 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' <IntegralToFloating>
108 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int4':'vector<int, 4>' <LValueToRValue>
109 // CHECK-NEXT: DeclRefExpr {{.*}} 'int4':'vector<int, 4>' lvalue ParmVar {{.*}} 'B' 'int4':'vector<int, 4>'
110 export float4 f4f4i4compound(float4 A, int4 B) {
111   A += B; // expected-warning{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'float4' (aka 'vector<float, 4>') may lose precision}}
112   return A;
116 //----------------------------------------------------------------------------//
117 // Case 5: Compound assignment of float2 with an int4.
119 // In compound assignment the RHS is converted to match the LHS.
120 //----------------------------------------------------------------------------//
122 // CHECK-LABEL: FunctionDecl {{.*}} used f4f2i4compound 'float4 (float2, int4)'
123 // CHECK: CompoundAssignOperator {{.*}} 'float2':'vector<float, 2>' lvalue '+=' ComputeLHSTy='float2':'vector<float, 2>' ComputeResultTy='float2':'vector<float, 2>'
124 // CHECK-NEXT: DeclRefExpr {{.*}} 'float2':'vector<float, 2>' lvalue ParmVar {{.*}} 'A' 'float2':'vector<float, 2>'
125 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float2':'vector<float, 2>' <IntegralToFloating>
126 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 2>' <HLSLVectorTruncation>
127 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int4':'vector<int, 4>' <LValueToRValue>
128 // CHECK-NEXT: DeclRefExpr {{.*}} 'int4':'vector<int, 4>' lvalue ParmVar {{.*}} 'B' 'int4':'vector<int, 4>'
129 export float4 f4f2i4compound(float2 A, int4 B) {
130   // expected-warning@#f4f2i4compound{{implicit conversion truncates vector: 'int4' (aka 'vector<int, 4>') to 'float2' (aka 'vector<float, 2>')}}
131   // expected-warning@#f4f2i4compound{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'float2' (aka 'vector<float, 2>') may lose precision}}
132   A += B; // #f4f2i4compound
133   return A.xyxy;
136 //----------------------------------------------------------------------------//
137 // Case 6: float2 * int4
139 // The int4 vector is trunctated to int2 then converted to float2.
140 //----------------------------------------------------------------------------//
142 // CHECK-LABEL: FunctionDecl {{.*}} used f4f2i4 'float2 (float2, int4)'
143 // CHECK: BinaryOperator {{.*}} 'float2':'vector<float, 2>' '*'
144 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float2':'vector<float, 2>' <LValueToRValue>
145 // CHECK-NEXT: DeclRefExpr {{.*}} 'float2':'vector<float, 2>' lvalue ParmVar {{.*}} 'A' 'float2':'vector<float, 2>'
146 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float2':'vector<float, 2>' <IntegralToFloating>
147 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 2>' <HLSLVectorTruncation>
148 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int4':'vector<int, 4>' <LValueToRValue>
149 // CHECK-NEXT: DeclRefExpr {{.*}} 'int4':'vector<int, 4>' lvalue ParmVar {{.*}} 'B' 'int4':'vector<int, 4>'
150 export float2 f4f2i4(float2 A, int4 B) {
151   // expected-warning@#f4f2i4{{implicit conversion truncates vector: 'int4' (aka 'vector<int, 4>') to 'float2' (aka 'vector<float, 2>')}}
152   // expected-warning@#f4f2i4{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'float2' (aka 'vector<float, 2>') may lose precision}}
153   return A * B; // #f4f2i4
156 //----------------------------------------------------------------------------//
157 // Case 7: Compound assignment of half4 with float4, and inverse.
159 // In compound assignment the RHS is converted to match the LHS.
160 //----------------------------------------------------------------------------//
162 // CHECK-LABEL: FunctionDecl {{.*}} used f4h4f4compound 'float4 (half4, float4)'
163 // CHECK: CompoundAssignOperator {{.*}} 'half4':'vector<half, 4>' lvalue '+=' ComputeLHSTy='half4':'vector<half, 4>' ComputeResultTy='half4':'vector<half, 4>'
164 // CHECK-NEXT: DeclRefExpr {{.*}} 'half4':'vector<half, 4>' lvalue ParmVar {{.*}} 'A' 'half4':'vector<half, 4>'
165 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'half4':'vector<half, 4>' <FloatingCast>
166 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' <LValueToRValue>
167 // CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector<float, 4>' lvalue ParmVar {{.*}} 'B' 'float4':'vector<float, 4>'
168 export float4 f4h4f4compound(half4 A, float4 B) {
169   A += B; // expected-warning{{implicit conversion loses floating-point precision: 'float4' (aka 'vector<float, 4>') to 'half4' (aka 'vector<half, 4>')}}
170   return B;
173 // CHECK-LABEL: FunctionDecl {{.*}} used f4f4h4compound 'float4 (float4, half4)'
174 // CHECK: CompoundAssignOperator {{.*}} 'float4':'vector<float, 4>' lvalue '+=' ComputeLHSTy='float4':'vector<float, 4>' ComputeResultTy='float4':'vector<float, 4>'
175 // CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector<float, 4>' lvalue ParmVar {{.*}} 'A' 'float4':'vector<float, 4>'
176 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' <FloatingCast>
177 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'half4':'vector<half, 4>' <LValueToRValue>
178 // CHECK-NEXT: DeclRefExpr {{.*}} 'half4':'vector<half, 4>' lvalue ParmVar {{.*}} 'B' 'half4':'vector<half, 4>'
179 export float4 f4f4h4compound(float4 A, half4 B) {
180   A += B; // expected-warning{{implicit conversion increases floating-point precision: 'half4' (aka 'vector<half, 4>') to 'float4' (aka 'vector<float, 4>')}}
181   return A;
184 //----------------------------------------------------------------------------//
185 // Case 8: int64_t4 * uint4
187 // The unsigned argument is promoted to the higher ranked signed type since it
188 // can express all values of the unsgined argument.
189 //----------------------------------------------------------------------------//
191 // CHECK-LABEL: FunctionDecl {{.*}} used l4l4i4 'int64_t4 (int64_t4, uint4)'
192 // CHECK: BinaryOperator {{.*}} 'int64_t4':'vector<int64_t, 4>' '*'
193 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int64_t4':'vector<int64_t, 4>' <LValueToRValue>
194 // CHECK-NEXT: DeclRefExpr {{.*}} 'int64_t4':'vector<int64_t, 4>' lvalue ParmVar {{.*}} 'A' 'int64_t4':'vector<int64_t, 4>'
195 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int64_t4':'vector<int64_t, 4>' <IntegralCast>
196 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'uint4':'vector<uint, 4>' <LValueToRValue>
197 // CHECK-NEXT: DeclRefExpr {{.*}} 'uint4':'vector<uint, 4>' lvalue ParmVar {{.*}} 'B' 'uint4':'vector<uint, 4>'
198 export int64_t4 l4l4i4(int64_t4 A, uint4 B) {
199   return A * B;
202 //----------------------------------------------------------------------------//
203 // Case 9: Compound assignment of int4 from int64_t4
205 // In compound assignment the RHS is converted to match the LHS.
206 //----------------------------------------------------------------------------//
208 // CHECK-LABEL: FunctionDecl {{.*}} used i4i4l4compound 'int4 (int4, int64_t4)'
209 // CHECK: CompoundAssignOperator {{.*}} 'int4':'vector<int, 4>' lvalue '+=' ComputeLHSTy='int4':'vector<int, 4>' ComputeResultTy='int4':'vector<int, 4>'
210 // CHECK-NEXT: DeclRefExpr {{.*}} 'int4':'vector<int, 4>' lvalue ParmVar {{.*}} 'A' 'int4':'vector<int, 4>'
211 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int4':'vector<int, 4>' <IntegralCast>
212 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int64_t4':'vector<int64_t, 4>' <LValueToRValue>
213 // CHECK-NEXT: DeclRefExpr {{.*}} 'int64_t4':'vector<int64_t, 4>' lvalue ParmVar {{.*}} 'B' 'int64_t4':'vector<int64_t, 4>'
214 export int4 i4i4l4compound(int4 A, int64_t4 B) {
215   A += B; // expected-warning{{implicit conversion loses integer precision: 'int64_t4' (aka 'vector<int64_t, 4>') to 'int4' (aka 'vector<int, 4>')}}
216   return A;
219 //----------------------------------------------------------------------------//
220 // Case 10: Compound assignment of vector<unsigned long, 4> with argument of
221 // vector<long long, 4>
223 // In compound assignment the RHS is converted to match the LHS. This one is
224 // also the weird case because it is out of spec, but we should handle it
225 // gracefully.
226 //----------------------------------------------------------------------------//
228 // CHECK-LABEL: FunctionDecl {{.*}} used wierdocompound 'vector<unsigned long, 4> (vector<unsigned long, 4>, vector<long long, 4>)'
229 // CHECK: CompoundAssignOperator {{.*}} 'vector<unsigned long, 4>' lvalue '+=' ComputeLHSTy='vector<unsigned long, 4>' ComputeResultTy='vector<unsigned long, 4>'
230 // CHECK-NEXT: DeclRefExpr {{.*}} 'vector<unsigned long, 4>' lvalue ParmVar {{.*}} 'A' 'vector<unsigned long, 4>'
231 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<unsigned long, 4>' <IntegralCast>
232 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<long long, 4>' <LValueToRValue>
233 // CHECK-NEXT: DeclRefExpr {{.*}} 'vector<long long, 4>' lvalue ParmVar {{.*}} 'B' 'vector<long long, 4>'
234 export vector<unsigned long, 4> wierdocompound(vector<unsigned long, 4> A, vector<long long, 4> B) {
235   // expected-warning@#wierdocompound{{implicit conversion changes signedness: 'vector<long long, 4>' (vector of 4 'long long' values) to 'vector<unsigned long, 4>' (vector of 4 'unsigned long' values)}}
236   A += B; // #wierdocompound
237   return A;
240 //----------------------------------------------------------------------------//
241 // Case 11: Compound assignment of scalar with vector argument.
243 // Because the LHS of a compound assignment cannot change type, the RHS must be
244 // implicitly convertable to the LHS type.
245 //----------------------------------------------------------------------------//
247 // CHECK-LABEL: FunctionDecl {{.*}} used ffi2compound 'float (float, int2)'
248 // CHECK: CompoundAssignOperator {{.*}} 'float' lvalue '+=' ComputeLHSTy='float' ComputeResultTy='float'
249 // CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'A' 'float'
250 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating>
251 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <HLSLVectorTruncation>
252 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int2':'vector<int, 2>' <LValueToRValue>
253 // CHECK-NEXT: DeclRefExpr {{.*}} 'int2':'vector<int, 2>' lvalue ParmVar {{.*}} 'B' 'int2':'vector<int, 2>'
254 export float ffi2compound(float A, int2 B) {
255   A += B; // expected-warning {{implicit conversion turns vector to scalar: 'int2' (aka 'vector<int, 2>') to 'float'}}
256   return A;
259 // CHECK-LABEL: FunctionDecl {{.*}} used iif2compound 'int (int, float2)'
260 // CHECK: CompoundAssignOperator {{.*}} 'int' lvalue '+=' ComputeLHSTy='int' ComputeResultTy='int'
261 // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'A' 'int'
262 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <FloatingToIntegral>
263 // CHECK-NEXT: mplicitCastExpr {{.*}} 'float' <HLSLVectorTruncation>
264 // CHECK-NEXT: ImplicitCastExpr{{.*}} 'float2':'vector<float, 2>' <LValueToRValue>
265 // CHECK-NEXT: DeclRefExpr {{.*}} 'float2':'vector<float, 2>' lvalue ParmVar {{.*}} 'B' 'float2':'vector<float, 2>'
266 export int iif2compound(int A, float2 B) {
267   A += B; // expected-warning{{implicit conversion turns vector to scalar: 'float2' (aka 'vector<float, 2>') to 'int'}}
268   return A;
272 //----------------------------------------------------------------------------//
273 // Case 12: Compound assignment of vector of larger size than the argument.
275 // Because the LHS of a compound assignment cannot change type, the RHS must be
276 // implicitly convertable to the LHS type. This fails since the RHS type can't
277 // be vector-extended implicitly.
278 //----------------------------------------------------------------------------//
280 #ifdef ERRORS
281 // The only cases that are really illegal here are when the RHS is a vector that
282 // is larger than the LHS or when the LHS is a scalar.
284 export float2 f2f4i2compound(float4 A, int2 B) {
285   A += B; // expected-error{{left hand operand of type 'float4' (aka 'vector<float, 4>') to compound assignment cannot be truncated when used with right hand operand of type 'int2' (aka 'vector<int, 2>')}}
286   return A.xy;
289 #endif
291 //----------------------------------------------------------------------------//
292 // Case 13: Comparison operators for mismatched arguments follow the same rules.
294 // Compare operators convert each argument following the usual arithmetic
295 // conversions.
296 //----------------------------------------------------------------------------//
298 // Note: these cases work and generate correct code, but the way they get there
299 // may change with https://github.com/llvm/llvm-project/issues/91639, because
300 // representing boolean vectors as 32-bit integer vectors will allow more
301 // efficient code generation.
303 // CHECK-LABEL: FunctionDecl {{.*}} used b4f4i4Compare 'bool4 (float4, int4)'
304 // CHECK: ImplicitCastExpr {{.*}} 'vector<bool, 4>' <IntegralToBoolean>
305 // CHECK-NEXT: BinaryOperator {{.*}} 'vector<int, 4>' '<'
306 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' <LValueToRValue>
307 // CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector<float, 4>' lvalue ParmVar {{.*}} 'A' 'float4':'vector<float, 4>'
308 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' <IntegralToFloating>
309 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int4':'vector<int, 4>' <LValueToRValue>
310 // CHECK-NEXT: DeclRefExpr {{.*}} 'int4':'vector<int, 4>' lvalue ParmVar {{.*}} 'B' 'int4':'vector<int, 4>'
311 export bool4 b4f4i4Compare(float4 A, int4 B) {
312   return A < B; // expected-warning{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'float4' (aka 'vector<float, 4>') may lose precision}}
316 // CHECK-LABEL: FunctionDecl {{.*}} used b2f2i4Compare 'bool2 (float2, int4)'
317 // CHECK: ImplicitCastExpr {{.*}} 'vector<bool, 2>' <IntegralToBoolean>
318 // CHECK-NEXT: BinaryOperator {{.*}} 'vector<int, 2>' '<='
319 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float2':'vector<float, 2>' <LValueToRValue>
320 // CHECK-NEXT: DeclRefExpr {{.*}} 'float2':'vector<float, 2>' lvalue ParmVar {{.*}} 'A' 'float2':'vector<float, 2>'
321 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float2':'vector<float, 2>' <IntegralToFloating>
322 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 2>' <HLSLVectorTruncation>
323 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int4':'vector<int, 4>' <LValueToRValue>
324 // CHECK-NEXT: DeclRefExpr {{.*}} 'int4':'vector<int, 4>' lvalue ParmVar {{.*}} 'B' 'int4':'vector<int, 4>'
326 export bool2 b2f2i4Compare(float2 A, int4 B) {
327   // expected-warning@#b2f2i4Compare{{implicit conversion truncates vector: 'int4' (aka 'vector<int, 4>') to 'float2' (aka 'vector<float, 2>')}}
328   // expected-warning@#b2f2i4Compare{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'float2' (aka 'vector<float, 2>') may lose precision}}
329   return A <= B; // #b2f2i4Compare
332 // CHECK-LABEL: FunctionDecl {{.*}} used b4fi4Compare 'bool4 (float, int4)'
333 // CHECK: ImplicitCastExpr {{.*}} 'vector<bool, 4>' <IntegralToBoolean>
334 // CHECK-NEXT: BinaryOperator {{.*}} 'vector<int, 4>' '>'
335 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 4>' <VectorSplat>
336 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
337 // CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'A' 'float'
338 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 4>' <IntegralToFloating>
339 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int4':'vector<int, 4>' <LValueToRValue>
340 // CHECK-NEXT: DeclRefExpr {{.*}} 'int4':'vector<int, 4>' lvalue ParmVar {{.*}} 'B' 'int4':'vector<int, 4>'
341 export bool4 b4fi4Compare(float A, int4 B) {
342   return A > B; // expected-warning{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'vector<float, 4>' (vector of 4 'float' values) may lose precision}}
345 //----------------------------------------------------------------------------//
346 // Case 14: Logical operators on vectors are disallowed in HLSL 2021+
347 //----------------------------------------------------------------------------//
349 #ifdef ERRORS
351 #if __HLSL_VERSION >= 2021
352 // expected-error@#b4f4i4Logical{{invalid operands to binary expression ('float4' (aka 'vector<float, 4>') and 'int4' (aka 'vector<int, 4>'))}}
353 // expected-note@#b4f4i4Logical{{did you mean or?}}
354 #else
355 // expected-warning@#b4f4i4Logical{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'float4' (aka 'vector<float, 4>') may lose precision}}
356 #endif
358 export bool4 b4f4i4Logical(float4 A, int4 B) {
359   return A || B; // #b4f4i4Logical
362 #if __HLSL_VERSION >= 2021
363 // expected-error@#b2f2i4Logical{{invalid operands to binary expression ('float2' (aka 'vector<float, 2>') and 'int4' (aka 'vector<int, 4>'))}}
364 // expected-note@#b2f2i4Logical{{did you mean and?}}
365 #else
366 // expected-warning@#b2f2i4Logical{{implicit conversion truncates vector: 'int4' (aka 'vector<int, 4>') to 'float2' (aka 'vector<float, 2>')}}
367 // expected-warning@#b2f2i4Logical{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'float2' (aka 'vector<float, 2>') may lose precision}}
368 #endif
370 export bool2 b2f2i4Logical(float2 A, int4 B) {
371   return A && B; // #b2f2i4Logical
374 #if __HLSL_VERSION >= 2021
375 // expected-error@#b2b2b2Logical{{invalid operands to binary expression ('bool2' (aka 'vector<bool, 2>') and 'bool2')}}
376 // expected-note@#b2b2b2Logical{{did you mean and?}}
377 #endif
379 export bool2 b2b2b2Logical(bool2 A, bool2 B) {
380   return A && B; // #b2b2b2Logical
383 #endif