diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 9944cb28f0487..ab1fe885a3a75 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -645,6 +645,10 @@ Unless specified otherwise operation(±0) = ±0 and operation(±infinity) = ±in rounding halfway cases to even (that is, to the nearest value that is an even integer), regardless of the current rounding direction. + T __builtin_elementwise_round(T x) round x to the nearest integer value in floating point format, floating point types + rounding halfway cases away from zero, regardless of the + current rounding direction. May raise floating-point + exceptions. T __builtin_elementwise_trunc(T x) return the integral value nearest to but no larger in floating point types magnitude than x T __builtin_elementwise_canonicalize(T x) return the platform specific canonical encoding floating point types diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 6cee1c83706aa..7c6a350c7eab2 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -228,6 +228,10 @@ Non-comprehensive list of changes in this release variable as a way to disable color diagnostics. - Clang now supports ``__builtin_isfpclass``, which checks if the specified floating-point value falls into any of the specified data classes. +- Added ``__builtin_elementwise_round`` for builtin for floating + point types. This allows access to ``llvm.round`` for + arbitrary floating-point and vector of floating-point types. + New Compiler Flags ------------------ diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def index 59b61b89bd245..aa0076aab951c 100644 --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -687,6 +687,7 @@ BUILTIN(__builtin_elementwise_log, "v.", "nct") BUILTIN(__builtin_elementwise_log2, "v.", "nct") BUILTIN(__builtin_elementwise_log10, "v.", "nct") BUILTIN(__builtin_elementwise_roundeven, "v.", "nct") +BUILTIN(__builtin_elementwise_round, "v.", "nct") BUILTIN(__builtin_elementwise_sin, "v.", "nct") BUILTIN(__builtin_elementwise_trunc, "v.", "nct") BUILTIN(__builtin_elementwise_canonicalize, "v.", "nct") diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 69438960ebf23..7a38ac4ba10cb 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -3194,6 +3194,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_elementwise_roundeven: return RValue::get(emitUnaryBuiltin(*this, E, llvm::Intrinsic::roundeven, "elt.roundeven")); + case Builtin::BI__builtin_elementwise_round: + return RValue::get(emitUnaryBuiltin(*this, E, llvm::Intrinsic::round, + "elt.round")); case Builtin::BI__builtin_elementwise_sin: return RValue::get( emitUnaryBuiltin(*this, E, llvm::Intrinsic::sin, "elt.sin")); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index d3b37c1fa70a2..72b2f1d1edd82 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2636,6 +2636,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, case Builtin::BI__builtin_elementwise_log2: case Builtin::BI__builtin_elementwise_log10: case Builtin::BI__builtin_elementwise_roundeven: + case Builtin::BI__builtin_elementwise_round: case Builtin::BI__builtin_elementwise_sin: case Builtin::BI__builtin_elementwise_trunc: case Builtin::BI__builtin_elementwise_canonicalize: { diff --git a/clang/test/CodeGen/builtins-elementwise-math.c b/clang/test/CodeGen/builtins-elementwise-math.c index deb518b1ba597..4598faaa84163 100644 --- a/clang/test/CodeGen/builtins-elementwise-math.c +++ b/clang/test/CodeGen/builtins-elementwise-math.c @@ -468,6 +468,22 @@ void test_builtin_elementwise_roundeven(float f1, float f2, double d1, double d2 vf2 = __builtin_elementwise_roundeven(vf1); } +void test_builtin_elementwise_round(float f1, float f2, double d1, double d2, + float4 vf1, float4 vf2) { + // CHECK-LABEL: define void @test_builtin_elementwise_round( + // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4 + // CHECK-NEXT: call float @llvm.round.f32(float [[F1]]) + f2 = __builtin_elementwise_round(f1); + + // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8 + // CHECK-NEXT: call double @llvm.round.f64(double [[D1]]) + d2 = __builtin_elementwise_round(d1); + + // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16 + // CHECK-NEXT: call <4 x float> @llvm.round.v4f32(<4 x float> [[VF1]]) + vf2 = __builtin_elementwise_round(vf1); +} + void test_builtin_elementwise_sin(float f1, float f2, double d1, double d2, float4 vf1, float4 vf2) { // CHECK-LABEL: define void @test_builtin_elementwise_sin( diff --git a/clang/test/Sema/builtins-elementwise-math.c b/clang/test/Sema/builtins-elementwise-math.c index 35b065437e54f..030c03eccd646 100644 --- a/clang/test/Sema/builtins-elementwise-math.c +++ b/clang/test/Sema/builtins-elementwise-math.c @@ -459,6 +459,32 @@ void test_builtin_elementwise_roundeven(int i, float f, double d, float4 v, int3 // expected-error@-1 {{1st argument must be a floating point type (was 'unsigned4' (vector of 4 'unsigned int' values))}} } +void test_builtin_elementwise_round(int i, float f, double d, float4 v, int3 iv, unsigned u, unsigned4 uv) { + + struct Foo s = __builtin_elementwise_round(f); + // expected-error@-1 {{initializing 'struct Foo' with an expression of incompatible type 'float'}} + + i = __builtin_elementwise_round(); + // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} + + i = __builtin_elementwise_round(i); + // expected-error@-1 {{1st argument must be a floating point type (was 'int')}} + + i = __builtin_elementwise_round(f, f); + // expected-error@-1 {{too many arguments to function call, expected 1, have 2}} + + u = __builtin_elementwise_round(u); + // expected-error@-1 {{1st argument must be a floating point type (was 'unsigned int')}} + + uv = __builtin_elementwise_round(uv); + // expected-error@-1 {{1st argument must be a floating point type (was 'unsigned4' (vector of 4 'unsigned int' values))}} + + // FIXME: Error should not mention integer + _Complex float c1, c2; + c1 = __builtin_elementwise_round(c1); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type (was '_Complex float')}} +} + void test_builtin_elementwise_sin(int i, float f, double d, float4 v, int3 iv, unsigned u, unsigned4 uv) { struct Foo s = __builtin_elementwise_sin(f);