Skip to content

Commit e0dd22f

Browse files
authored
[Clang] Add elementwise maximumnum/minimumnum builtin functions (#149775)
Addresses #112164. minimumnum and maximumnum intrinsics were added in 5bf81e5. The new built-ins can be used for implementing OpenCL math function fmax and fmin in #128506.
1 parent 7dc9b43 commit e0dd22f

File tree

7 files changed

+300
-0
lines changed

7 files changed

+300
-0
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,14 @@ of different sizes and signs is forbidden in binary and ternary builtins.
848848
semantics, see `LangRef
849849
<http://llvm.org/docs/LangRef.html#llvm-min-intrinsics-comparation>`_
850850
for the comparison.
851+
T __builtin_elementwise_maximumnum(T x, T y) return x or y, whichever is larger. Follows IEEE 754-2019 floating point types
852+
semantics, see `LangRef
853+
<http://llvm.org/docs/LangRef.html#llvm-min-intrinsics-comparation>`_
854+
for the comparison.
855+
T __builtin_elementwise_minimumnum(T x, T y) return x or y, whichever is smaller. Follows IEEE 754-2019 floating point types
856+
semantics, see `LangRef
857+
<http://llvm.org/docs/LangRef.html#llvm-min-intrinsics-comparation>`_
858+
for the comparison.
851859
============================================== ====================================================================== =========================================
852860

853861

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ Non-comprehensive list of changes in this release
344344
- Added `__builtin_elementwise_exp10`.
345345
- For AMDPGU targets, added `__builtin_v_cvt_off_f32_i4` that maps to the `v_cvt_off_f32_i4` instruction.
346346
- Added `__builtin_elementwise_minnum` and `__builtin_elementwise_maxnum`.
347+
- Added `__builtin_elementwise_minnumnum` and `__builtin_elementwise_maxnumnum`.
347348
- No longer crashing on invalid Objective-C categories and extensions when
348349
dumping the AST as JSON. (#GH137320)
349350
- Clang itself now uses split stacks instead of threads for allocating more

clang/include/clang/Basic/Builtins.td

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,6 +1334,18 @@ def ElementwiseMinimum : Builtin {
13341334
let Prototype = "void(...)";
13351335
}
13361336

1337+
def ElementwiseMaximumNum : Builtin {
1338+
let Spellings = ["__builtin_elementwise_maximumnum"];
1339+
let Attributes = [NoThrow, Const, CustomTypeChecking];
1340+
let Prototype = "void(...)";
1341+
}
1342+
1343+
def ElementwiseMinimumNum : Builtin {
1344+
let Spellings = ["__builtin_elementwise_minimumnum"];
1345+
let Attributes = [NoThrow, Const, CustomTypeChecking];
1346+
let Prototype = "void(...)";
1347+
}
1348+
13371349
def ElementwiseCeil : Builtin {
13381350
let Spellings = ["__builtin_elementwise_ceil"];
13391351
let Attributes = [NoThrow, Const, CustomTypeChecking];

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4108,6 +4108,22 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
41084108
return RValue::get(Result);
41094109
}
41104110

4111+
case Builtin::BI__builtin_elementwise_maximumnum: {
4112+
Value *Op0 = EmitScalarExpr(E->getArg(0));
4113+
Value *Op1 = EmitScalarExpr(E->getArg(1));
4114+
Value *Result = Builder.CreateBinaryIntrinsic(
4115+
Intrinsic::maximumnum, Op0, Op1, nullptr, "elt.maximumnum");
4116+
return RValue::get(Result);
4117+
}
4118+
4119+
case Builtin::BI__builtin_elementwise_minimumnum: {
4120+
Value *Op0 = EmitScalarExpr(E->getArg(0));
4121+
Value *Op1 = EmitScalarExpr(E->getArg(1));
4122+
Value *Result = Builder.CreateBinaryIntrinsic(
4123+
Intrinsic::minimumnum, Op0, Op1, nullptr, "elt.minimumnum");
4124+
return RValue::get(Result);
4125+
}
4126+
41114127
case Builtin::BI__builtin_reduce_max: {
41124128
auto GetIntrinsicID = [this](QualType QT) {
41134129
if (auto *VecTy = QT->getAs<VectorType>())

clang/lib/Sema/SemaChecking.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3013,6 +3013,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
30133013
case Builtin::BI__builtin_elementwise_maxnum:
30143014
case Builtin::BI__builtin_elementwise_minimum:
30153015
case Builtin::BI__builtin_elementwise_maximum:
3016+
case Builtin::BI__builtin_elementwise_minimumnum:
3017+
case Builtin::BI__builtin_elementwise_maximumnum:
30163018
case Builtin::BI__builtin_elementwise_atan2:
30173019
case Builtin::BI__builtin_elementwise_fmod:
30183020
case Builtin::BI__builtin_elementwise_pow:
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
2+
// RUN: %clang_cc1 -x c++ -std=c++20 -disable-llvm-passes -O3 -triple x86_64 %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK
3+
4+
typedef _Float16 half8 __attribute__((ext_vector_type(8)));
5+
typedef __bf16 bf16x8 __attribute__((ext_vector_type(8)));
6+
typedef float float4 __attribute__((ext_vector_type(4)));
7+
typedef double double2 __attribute__((ext_vector_type(2)));
8+
typedef long double ldouble2 __attribute__((ext_vector_type(2)));
9+
10+
// CHECK-LABEL: define dso_local noundef <8 x half> @_Z7pfmin16Dv8_DF16_S_(
11+
// CHECK-SAME: <8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0:[0-9]+]] {
12+
// CHECK-NEXT: [[ENTRY:.*:]]
13+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <8 x half>, align 16
14+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <8 x half>, align 16
15+
// CHECK-NEXT: store <8 x half> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2:![0-9]+]]
16+
// CHECK-NEXT: store <8 x half> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
17+
// CHECK-NEXT: [[TMP0:%.*]] = load <8 x half>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
18+
// CHECK-NEXT: [[TMP1:%.*]] = load <8 x half>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
19+
// CHECK-NEXT: [[ELT_MINIMUMNUM:%.*]] = call <8 x half> @llvm.minimumnum.v8f16(<8 x half> [[TMP0]], <8 x half> [[TMP1]])
20+
// CHECK-NEXT: ret <8 x half> [[ELT_MINIMUMNUM]]
21+
//
22+
half8 pfmin16(half8 a, half8 b) {
23+
return __builtin_elementwise_minimumnum(a, b);
24+
}
25+
// CHECK-LABEL: define dso_local noundef <8 x bfloat> @_Z8pfmin16bDv8_DF16bS_(
26+
// CHECK-SAME: <8 x bfloat> noundef [[A:%.*]], <8 x bfloat> noundef [[B:%.*]]) #[[ATTR0]] {
27+
// CHECK-NEXT: [[ENTRY:.*:]]
28+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <8 x bfloat>, align 16
29+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <8 x bfloat>, align 16
30+
// CHECK-NEXT: store <8 x bfloat> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
31+
// CHECK-NEXT: store <8 x bfloat> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
32+
// CHECK-NEXT: [[TMP0:%.*]] = load <8 x bfloat>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
33+
// CHECK-NEXT: [[TMP1:%.*]] = load <8 x bfloat>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
34+
// CHECK-NEXT: [[ELT_MINIMUMNUM:%.*]] = call <8 x bfloat> @llvm.minimumnum.v8bf16(<8 x bfloat> [[TMP0]], <8 x bfloat> [[TMP1]])
35+
// CHECK-NEXT: ret <8 x bfloat> [[ELT_MINIMUMNUM]]
36+
//
37+
bf16x8 pfmin16b(bf16x8 a, bf16x8 b) {
38+
return __builtin_elementwise_minimumnum(a, b);
39+
}
40+
// CHECK-LABEL: define dso_local noundef <4 x float> @_Z7pfmin32Dv4_fS_(
41+
// CHECK-SAME: <4 x float> noundef [[A:%.*]], <4 x float> noundef [[B:%.*]]) #[[ATTR0]] {
42+
// CHECK-NEXT: [[ENTRY:.*:]]
43+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <4 x float>, align 16
44+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <4 x float>, align 16
45+
// CHECK-NEXT: store <4 x float> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
46+
// CHECK-NEXT: store <4 x float> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
47+
// CHECK-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
48+
// CHECK-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
49+
// CHECK-NEXT: [[ELT_MINIMUMNUM:%.*]] = call <4 x float> @llvm.minimumnum.v4f32(<4 x float> [[TMP0]], <4 x float> [[TMP1]])
50+
// CHECK-NEXT: ret <4 x float> [[ELT_MINIMUMNUM]]
51+
//
52+
float4 pfmin32(float4 a, float4 b) {
53+
return __builtin_elementwise_minimumnum(a, b);
54+
}
55+
// CHECK-LABEL: define dso_local noundef <2 x double> @_Z7pfmin64Dv2_dS_(
56+
// CHECK-SAME: <2 x double> noundef [[A:%.*]], <2 x double> noundef [[B:%.*]]) #[[ATTR0]] {
57+
// CHECK-NEXT: [[ENTRY:.*:]]
58+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <2 x double>, align 16
59+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <2 x double>, align 16
60+
// CHECK-NEXT: store <2 x double> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
61+
// CHECK-NEXT: store <2 x double> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
62+
// CHECK-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
63+
// CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
64+
// CHECK-NEXT: [[ELT_MINIMUMNUM:%.*]] = call <2 x double> @llvm.minimumnum.v2f64(<2 x double> [[TMP0]], <2 x double> [[TMP1]])
65+
// CHECK-NEXT: ret <2 x double> [[ELT_MINIMUMNUM]]
66+
//
67+
double2 pfmin64(double2 a, double2 b) {
68+
return __builtin_elementwise_minimumnum(a, b);
69+
}
70+
// CHECK-LABEL: define dso_local noundef <2 x x86_fp80> @_Z7pfmin80Dv2_eS_(
71+
// CHECK-SAME: ptr noundef byval(<2 x x86_fp80>) align 32 [[TMP0:%.*]], ptr noundef byval(<2 x x86_fp80>) align 32 [[TMP1:%.*]]) #[[ATTR2:[0-9]+]] {
72+
// CHECK-NEXT: [[ENTRY:.*:]]
73+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <2 x x86_fp80>, align 32
74+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <2 x x86_fp80>, align 32
75+
// CHECK-NEXT: [[A:%.*]] = load <2 x x86_fp80>, ptr [[TMP0]], align 32, !tbaa [[TBAA2]]
76+
// CHECK-NEXT: [[B:%.*]] = load <2 x x86_fp80>, ptr [[TMP1]], align 32, !tbaa [[TBAA2]]
77+
// CHECK-NEXT: store <2 x x86_fp80> [[A]], ptr [[A_ADDR]], align 32, !tbaa [[TBAA2]]
78+
// CHECK-NEXT: store <2 x x86_fp80> [[B]], ptr [[B_ADDR]], align 32, !tbaa [[TBAA2]]
79+
// CHECK-NEXT: [[TMP2:%.*]] = load <2 x x86_fp80>, ptr [[A_ADDR]], align 32, !tbaa [[TBAA2]]
80+
// CHECK-NEXT: [[TMP3:%.*]] = load <2 x x86_fp80>, ptr [[B_ADDR]], align 32, !tbaa [[TBAA2]]
81+
// CHECK-NEXT: [[ELT_MINIMUMNUM:%.*]] = call <2 x x86_fp80> @llvm.minimumnum.v2f80(<2 x x86_fp80> [[TMP2]], <2 x x86_fp80> [[TMP3]])
82+
// CHECK-NEXT: ret <2 x x86_fp80> [[ELT_MINIMUMNUM]]
83+
//
84+
ldouble2 pfmin80(ldouble2 a, ldouble2 b) {
85+
return __builtin_elementwise_minimumnum(a, b);
86+
}
87+
88+
// CHECK-LABEL: define dso_local noundef <8 x half> @_Z7pfmax16Dv8_DF16_S_(
89+
// CHECK-SAME: <8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
90+
// CHECK-NEXT: [[ENTRY:.*:]]
91+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <8 x half>, align 16
92+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <8 x half>, align 16
93+
// CHECK-NEXT: store <8 x half> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
94+
// CHECK-NEXT: store <8 x half> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
95+
// CHECK-NEXT: [[TMP0:%.*]] = load <8 x half>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
96+
// CHECK-NEXT: [[TMP1:%.*]] = load <8 x half>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
97+
// CHECK-NEXT: [[ELT_MAXIMUMNUM:%.*]] = call <8 x half> @llvm.maximumnum.v8f16(<8 x half> [[TMP0]], <8 x half> [[TMP1]])
98+
// CHECK-NEXT: ret <8 x half> [[ELT_MAXIMUMNUM]]
99+
//
100+
half8 pfmax16(half8 a, half8 b) {
101+
return __builtin_elementwise_maximumnum(a, b);
102+
}
103+
// CHECK-LABEL: define dso_local noundef <8 x bfloat> @_Z8pfmax16bDv8_DF16bS_(
104+
// CHECK-SAME: <8 x bfloat> noundef [[A:%.*]], <8 x bfloat> noundef [[B:%.*]]) #[[ATTR0]] {
105+
// CHECK-NEXT: [[ENTRY:.*:]]
106+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <8 x bfloat>, align 16
107+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <8 x bfloat>, align 16
108+
// CHECK-NEXT: store <8 x bfloat> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
109+
// CHECK-NEXT: store <8 x bfloat> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
110+
// CHECK-NEXT: [[TMP0:%.*]] = load <8 x bfloat>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
111+
// CHECK-NEXT: [[TMP1:%.*]] = load <8 x bfloat>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
112+
// CHECK-NEXT: [[ELT_MAXIMUMNUM:%.*]] = call <8 x bfloat> @llvm.maximumnum.v8bf16(<8 x bfloat> [[TMP0]], <8 x bfloat> [[TMP1]])
113+
// CHECK-NEXT: ret <8 x bfloat> [[ELT_MAXIMUMNUM]]
114+
//
115+
bf16x8 pfmax16b(bf16x8 a, bf16x8 b) {
116+
return __builtin_elementwise_maximumnum(a, b);
117+
}
118+
// CHECK-LABEL: define dso_local noundef <4 x float> @_Z7pfmax32Dv4_fS_(
119+
// CHECK-SAME: <4 x float> noundef [[A:%.*]], <4 x float> noundef [[B:%.*]]) #[[ATTR0]] {
120+
// CHECK-NEXT: [[ENTRY:.*:]]
121+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <4 x float>, align 16
122+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <4 x float>, align 16
123+
// CHECK-NEXT: store <4 x float> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
124+
// CHECK-NEXT: store <4 x float> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
125+
// CHECK-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
126+
// CHECK-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
127+
// CHECK-NEXT: [[ELT_MAXIMUMNUM:%.*]] = call <4 x float> @llvm.maximumnum.v4f32(<4 x float> [[TMP0]], <4 x float> [[TMP1]])
128+
// CHECK-NEXT: ret <4 x float> [[ELT_MAXIMUMNUM]]
129+
//
130+
float4 pfmax32(float4 a, float4 b) {
131+
return __builtin_elementwise_maximumnum(a, b);
132+
}
133+
// CHECK-LABEL: define dso_local noundef <2 x double> @_Z7pfmax64Dv2_dS_(
134+
// CHECK-SAME: <2 x double> noundef [[A:%.*]], <2 x double> noundef [[B:%.*]]) #[[ATTR0]] {
135+
// CHECK-NEXT: [[ENTRY:.*:]]
136+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <2 x double>, align 16
137+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <2 x double>, align 16
138+
// CHECK-NEXT: store <2 x double> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
139+
// CHECK-NEXT: store <2 x double> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
140+
// CHECK-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
141+
// CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
142+
// CHECK-NEXT: [[ELT_MAXIMUMNUM:%.*]] = call <2 x double> @llvm.maximumnum.v2f64(<2 x double> [[TMP0]], <2 x double> [[TMP1]])
143+
// CHECK-NEXT: ret <2 x double> [[ELT_MAXIMUMNUM]]
144+
//
145+
double2 pfmax64(double2 a, double2 b) {
146+
return __builtin_elementwise_maximumnum(a, b);
147+
}
148+
149+
// CHECK-LABEL: define dso_local noundef <2 x x86_fp80> @_Z7pfmax80Dv2_eS_(
150+
// CHECK-SAME: ptr noundef byval(<2 x x86_fp80>) align 32 [[TMP0:%.*]], ptr noundef byval(<2 x x86_fp80>) align 32 [[TMP1:%.*]]) #[[ATTR2]] {
151+
// CHECK-NEXT: [[ENTRY:.*:]]
152+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <2 x x86_fp80>, align 32
153+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <2 x x86_fp80>, align 32
154+
// CHECK-NEXT: [[A:%.*]] = load <2 x x86_fp80>, ptr [[TMP0]], align 32, !tbaa [[TBAA2]]
155+
// CHECK-NEXT: [[B:%.*]] = load <2 x x86_fp80>, ptr [[TMP1]], align 32, !tbaa [[TBAA2]]
156+
// CHECK-NEXT: store <2 x x86_fp80> [[A]], ptr [[A_ADDR]], align 32, !tbaa [[TBAA2]]
157+
// CHECK-NEXT: store <2 x x86_fp80> [[B]], ptr [[B_ADDR]], align 32, !tbaa [[TBAA2]]
158+
// CHECK-NEXT: [[TMP2:%.*]] = load <2 x x86_fp80>, ptr [[A_ADDR]], align 32, !tbaa [[TBAA2]]
159+
// CHECK-NEXT: [[TMP3:%.*]] = load <2 x x86_fp80>, ptr [[B_ADDR]], align 32, !tbaa [[TBAA2]]
160+
// CHECK-NEXT: [[ELT_MINIMUMNUM:%.*]] = call <2 x x86_fp80> @llvm.minimumnum.v2f80(<2 x x86_fp80> [[TMP2]], <2 x x86_fp80> [[TMP3]])
161+
// CHECK-NEXT: ret <2 x x86_fp80> [[ELT_MINIMUMNUM]]
162+
//
163+
ldouble2 pfmax80(ldouble2 a, ldouble2 b) {
164+
return __builtin_elementwise_minimumnum(a, b);
165+
}
166+
167+
//.
168+
// CHECK: [[TBAA2]] = !{[[META3:![0-9]+]], [[META3]], i64 0}
169+
// CHECK: [[META3]] = !{!"omnipotent char", [[META4:![0-9]+]], i64 0}
170+
// CHECK: [[META4]] = !{!"Simple C++ TBAA"}
171+
//.

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

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,96 @@ void test_builtin_elementwise_minimum(int i, short s, float f, double d, float4
386386
// expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was '_Complex float')}}
387387
}
388388

389+
void test_builtin_elementwise_maximumnum(int i, short s, float f, double d, float4 fv, double4 dv, int3 iv, unsigned3 uv, int *p) {
390+
i = __builtin_elementwise_maximumnum(p, d);
391+
// expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int *')}}
392+
393+
struct Foo foo = __builtin_elementwise_maximumnum(d, d);
394+
// expected-error@-1 {{initializing 'struct Foo' with an expression of incompatible type 'double'}}
395+
396+
i = __builtin_elementwise_maximumnum(i);
397+
// expected-error@-1 {{too few arguments to function call, expected 2, have 1}}
398+
399+
i = __builtin_elementwise_maximumnum();
400+
// expected-error@-1 {{too few arguments to function call, expected 2, have 0}}
401+
402+
i = __builtin_elementwise_maximumnum(i, i, i);
403+
// expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
404+
405+
i = __builtin_elementwise_maximumnum(fv, iv);
406+
// expected-error@-1 {{arguments are of different types ('float4' (vector of 4 'float' values) vs 'int3' (vector of 3 'int' values))}}
407+
408+
i = __builtin_elementwise_maximumnum(uv, iv);
409+
// expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'unsigned3' (vector of 3 'unsigned int' values))}}
410+
411+
dv = __builtin_elementwise_maximumnum(fv, dv);
412+
// expected-error@-1 {{arguments are of different types ('float4' (vector of 4 'float' values) vs 'double4' (vector of 4 'double' values))}}
413+
414+
d = __builtin_elementwise_maximumnum(f, d);
415+
// expected-error@-1 {{arguments are of different types ('float' vs 'double')}}
416+
417+
fv = __builtin_elementwise_maximumnum(fv, fv);
418+
419+
i = __builtin_elementwise_maximumnum(iv, iv);
420+
// expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int3' (vector of 3 'int' values))}}
421+
422+
i = __builtin_elementwise_maximumnum(i, i);
423+
// expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int')}}
424+
425+
int A[10];
426+
A = __builtin_elementwise_maximumnum(A, A);
427+
// expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int *')}}
428+
429+
_Complex float c1, c2;
430+
c1 = __builtin_elementwise_maximumnum(c1, c2);
431+
// expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was '_Complex float')}}
432+
}
433+
434+
void test_builtin_elementwise_minimumnum(int i, short s, float f, double d, float4 fv, double4 dv, int3 iv, unsigned3 uv, int *p) {
435+
i = __builtin_elementwise_minimumnum(p, d);
436+
// expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int *')}}
437+
438+
struct Foo foo = __builtin_elementwise_minimumnum(d, d);
439+
// expected-error@-1 {{initializing 'struct Foo' with an expression of incompatible type 'double'}}
440+
441+
i = __builtin_elementwise_minimumnum(i);
442+
// expected-error@-1 {{too few arguments to function call, expected 2, have 1}}
443+
444+
i = __builtin_elementwise_minimumnum();
445+
// expected-error@-1 {{too few arguments to function call, expected 2, have 0}}
446+
447+
i = __builtin_elementwise_minimumnum(i, i, i);
448+
// expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
449+
450+
i = __builtin_elementwise_minimumnum(fv, iv);
451+
// expected-error@-1 {{arguments are of different types ('float4' (vector of 4 'float' values) vs 'int3' (vector of 3 'int' values))}}
452+
453+
i = __builtin_elementwise_minimumnum(uv, iv);
454+
// expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'unsigned3' (vector of 3 'unsigned int' values))}}
455+
456+
dv = __builtin_elementwise_minimumnum(fv, dv);
457+
// expected-error@-1 {{arguments are of different types ('float4' (vector of 4 'float' values) vs 'double4' (vector of 4 'double' values))}}
458+
459+
d = __builtin_elementwise_minimumnum(f, d);
460+
// expected-error@-1 {{arguments are of different types ('float' vs 'double')}}
461+
462+
fv = __builtin_elementwise_minimumnum(fv, fv);
463+
464+
i = __builtin_elementwise_minimumnum(iv, iv);
465+
// expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int3' (vector of 3 'int' values))}}
466+
467+
i = __builtin_elementwise_minimumnum(i, i);
468+
// expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int')}}
469+
470+
int A[10];
471+
A = __builtin_elementwise_minimumnum(A, A);
472+
// expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int *')}}
473+
474+
_Complex float c1, c2;
475+
c1 = __builtin_elementwise_minimumnum(c1, c2);
476+
// expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was '_Complex float')}}
477+
}
478+
389479
void test_builtin_elementwise_bitreverse(int i, float f, double d, float4 v, int3 iv, unsigned u, unsigned4 uv) {
390480

391481
struct Foo s = __builtin_elementwise_bitreverse(i);

0 commit comments

Comments
 (0)