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