diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -639,6 +639,7 @@ T __builtin_elementwise_log(T x) return the natural logarithm of x floating point types T __builtin_elementwise_log2(T x) return the base 2 logarithm of x floating point types T __builtin_elementwise_log10(T x) return the base 10 logarithm of x floating point types + T __builtin_elementwise_pow(T x, T y) return x raised to the power of y floating point types T __builtin_elementwise_exp(T x) returns the base-e exponential, e^x, of the specified value floating point types T __builtin_elementwise_exp2(T x) returns the base-2 exponential, 2^x, of the specified value floating point types T __builtin_elementwise_roundeven(T x) round x to the nearest integer value in floating point format, floating point types diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -648,6 +648,7 @@ - Add ``__builtin_elementwise_exp`` builtin for floating point types only. - Add ``__builtin_elementwise_exp2`` builtin for floating point types only. - Add ``__builtin_set_flt_rounds`` builtin for X86, x86_64, Arm and AArch64 only. +- Add ``__builtin_elementwise_pow`` builtin for floating point types only. AST Matchers ------------ diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -684,6 +684,7 @@ BUILTIN(__builtin_elementwise_log, "v.", "nct") BUILTIN(__builtin_elementwise_log2, "v.", "nct") BUILTIN(__builtin_elementwise_log10, "v.", "nct") +BUILTIN(__builtin_elementwise_pow, "v.", "nct") BUILTIN(__builtin_elementwise_roundeven, "v.", "nct") BUILTIN(__builtin_elementwise_sin, "v.", "nct") BUILTIN(__builtin_elementwise_trunc, "v.", "nct") diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -3157,6 +3157,14 @@ case Builtin::BI__builtin_elementwise_log10: return RValue::get( emitUnaryBuiltin(*this, E, llvm::Intrinsic::log10, "elt.log10")); + case Builtin::BI__builtin_elementwise_pow: { + Value* Op0 = EmitScalarExpr(E->getArg(0)); + Value* Op1 = EmitScalarExpr(E->getArg(1)); + unsigned Opc = llvm::Intrinsic::pow; + Value* Result = Builder.CreateBinaryIntrinsic(Opc, Op0, Op1, nullptr, "elt.pow"); + return RValue::get(Result); + } + case Builtin::BI__builtin_elementwise_cos: return RValue::get( emitUnaryBuiltin(*this, E, llvm::Intrinsic::cos, "elt.cos")); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2630,6 +2630,7 @@ case Builtin::BI__builtin_elementwise_floor: case Builtin::BI__builtin_elementwise_log: case Builtin::BI__builtin_elementwise_log2: + case Builtin::BI__builtin_elementwise_pow: case Builtin::BI__builtin_elementwise_log10: case Builtin::BI__builtin_elementwise_roundeven: case Builtin::BI__builtin_elementwise_sin: diff --git a/clang/test/CodeGen/builtins-elementwise-math.c b/clang/test/CodeGen/builtins-elementwise-math.c --- a/clang/test/CodeGen/builtins-elementwise-math.c +++ b/clang/test/CodeGen/builtins-elementwise-math.c @@ -452,6 +452,55 @@ vf2 = __builtin_elementwise_log2(vf1); } +void test_builtin_elementwise_pow(float f1, float f2, double d1, double d2, + float4 vf1, float4 vf2, long long int i1, + long long int i2, si8 vi1, si8 vi2, + unsigned u1, unsigned u2, u4 vu1, u4 vu2, + _BitInt(31) bi1, _BitInt(31) bi2, + unsigned _BitInt(55) bu1, unsigned _BitInt(55) bu2) { + // CHECK: [[I1:%.+]] = load i64, ptr %i1.addr, align 8 + // CHECK-NEXT: [[I2:%.+]] = load i64, ptr %i2.addr, align 8 + // CHECK-NEXT: call i64 @llvm.pow.i64(i64 [[I1]], i64 [[I2]]) + i1 = __builtin_elementwise_pow(i1, i2); + + // CHECK: [[I1:%.+]] = load i64, ptr %i1.addr, align 8 + // CHECK-NEXT: call i64 @llvm.pow.i64(i64 [[I1]], i64 10) + i1 = __builtin_elementwise_pow(i1, 10); + + // CHECK: [[VI1:%.+]] = load <8 x i16>, ptr %vi1.addr, align 16 + // CHECK-NEXT: [[VI2:%.+]] = load <8 x i16>, ptr %vi2.addr, align 16 + // CHECK-NEXT: call <8 x i16> @llvm.pow.v8i16(<8 x i16> [[VI1]], <8 x i16> [[VI2]]) + vi1 = __builtin_elementwise_pow(vi1, vi2); + + // CHECK: [[U1:%.+]] = load i32, ptr %u1.addr, align 4 + // CHECK-NEXT: [[U2:%.+]] = load i32, ptr %u2.addr, align 4 + // CHECK-NEXT: call i32 @llvm.pow.i32(i32 [[U1]], i32 [[U2]]) + u1 = __builtin_elementwise_pow(u1, u2); + + // CHECK: [[VU1:%.+]] = load <4 x i32>, ptr %vu1.addr, align 16 + // CHECK-NEXT: [[VU2:%.+]] = load <4 x i32>, ptr %vu2.addr, align 16 + // CHECK-NEXT: call <4 x i32> @llvm.pow.v4i32(<4 x i32> [[VU1]], <4 x i32> [[VU2]]) + vu1 = __builtin_elementwise_pow(vu1, vu2); + + // CHECK: [[BI1:%.+]] = load i31, ptr %bi1.addr, align 4 + // CHECK-NEXT: [[BI2:%.+]] = load i31, ptr %bi2.addr, align 4 + // CHECK-NEXT: call i31 @llvm.pow.i31(i31 [[BI1]], i31 [[BI2]]) + bi1 = __builtin_elementwise_pow(bi1, bi2); + + // CHECK: [[BU1:%.+]] = load i55, ptr %bu1.addr, align 8 + // CHECK-NEXT: [[BU2:%.+]] = load i55, ptr %bu2.addr, align 8 + // CHECK-NEXT: call i55 @llvm.pow.i55(i55 [[BU1]], i55 [[BU2]]) + bu1 = __builtin_elementwise_pow(bu1, bu2); + + // CHECK: [[IAS1:%.+]] = load i32, ptr addrspace(1) @int_as_one, align 4 + // CHECK-NEXT: [[B:%.+]] = load i32, ptr @b, align 4 + // CHECK-NEXT: call i32 @llvm.pow.i32(i32 [[IAS1]], i32 [[B]]) + int_as_one = __builtin_elementwise_pow(int_as_one, b); + + // CHECK: call i32 @llvm.pow.i32(i32 1, i32 97) + i1 = __builtin_elementwise_pow(1, 'a'); +} + void test_builtin_elementwise_roundeven(float f1, float f2, double d1, double d2, float4 vf1, float4 vf2) { // CHECK-LABEL: define void @test_builtin_elementwise_roundeven( diff --git a/clang/test/Sema/aarch64-sve-vector-pow-ops.c b/clang/test/Sema/aarch64-sve-vector-pow-ops.c new file mode 100644 --- /dev/null +++ b/clang/test/Sema/aarch64-sve-vector-pow-ops.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple aarch64 -target-feature +f -target-feature +d \ +// RUN: -target-feature +v -target-feature +zfh -target-feature +sve -target-feature +experimental-zvfh \ +// RUN: -disable-O0-optnone -o - -fsyntax-only %s -verify +// REQUIRES: aarch64-registered-target + +#include + +svfloat32_t test_pow_vv_i8mf8(svfloat32_t v) { + + return __builtin_elementwise_pow(v, v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} +} \ No newline at end of file diff --git a/clang/test/Sema/builtins-elementwise-math.c b/clang/test/Sema/builtins-elementwise-math.c --- a/clang/test/Sema/builtins-elementwise-math.c +++ b/clang/test/Sema/builtins-elementwise-math.c @@ -438,6 +438,65 @@ // expected-error@-1 {{1st argument must be a floating point type (was 'unsigned4' (vector of 4 'unsigned int' values))}} } +void test_builtin_elementwise_pow(int i, short s, double d, float4 v, int3 iv, unsigned3 uv, int *p) { + i = __builtin_elementwise_pow(p, d); + // expected-error@-1 {{arguments are of different types ('int *' vs 'double')}} + + struct Foo foo = __builtin_elementwise_pow(i, i); + // expected-error@-1 {{initializing 'struct Foo' with an expression of incompatible type 'int'}} + + i = __builtin_elementwise_pow(i); + // expected-error@-1 {{too few arguments to function call, expected 2, have 1}} + + i = __builtin_elementwise_pow(); + // expected-error@-1 {{too few arguments to function call, expected 2, have 0}} + + i = __builtin_elementwise_pow(i, i, i); + // expected-error@-1 {{too many arguments to function call, expected 2, have 3}} + + i = __builtin_elementwise_pow(v, iv); + // expected-error@-1 {{arguments are of different types ('float4' (vector of 4 'float' values) vs 'int3' (vector of 3 'int' values))}} + + i = __builtin_elementwise_pow(uv, iv); + // expected-error@-1 {{arguments are of different types ('unsigned3' (vector of 3 'unsigned int' values) vs 'int3' (vector of 3 'int' values))}} + + v = __builtin_elementwise_pow(v, v); + // expected-error@-1 {{1st argument must be a vector of integers (was 'float4' (vector of 4 'float' values))}} + + s = __builtin_elementwise_pow(i, s); + + enum e { one, + two }; + i = __builtin_elementwise_pow(one, two); + + enum f { three }; + enum f x = __builtin_elementwise_pow(one, three); + + _BitInt(32) ext; // expected-warning {{'_BitInt' in C17 and earlier is a Clang extension}} + ext = __builtin_elementwise_pow(ext, ext); + + const int ci; + i = __builtin_elementwise_pow(ci, i); + i = __builtin_elementwise_pow(i, ci); + i = __builtin_elementwise_pow(ci, ci); + + i = __builtin_elementwise_pow(i, int_as_one); // ok (attributes don't match)? + i = __builtin_elementwise_pow(i, b); // ok (sugar doesn't match)? + + int A[10]; + A = __builtin_elementwise_pow(A, A); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type (was 'int *')}} + + int(ii); + int j; + j = __builtin_elementwise_pow(i, j); + + _Complex float c1, c2; + c1 = __builtin_elementwise_pow(c1, c2); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type (was '_Complex float')}} +} + + void test_builtin_elementwise_roundeven(int i, float f, double d, float4 v, int3 iv, unsigned u, unsigned4 uv) { struct Foo s = __builtin_elementwise_roundeven(f); diff --git a/clang/test/Sema/riscv-sve-vector-pow-ops.c b/clang/test/Sema/riscv-sve-vector-pow-ops.c new file mode 100644 --- /dev/null +++ b/clang/test/Sema/riscv-sve-vector-pow-ops.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-feature +d \ +// RUN: -target-feature +v -target-feature +zfh -target-feature +experimental-zvfh \ +// RUN: -disable-O0-optnone -o - -fsyntax-only %s -verify +// REQUIRES: riscv-registered-target + +#include + + +vfloat32mf2_t test_pow_vv_i8mf8(vfloat32mf2_t v) { + + return __builtin_elementwise_pow(v, v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} +} \ No newline at end of file diff --git a/clang/test/SemaCXX/builtins-elementwise-math.cpp b/clang/test/SemaCXX/builtins-elementwise-math.cpp --- a/clang/test/SemaCXX/builtins-elementwise-math.cpp +++ b/clang/test/SemaCXX/builtins-elementwise-math.cpp @@ -108,3 +108,11 @@ static_assert(!is_const::value); static_assert(!is_const::value); } + +void test_builtin_elementwise_pow() { + const double a = 2; + double b = 1; + static_assert(!is_const::value); + static_assert(!is_const::value); + static_assert(!is_const::value); +}