Skip to content

Commit 511cfd9

Browse files
author
Francis Visoiu Mistrih
committed
[Clang] Add __builtin_elementwise|reduce_max|minimum
We have the LLVM intrinsics, and we're missing the clang builtins to be used directly in code that needs to make the distinction in NaN semantics.
1 parent fbec675 commit 511cfd9

11 files changed

+409
-72
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 87 additions & 71 deletions
Large diffs are not rendered by default.

clang/include/clang/Basic/Builtins.td

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,6 +1268,18 @@ def ElementwiseMin : Builtin {
12681268
let Prototype = "void(...)";
12691269
}
12701270

1271+
def ElementwiseMaximum : Builtin {
1272+
let Spellings = ["__builtin_elementwise_maximum"];
1273+
let Attributes = [NoThrow, Const, CustomTypeChecking];
1274+
let Prototype = "void(...)";
1275+
}
1276+
1277+
def ElementwiseMinimum : Builtin {
1278+
let Spellings = ["__builtin_elementwise_minimum"];
1279+
let Attributes = [NoThrow, Const, CustomTypeChecking];
1280+
let Prototype = "void(...)";
1281+
}
1282+
12711283
def ElementwiseCeil : Builtin {
12721284
let Spellings = ["__builtin_elementwise_ceil"];
12731285
let Attributes = [NoThrow, Const, CustomTypeChecking];
@@ -1436,6 +1448,18 @@ def ReduceMin : Builtin {
14361448
let Prototype = "void(...)";
14371449
}
14381450

1451+
def ReduceMaximum : Builtin {
1452+
let Spellings = ["__builtin_reduce_maximum"];
1453+
let Attributes = [NoThrow, Const, CustomTypeChecking];
1454+
let Prototype = "void(...)";
1455+
}
1456+
1457+
def ReduceMinimum : Builtin {
1458+
let Spellings = ["__builtin_reduce_minimum"];
1459+
let Attributes = [NoThrow, Const, CustomTypeChecking];
1460+
let Prototype = "void(...)";
1461+
}
1462+
14391463
def ReduceXor : Builtin {
14401464
let Spellings = ["__builtin_reduce_xor"];
14411465
let Attributes = [NoThrow, Const, CustomTypeChecking];

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12216,7 +12216,8 @@ def err_builtin_invalid_arg_type: Error <
1221612216
"a floating point type|"
1221712217
"a vector of integers|"
1221812218
"an unsigned integer|"
12219-
"an 'int'}1 (was %2)">;
12219+
"an 'int'|"
12220+
"a vector of floating points}1 (was %2)">;
1222012221

1222112222
def err_builtin_matrix_disabled: Error<
1222212223
"matrix types extension is disabled. Pass -fenable-matrix to enable it">;

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3960,6 +3960,22 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
39603960
return RValue::get(Result);
39613961
}
39623962

3963+
case Builtin::BI__builtin_elementwise_maximum: {
3964+
Value *Op0 = EmitScalarExpr(E->getArg(0));
3965+
Value *Op1 = EmitScalarExpr(E->getArg(1));
3966+
Value *Result = Builder.CreateBinaryIntrinsic(llvm::Intrinsic::maximum, Op0,
3967+
Op1, nullptr, "elt.maximum");
3968+
return RValue::get(Result);
3969+
}
3970+
3971+
case Builtin::BI__builtin_elementwise_minimum: {
3972+
Value *Op0 = EmitScalarExpr(E->getArg(0));
3973+
Value *Op1 = EmitScalarExpr(E->getArg(1));
3974+
Value *Result = Builder.CreateBinaryIntrinsic(llvm::Intrinsic::minimum, Op0,
3975+
Op1, nullptr, "elt.minimum");
3976+
return RValue::get(Result);
3977+
}
3978+
39633979
case Builtin::BI__builtin_reduce_max: {
39643980
auto GetIntrinsicID = [this](QualType QT) {
39653981
if (auto *VecTy = QT->getAs<VectorType>())
@@ -4013,6 +4029,29 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
40134029
return RValue::get(emitBuiltinWithOneOverloadedType<1>(
40144030
*this, E, llvm::Intrinsic::vector_reduce_and, "rdx.and"));
40154031

4032+
case Builtin::BI__builtin_reduce_maximum: {
4033+
auto GetIntrinsicID = [](QualType QT) {
4034+
if (auto *VecTy = QT->getAs<VectorType>())
4035+
QT = VecTy->getElementType();
4036+
assert(QT->isFloatingType() && "must have a float here");
4037+
return llvm::Intrinsic::vector_reduce_fmaximum;
4038+
};
4039+
return RValue::get(emitBuiltinWithOneOverloadedType<1>(
4040+
*this, E, GetIntrinsicID(E->getArg(0)->getType()), "rdx.maximum"));
4041+
}
4042+
4043+
case Builtin::BI__builtin_reduce_minimum: {
4044+
auto GetIntrinsicID = [](QualType QT) {
4045+
if (auto *VecTy = QT->getAs<VectorType>())
4046+
QT = VecTy->getElementType();
4047+
assert(QT->isFloatingType() && "must have a float here");
4048+
return llvm::Intrinsic::vector_reduce_fminimum;
4049+
};
4050+
4051+
return RValue::get(emitBuiltinWithOneOverloadedType<1>(
4052+
*this, E, GetIntrinsicID(E->getArg(0)->getType()), "rdx.minimum"));
4053+
}
4054+
40164055
case Builtin::BI__builtin_matrix_transpose: {
40174056
auto *MatrixTy = E->getArg(0)->getType()->castAs<ConstantMatrixType>();
40184057
Value *MatValue = EmitScalarExpr(E->getArg(0));

clang/lib/Sema/SemaChecking.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2755,6 +2755,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
27552755

27562756
// These builtins restrict the element type to floating point
27572757
// types only, and take in two arguments.
2758+
case Builtin::BI__builtin_elementwise_minimum:
2759+
case Builtin::BI__builtin_elementwise_maximum:
27582760
case Builtin::BI__builtin_elementwise_pow: {
27592761
if (BuiltinElementwiseMath(TheCall))
27602762
return ExprError();
@@ -2867,6 +2869,29 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
28672869
TheCall->setType(ElTy);
28682870
break;
28692871
}
2872+
case Builtin::BI__builtin_reduce_maximum:
2873+
case Builtin::BI__builtin_reduce_minimum: {
2874+
if (PrepareBuiltinReduceMathOneArgCall(TheCall))
2875+
return ExprError();
2876+
2877+
const Expr *Arg = TheCall->getArg(0);
2878+
const auto *TyA = Arg->getType()->getAs<VectorType>();
2879+
2880+
QualType ElTy;
2881+
if (TyA)
2882+
ElTy = TyA->getElementType();
2883+
else if (Arg->getType()->isSizelessVectorType())
2884+
ElTy = Arg->getType()->getSizelessVectorEltType(Context);
2885+
2886+
if (ElTy.isNull() || !ElTy->isFloatingType()) {
2887+
Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
2888+
<< 1 << /* vector of floating points */ 9 << Arg->getType();
2889+
return ExprError();
2890+
}
2891+
2892+
TheCall->setType(ElTy);
2893+
break;
2894+
}
28702895

28712896
// These builtins support vectors of integers only.
28722897
// TODO: ADD/MUL should support floating-point types.

clang/test/CodeGen/builtins-elementwise-math.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,82 @@ void test_builtin_elementwise_sub_sat(float f1, float f2, double d1, double d2,
169169
i1 = __builtin_elementwise_sub_sat(1, 'a');
170170
}
171171

172+
void test_builtin_elementwise_maximum(float f1, float f2, double d1, double d2,
173+
float4 vf1, float4 vf2, long long int i1,
174+
long long int i2, si8 vi1, si8 vi2,
175+
unsigned u1, unsigned u2, u4 vu1, u4 vu2,
176+
_BitInt(31) bi1, _BitInt(31) bi2,
177+
unsigned _BitInt(55) bu1, unsigned _BitInt(55) bu2) {
178+
// CHECK-LABEL: define void @test_builtin_elementwise_maximum(
179+
// CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4
180+
// CHECK-NEXT: [[F2:%.+]] = load float, ptr %f2.addr, align 4
181+
// CHECK-NEXT: call float @llvm.maximum.f32(float [[F1]], float [[F2]])
182+
f1 = __builtin_elementwise_maximum(f1, f2);
183+
184+
// CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8
185+
// CHECK-NEXT: [[D2:%.+]] = load double, ptr %d2.addr, align 8
186+
// CHECK-NEXT: call double @llvm.maximum.f64(double [[D1]], double [[D2]])
187+
d1 = __builtin_elementwise_maximum(d1, d2);
188+
189+
// CHECK: [[D2:%.+]] = load double, ptr %d2.addr, align 8
190+
// CHECK-NEXT: call double @llvm.maximum.f64(double 2.000000e+01, double [[D2]])
191+
d1 = __builtin_elementwise_maximum(20.0, d2);
192+
193+
// CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16
194+
// CHECK-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16
195+
// CHECK-NEXT: call <4 x float> @llvm.maximum.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]])
196+
vf1 = __builtin_elementwise_maximum(vf1, vf2);
197+
198+
// CHECK: [[CVF1:%.+]] = load <4 x float>, ptr %cvf1, align 16
199+
// CHECK-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16
200+
// CHECK-NEXT: call <4 x float> @llvm.maximum.v4f32(<4 x float> [[CVF1]], <4 x float> [[VF2]])
201+
const float4 cvf1 = vf1;
202+
vf1 = __builtin_elementwise_maximum(cvf1, vf2);
203+
204+
// CHECK: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16
205+
// CHECK-NEXT: [[CVF1:%.+]] = load <4 x float>, ptr %cvf1, align 16
206+
// CHECK-NEXT: call <4 x float> @llvm.maximum.v4f32(<4 x float> [[VF2]], <4 x float> [[CVF1]])
207+
vf1 = __builtin_elementwise_maximum(vf2, cvf1);
208+
}
209+
210+
void test_builtin_elementwise_minimum(float f1, float f2, double d1, double d2,
211+
float4 vf1, float4 vf2, long long int i1,
212+
long long int i2, si8 vi1, si8 vi2,
213+
unsigned u1, unsigned u2, u4 vu1, u4 vu2,
214+
_BitInt(31) bi1, _BitInt(31) bi2,
215+
unsigned _BitInt(55) bu1, unsigned _BitInt(55) bu2) {
216+
// CHECK-LABEL: define void @test_builtin_elementwise_minimum(
217+
// CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4
218+
// CHECK-NEXT: [[F2:%.+]] = load float, ptr %f2.addr, align 4
219+
// CHECK-NEXT: call float @llvm.minimum.f32(float [[F1]], float [[F2]])
220+
f1 = __builtin_elementwise_minimum(f1, f2);
221+
222+
// CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8
223+
// CHECK-NEXT: [[D2:%.+]] = load double, ptr %d2.addr, align 8
224+
// CHECK-NEXT: call double @llvm.minimum.f64(double [[D1]], double [[D2]])
225+
d1 = __builtin_elementwise_minimum(d1, d2);
226+
227+
// CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8
228+
// CHECK-NEXT: call double @llvm.minimum.f64(double [[D1]], double 2.000000e+00)
229+
d1 = __builtin_elementwise_minimum(d1, 2.0);
230+
231+
// CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16
232+
// CHECK-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16
233+
// CHECK-NEXT: call <4 x float> @llvm.minimum.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]])
234+
vf1 = __builtin_elementwise_minimum(vf1, vf2);
235+
236+
// CHECK: [[CVF1:%.+]] = load <4 x float>, ptr %cvf1, align 16
237+
// CHECK-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16
238+
// CHECK-NEXT: call <4 x float> @llvm.minimum.v4f32(<4 x float> [[CVF1]], <4 x float> [[VF2]])
239+
const float4 cvf1 = vf1;
240+
vf1 = __builtin_elementwise_minimum(cvf1, vf2);
241+
242+
// CHECK: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16
243+
// CHECK-NEXT: [[CVF1:%.+]] = load <4 x float>, ptr %cvf1, align 16
244+
// CHECK-NEXT: call <4 x float> @llvm.minimum.v4f32(<4 x float> [[VF2]], <4 x float> [[CVF1]])
245+
vf1 = __builtin_elementwise_minimum(vf2, cvf1);
246+
}
247+
172248
void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
173249
float4 vf1, float4 vf2, long long int i1,
174250
long long int i2, si8 vi1, si8 vi2,

clang/test/CodeGen/builtins-reduction-math.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,30 @@ void test_builtin_reduce_and(si8 vi1, u4 vu1) {
138138
unsigned r3 = __builtin_reduce_and(vu1);
139139
}
140140

141+
void test_builtin_reduce_maximum(float4 vf1) {
142+
// CHECK-LABEL: define void @test_builtin_reduce_maximum(
143+
// CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16
144+
// CHECK-NEXT: call float @llvm.vector.reduce.fmaximum.v4f32(<4 x float> [[VF1]])
145+
float r1 = __builtin_reduce_maximum(vf1);
146+
147+
// CHECK: [[VF1_AS1:%.+]] = load <4 x float>, ptr addrspace(1) @vf1_as_one, align 16
148+
// CHECK-NEXT: [[RDX1:%.+]] = call float @llvm.vector.reduce.fmaximum.v4f32(<4 x float> [[VF1_AS1]])
149+
// CHECK-NEXT: fpext float [[RDX1]] to double
150+
const double r4 = __builtin_reduce_maximum(vf1_as_one);
151+
}
152+
153+
void test_builtin_reduce_minimum(float4 vf1) {
154+
// CHECK-LABEL: define void @test_builtin_reduce_minimum(
155+
// CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16
156+
// CHECK-NEXT: call float @llvm.vector.reduce.fminimum.v4f32(<4 x float> [[VF1]])
157+
float r1 = __builtin_reduce_minimum(vf1);
158+
159+
// CHECK: [[VF1_AS1:%.+]] = load <4 x float>, ptr addrspace(1) @vf1_as_one, align 16
160+
// CHECK-NEXT: [[RDX1:%.+]] = call float @llvm.vector.reduce.fminimum.v4f32(<4 x float> [[VF1_AS1]])
161+
// CHECK-NEXT: fpext float [[RDX1]] to double
162+
const double r4 = __builtin_reduce_minimum(vf1_as_one);
163+
}
164+
141165
#if defined(__ARM_FEATURE_SVE)
142166
#include <arm_sve.h>
143167

clang/test/CodeGen/strictfp-elementwise-bulitins.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,26 @@ float4 strict_elementwise_min(float4 a, float4 b) {
4747
return __builtin_elementwise_min(a, b);
4848
}
4949

50+
// CHECK-LABEL: define dso_local noundef <4 x float> @_Z26strict_elementwise_maximumDv4_fS_
51+
// CHECK-SAME: (<4 x float> noundef [[A:%.*]], <4 x float> noundef [[B:%.*]]) local_unnamed_addr #[[ATTR2]] {
52+
// CHECK-NEXT: entry:
53+
// CHECK-NEXT: [[ELT_MAXIMUM:%.*]] = tail call <4 x float> @llvm.maximum.v4f32(<4 x float> [[A]], <4 x float> [[B]]) #[[ATTR4]]
54+
// CHECK-NEXT: ret <4 x float> [[ELT_MAXIMUM]]
55+
//
56+
float4 strict_elementwise_maximum(float4 a, float4 b) {
57+
return __builtin_elementwise_maximum(a, b);
58+
}
59+
60+
// CHECK-LABEL: define dso_local noundef <4 x float> @_Z26strict_elementwise_minimumDv4_fS_
61+
// CHECK-SAME: (<4 x float> noundef [[A:%.*]], <4 x float> noundef [[B:%.*]]) local_unnamed_addr #[[ATTR2]] {
62+
// CHECK-NEXT: entry:
63+
// CHECK-NEXT: [[ELT_MINIMUM:%.*]] = tail call <4 x float> @llvm.minimum.v4f32(<4 x float> [[A]], <4 x float> [[B]]) #[[ATTR4]]
64+
// CHECK-NEXT: ret <4 x float> [[ELT_MINIMUM]]
65+
//
66+
float4 strict_elementwise_minimum(float4 a, float4 b) {
67+
return __builtin_elementwise_minimum(a, b);
68+
}
69+
5070
// CHECK-LABEL: define dso_local noundef <4 x float> @_Z23strict_elementwise_ceilDv4_f
5171
// CHECK-SAME: (<4 x float> noundef [[A:%.*]]) local_unnamed_addr #[[ATTR2]] {
5272
// CHECK-NEXT: entry:

clang/test/Sema/builtins-elementwise-math.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,74 @@ void test_builtin_elementwise_min(int i, short s, double d, float4 v, int3 iv, u
273273
// expected-error@-1 {{1st argument must be a vector, integer or floating point type (was '_Complex float')}}
274274
}
275275

276+
void test_builtin_elementwise_maximum(int i, short s, float f, double d, float4 v, int3 iv, unsigned3 uv, int *p) {
277+
i = __builtin_elementwise_maximum(p, d);
278+
// expected-error@-1 {{arguments are of different types ('int *' vs 'double')}}
279+
280+
struct Foo foo = __builtin_elementwise_maximum(d, d);
281+
// expected-error@-1 {{initializing 'struct Foo' with an expression of incompatible type 'double'}}
282+
283+
i = __builtin_elementwise_maximum(i);
284+
// expected-error@-1 {{too few arguments to function call, expected 2, have 1}}
285+
286+
i = __builtin_elementwise_maximum();
287+
// expected-error@-1 {{too few arguments to function call, expected 2, have 0}}
288+
289+
i = __builtin_elementwise_maximum(i, i, i);
290+
// expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
291+
292+
i = __builtin_elementwise_maximum(v, iv);
293+
// expected-error@-1 {{arguments are of different types ('float4' (vector of 4 'float' values) vs 'int3' (vector of 3 'int' values))}}
294+
295+
i = __builtin_elementwise_maximum(uv, iv);
296+
// expected-error@-1 {{arguments are of different types ('unsigned3' (vector of 3 'unsigned int' values) vs 'int3' (vector of 3 'int' values))}}
297+
298+
d = __builtin_elementwise_maximum(d, f);
299+
300+
v = __builtin_elementwise_maximum(v, v);
301+
302+
int A[10];
303+
A = __builtin_elementwise_maximum(A, A);
304+
// expected-error@-1 {{1st argument must be a vector, integer or floating point type (was 'int *')}}
305+
306+
_Complex float c1, c2;
307+
c1 = __builtin_elementwise_maximum(c1, c2);
308+
// expected-error@-1 {{1st argument must be a vector, integer or floating point type (was '_Complex float')}}
309+
}
310+
311+
void test_builtin_elementwise_minimum(int i, short s, float f, double d, float4 v, int3 iv, unsigned3 uv, int *p) {
312+
i = __builtin_elementwise_minimum(p, d);
313+
// expected-error@-1 {{arguments are of different types ('int *' vs 'double')}}
314+
315+
struct Foo foo = __builtin_elementwise_minimum(d, d);
316+
// expected-error@-1 {{initializing 'struct Foo' with an expression of incompatible type 'double'}}
317+
318+
i = __builtin_elementwise_minimum(i);
319+
// expected-error@-1 {{too few arguments to function call, expected 2, have 1}}
320+
321+
i = __builtin_elementwise_minimum();
322+
// expected-error@-1 {{too few arguments to function call, expected 2, have 0}}
323+
324+
i = __builtin_elementwise_minimum(i, i, i);
325+
// expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
326+
327+
i = __builtin_elementwise_minimum(v, iv);
328+
// expected-error@-1 {{arguments are of different types ('float4' (vector of 4 'float' values) vs 'int3' (vector of 3 'int' values))}}
329+
330+
i = __builtin_elementwise_minimum(uv, iv);
331+
// expected-error@-1 {{arguments are of different types ('unsigned3' (vector of 3 'unsigned int' values) vs 'int3' (vector of 3 'int' values))}}
332+
333+
d = __builtin_elementwise_minimum(f, d);
334+
335+
int A[10];
336+
A = __builtin_elementwise_minimum(A, A);
337+
// expected-error@-1 {{1st argument must be a vector, integer or floating point type (was 'int *')}}
338+
339+
_Complex float c1, c2;
340+
c1 = __builtin_elementwise_minimum(c1, c2);
341+
// expected-error@-1 {{1st argument must be a vector, integer or floating point type (was '_Complex float')}}
342+
}
343+
276344
void test_builtin_elementwise_bitreverse(int i, float f, double d, float4 v, int3 iv, unsigned u, unsigned4 uv) {
277345

278346
struct Foo s = __builtin_elementwise_bitreverse(i);

clang/test/Sema/builtins-reduction-math.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,31 @@ void test_builtin_reduce_and(int i, float4 v, int3 iv) {
120120
i = __builtin_reduce_and(v);
121121
// expected-error@-1 {{1st argument must be a vector of integers (was 'float4' (vector of 4 'float' values))}}
122122
}
123+
124+
void test_builtin_reduce_maximum(int i, float4 v, int3 iv) {
125+
struct Foo s = __builtin_reduce_maximum(v);
126+
// expected-error@-1 {{initializing 'struct Foo' with an expression of incompatible type 'float'}}
127+
128+
i = __builtin_reduce_maximum(v, v);
129+
// expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
130+
131+
i = __builtin_reduce_maximum();
132+
// expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
133+
134+
i = __builtin_reduce_maximum(i);
135+
// expected-error@-1 {{1st argument must be a vector of floating points (was 'int')}}
136+
}
137+
138+
void test_builtin_reduce_minimum(int i, float4 v, int3 iv) {
139+
struct Foo s = __builtin_reduce_minimum(v);
140+
// expected-error@-1 {{initializing 'struct Foo' with an expression of incompatible type 'float'}}
141+
142+
i = __builtin_reduce_minimum(v, v);
143+
// expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
144+
145+
i = __builtin_reduce_minimum();
146+
// expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
147+
148+
i = __builtin_reduce_minimum(i);
149+
// expected-error@-1 {{1st argument must be a vector of floating points (was 'int')}}
150+
}

0 commit comments

Comments
 (0)