Author: Joshua Batista Date: 2023-07-24T14:03:58-07:00 New Revision: 3a98e73169e1d8e4fbb739462eea62445db1a6c8
URL: https://github.com/llvm/llvm-project/commit/3a98e73169e1d8e4fbb739462eea62445db1a6c8 DIFF: https://github.com/llvm/llvm-project/commit/3a98e73169e1d8e4fbb739462eea62445db1a6c8.diff LOG: clang: Add elementwise pow builtin Add codegen for llvm pow elementwise builtin The pow elementwise builtin is necessary for HLSL codegen. Tests were added to make sure that the expected errors are encountered when these functions are given inputs of incompatible types, or too many inputs. The new builtin is restricted to floating point types only. Reviewed By: arsenm Differential Revision: https://reviews.llvm.org/D153310 Added: clang/test/Sema/aarch64-sve-vector-pow-ops.c clang/test/Sema/riscv-sve-vector-pow-ops.c Modified: clang/docs/LanguageExtensions.rst clang/docs/ReleaseNotes.rst clang/include/clang/Basic/Builtins.def clang/lib/CodeGen/CGBuiltin.cpp clang/lib/Sema/SemaChecking.cpp clang/test/CodeGen/builtins-elementwise-math.c clang/test/CodeGen/strictfp-elementwise-bulitins.cpp clang/test/Sema/builtins-elementwise-math.c clang/test/SemaCXX/builtins-elementwise-math.cpp Removed: ################################################################################ diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 6705ee176196cc..1830480b1285d7 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -639,6 +639,7 @@ Unless specified otherwise operation(±0) = ±0 and operation(±infinity) = ±in 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 index d6cf96bee488d1..4f82edd0d03d14 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -961,6 +961,7 @@ Floating Point Support in Clang - 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 index fe00a2f69922a1..6dad8b512bd2df 100644 --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -687,6 +687,7 @@ BUILTIN(__builtin_elementwise_floor, "v.", "nct") 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 index d5ad35c0c93602..30f5f4e7061c05 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -3234,6 +3234,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, 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 index 17d9889da85e2d..f8e48728da6647 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2657,6 +2657,22 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, 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 index 729fd518c4488d..1087986c434774 100644 --- a/clang/test/CodeGen/builtins-elementwise-math.c +++ b/clang/test/CodeGen/builtins-elementwise-math.c @@ -452,6 +452,26 @@ void test_builtin_elementwise_log2(float f1, float f2, double d1, double d2, 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 index 3417d531c92bb3..76110e48ea3509 100644 --- a/clang/test/CodeGen/strictfp-elementwise-bulitins.cpp +++ b/clang/test/CodeGen/strictfp-elementwise-bulitins.cpp @@ -217,3 +217,12 @@ float4 strict_elementwise_fma(float4 a, float4 b, float4 c) { 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 index 00000000000000..1024cdc2517d07 --- /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 <arm_sve.h> + +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 index c23367df110ce9..5aad056c4de409 100644 --- a/clang/test/Sema/builtins-elementwise-math.c +++ b/clang/test/Sema/builtins-elementwise-math.c @@ -438,6 +438,31 @@ void test_builtin_elementwise_log2(int i, float f, double d, float4 v, int3 iv, // 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 diff erent 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 diff erent 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 diff erent 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 index 00000000000000..78efb4b549f801 --- /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 <riscv_vector.h> + + +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}} +} diff --git a/clang/test/SemaCXX/builtins-elementwise-math.cpp b/clang/test/SemaCXX/builtins-elementwise-math.cpp index 9a0e622f7bf973..492497aa33658a 100644 --- a/clang/test/SemaCXX/builtins-elementwise-math.cpp +++ b/clang/test/SemaCXX/builtins-elementwise-math.cpp @@ -198,3 +198,11 @@ void test_builtin_elementwise_fma() { static_assert(!is_const<decltype(__builtin_elementwise_fma(b, a, c))>::value); static_assert(!is_const<decltype(__builtin_elementwise_fma(c, c, c))>::value); } + +void test_builtin_elementwise_pow() { + const double a = 2; + double b = 1; + static_assert(!is_const<decltype(__builtin_elementwise_pow(a, b))>::value); + static_assert(!is_const<decltype(__builtin_elementwise_pow(b, a))>::value); + static_assert(!is_const<decltype(__builtin_elementwise_pow(a, a))>::value); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits