Index: clang/docs/LanguageExtensions.rst =================================================================== --- clang/docs/LanguageExtensions.rst +++ clang/docs/LanguageExtensions.rst @@ -645,6 +645,10 @@ 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 Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -228,6 +228,10 @@ 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 ------------------ Index: clang/include/clang/Basic/Builtins.def =================================================================== --- clang/include/clang/Basic/Builtins.def +++ clang/include/clang/Basic/Builtins.def @@ -687,6 +687,7 @@ 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") Index: clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- clang/lib/CodeGen/CGBuiltin.cpp +++ clang/lib/CodeGen/CGBuiltin.cpp @@ -3194,6 +3194,9 @@ 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")); Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -2636,6 +2636,7 @@ 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: { Index: clang/test/CodeGen/builtins-elementwise-math.c =================================================================== --- clang/test/CodeGen/builtins-elementwise-math.c +++ clang/test/CodeGen/builtins-elementwise-math.c @@ -468,6 +468,22 @@ 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( Index: clang/test/Sema/builtins-elementwise-math.c =================================================================== --- clang/test/Sema/builtins-elementwise-math.c +++ clang/test/Sema/builtins-elementwise-math.c @@ -459,6 +459,32 @@ // 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);