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 @@ -851,6 +851,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 @@ -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_pow, "v.", "nct") BUILTIN(__builtin_elementwise_roundeven, "v.", "nct") BUILTIN(__builtin_elementwise_round, "v.", "nct") BUILTIN(__builtin_elementwise_rint, "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 @@ -3234,6 +3234,9 @@ case Builtin::BI__builtin_elementwise_log10: return RValue::get( emitUnaryBuiltin(*this, E, llvm::Intrinsic::log10, "elt.log10")); + case Builtin::BI__builtin_elementwise_pow: { + return RValue::get(emitBinaryBuiltin(*this, E, llvm::Intrinsic::pow)); + } 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 @@ -2657,6 +2657,22 @@ return ExprError(); break; } + + // These builtins restrict the element type to floating point + // types only, and take in two arguments. + case Builtin::BI__builtin_elementwise_pow: { + if (SemaBuiltinElementwiseMath(TheCall)) + return ExprError(); + + QualType ArgTy = TheCall->getArg(0)->getType(); + if (checkFPMathBuiltinElementType(*this, TheCall->getArg(0)->getBeginLoc(), + ArgTy, 1) || + checkFPMathBuiltinElementType(*this, TheCall->getArg(1)->getBeginLoc(), + ArgTy, 2)) + return ExprError(); + break; + } + // These builtins restrict the element type to integer // types only. case Builtin::BI__builtin_elementwise_add_sat: 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,26 @@ vf2 = __builtin_elementwise_log2(vf1); } +void test_builtin_elementwise_pow(float f1, float f2, double d1, double d2, + float4 vf1, float4 vf2) { + + // CHECK-LABEL: define void @test_builtin_elementwise_pow( + // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4 + // CHECK: [[F2:%.+]] = load float, ptr %f2.addr, align 4 + // CHECK-NEXT: call float @llvm.pow.f32(float [[F1]], float [[F2]]) + f2 = __builtin_elementwise_pow(f1, f2); + + // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8 + // CHECK: [[D2:%.+]] = load double, ptr %d2.addr, align 8 + // CHECK-NEXT: call double @llvm.pow.f64(double [[D1]], double [[D2]]) + d2 = __builtin_elementwise_pow(d1, d2); + + // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16 + // CHECK: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16 + // CHECK-NEXT: call <4 x float> @llvm.pow.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]]) + vf2 = __builtin_elementwise_pow(vf1, vf2); +} + 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/CodeGen/strictfp-elementwise-bulitins.cpp b/clang/test/CodeGen/strictfp-elementwise-bulitins.cpp --- a/clang/test/CodeGen/strictfp-elementwise-bulitins.cpp +++ b/clang/test/CodeGen/strictfp-elementwise-bulitins.cpp @@ -217,3 +217,12 @@ return __builtin_elementwise_fma(a, b, c); } +// CHECK-LABEL: define dso_local noundef <4 x float> @_Z22strict_elementwise_powDv4_fS_ +// CHECK-SAME: (<4 x float> noundef [[A:%.*]], <4 x float> noundef [[B:%.*]]) local_unnamed_addr #[[ATTR2]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call <4 x float> @llvm.pow.v4f32(<4 x float> [[A]], <4 x float> [[B]]) #[[ATTR4]] +// CHECK-NEXT: ret <4 x float> [[TMP0]] +// +float4 strict_elementwise_pow(float4 a, float4 b) { + return __builtin_elementwise_pow(a, b); +} 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}} +} 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,31 @@ // 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 {{1st argument must be a floating point type (was '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))}} + +} + + 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 @@ -198,3 +198,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); +}