Skip to content

Commit 3a98e73

Browse files
committed
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
1 parent 4e680ae commit 3a98e73

11 files changed

+109
-0
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,7 @@ Unless specified otherwise operation(±0) = ±0 and operation(±infinity) = ±in
639639
T __builtin_elementwise_log(T x) return the natural logarithm of x floating point types
640640
T __builtin_elementwise_log2(T x) return the base 2 logarithm of x floating point types
641641
T __builtin_elementwise_log10(T x) return the base 10 logarithm of x floating point types
642+
T __builtin_elementwise_pow(T x, T y) return x raised to the power of y floating point types
642643
T __builtin_elementwise_exp(T x) returns the base-e exponential, e^x, of the specified value floating point types
643644
T __builtin_elementwise_exp2(T x) returns the base-2 exponential, 2^x, of the specified value floating point types
644645
T __builtin_elementwise_roundeven(T x) round x to the nearest integer value in floating point format, floating point types

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,7 @@ Floating Point Support in Clang
961961
- Add ``__builtin_elementwise_exp`` builtin for floating point types only.
962962
- Add ``__builtin_elementwise_exp2`` builtin for floating point types only.
963963
- Add ``__builtin_set_flt_rounds`` builtin for X86, x86_64, Arm and AArch64 only.
964+
- Add ``__builtin_elementwise_pow`` builtin for floating point types only.
964965

965966
AST Matchers
966967
------------

clang/include/clang/Basic/Builtins.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,7 @@ BUILTIN(__builtin_elementwise_floor, "v.", "nct")
687687
BUILTIN(__builtin_elementwise_log, "v.", "nct")
688688
BUILTIN(__builtin_elementwise_log2, "v.", "nct")
689689
BUILTIN(__builtin_elementwise_log10, "v.", "nct")
690+
BUILTIN(__builtin_elementwise_pow, "v.", "nct")
690691
BUILTIN(__builtin_elementwise_roundeven, "v.", "nct")
691692
BUILTIN(__builtin_elementwise_round, "v.", "nct")
692693
BUILTIN(__builtin_elementwise_rint, "v.", "nct")

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3234,6 +3234,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
32343234
case Builtin::BI__builtin_elementwise_log10:
32353235
return RValue::get(
32363236
emitUnaryBuiltin(*this, E, llvm::Intrinsic::log10, "elt.log10"));
3237+
case Builtin::BI__builtin_elementwise_pow: {
3238+
return RValue::get(emitBinaryBuiltin(*this, E, llvm::Intrinsic::pow));
3239+
}
32373240
case Builtin::BI__builtin_elementwise_cos:
32383241
return RValue::get(
32393242
emitUnaryBuiltin(*this, E, llvm::Intrinsic::cos, "elt.cos"));

clang/lib/Sema/SemaChecking.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2657,6 +2657,22 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
26572657
return ExprError();
26582658
break;
26592659
}
2660+
2661+
// These builtins restrict the element type to floating point
2662+
// types only, and take in two arguments.
2663+
case Builtin::BI__builtin_elementwise_pow: {
2664+
if (SemaBuiltinElementwiseMath(TheCall))
2665+
return ExprError();
2666+
2667+
QualType ArgTy = TheCall->getArg(0)->getType();
2668+
if (checkFPMathBuiltinElementType(*this, TheCall->getArg(0)->getBeginLoc(),
2669+
ArgTy, 1) ||
2670+
checkFPMathBuiltinElementType(*this, TheCall->getArg(1)->getBeginLoc(),
2671+
ArgTy, 2))
2672+
return ExprError();
2673+
break;
2674+
}
2675+
26602676
// These builtins restrict the element type to integer
26612677
// types only.
26622678
case Builtin::BI__builtin_elementwise_add_sat:

clang/test/CodeGen/builtins-elementwise-math.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,26 @@ void test_builtin_elementwise_log2(float f1, float f2, double d1, double d2,
452452
vf2 = __builtin_elementwise_log2(vf1);
453453
}
454454

455+
void test_builtin_elementwise_pow(float f1, float f2, double d1, double d2,
456+
float4 vf1, float4 vf2) {
457+
458+
// CHECK-LABEL: define void @test_builtin_elementwise_pow(
459+
// CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4
460+
// CHECK: [[F2:%.+]] = load float, ptr %f2.addr, align 4
461+
// CHECK-NEXT: call float @llvm.pow.f32(float [[F1]], float [[F2]])
462+
f2 = __builtin_elementwise_pow(f1, f2);
463+
464+
// CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8
465+
// CHECK: [[D2:%.+]] = load double, ptr %d2.addr, align 8
466+
// CHECK-NEXT: call double @llvm.pow.f64(double [[D1]], double [[D2]])
467+
d2 = __builtin_elementwise_pow(d1, d2);
468+
469+
// CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16
470+
// CHECK: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16
471+
// CHECK-NEXT: call <4 x float> @llvm.pow.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]])
472+
vf2 = __builtin_elementwise_pow(vf1, vf2);
473+
}
474+
455475
void test_builtin_elementwise_roundeven(float f1, float f2, double d1, double d2,
456476
float4 vf1, float4 vf2) {
457477
// CHECK-LABEL: define void @test_builtin_elementwise_roundeven(

clang/test/CodeGen/strictfp-elementwise-bulitins.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,3 +217,12 @@ float4 strict_elementwise_fma(float4 a, float4 b, float4 c) {
217217
return __builtin_elementwise_fma(a, b, c);
218218
}
219219

220+
// CHECK-LABEL: define dso_local noundef <4 x float> @_Z22strict_elementwise_powDv4_fS_
221+
// CHECK-SAME: (<4 x float> noundef [[A:%.*]], <4 x float> noundef [[B:%.*]]) local_unnamed_addr #[[ATTR2]] {
222+
// CHECK-NEXT: entry:
223+
// CHECK-NEXT: [[TMP0:%.*]] = tail call <4 x float> @llvm.pow.v4f32(<4 x float> [[A]], <4 x float> [[B]]) #[[ATTR4]]
224+
// CHECK-NEXT: ret <4 x float> [[TMP0]]
225+
//
226+
float4 strict_elementwise_pow(float4 a, float4 b) {
227+
return __builtin_elementwise_pow(a, b);
228+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %clang_cc1 -triple aarch64 -target-feature +f -target-feature +d \
2+
// RUN: -target-feature +v -target-feature +zfh -target-feature +sve -target-feature +experimental-zvfh \
3+
// RUN: -disable-O0-optnone -o - -fsyntax-only %s -verify
4+
// REQUIRES: aarch64-registered-target
5+
6+
#include <arm_sve.h>
7+
8+
svfloat32_t test_pow_vv_i8mf8(svfloat32_t v) {
9+
10+
return __builtin_elementwise_pow(v, v);
11+
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
12+
}

clang/test/Sema/builtins-elementwise-math.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,31 @@ void test_builtin_elementwise_log2(int i, float f, double d, float4 v, int3 iv,
438438
// expected-error@-1 {{1st argument must be a floating point type (was 'unsigned4' (vector of 4 'unsigned int' values))}}
439439
}
440440

441+
void test_builtin_elementwise_pow(int i, short s, double d, float4 v, int3 iv, unsigned3 uv, int *p) {
442+
i = __builtin_elementwise_pow(p, d);
443+
// expected-error@-1 {{arguments are of different types ('int *' vs 'double')}}
444+
445+
struct Foo foo = __builtin_elementwise_pow(i, i);
446+
// expected-error@-1 {{1st argument must be a floating point type (was 'int')}}
447+
448+
i = __builtin_elementwise_pow(i);
449+
// expected-error@-1 {{too few arguments to function call, expected 2, have 1}}
450+
451+
i = __builtin_elementwise_pow();
452+
// expected-error@-1 {{too few arguments to function call, expected 2, have 0}}
453+
454+
i = __builtin_elementwise_pow(i, i, i);
455+
// expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
456+
457+
i = __builtin_elementwise_pow(v, iv);
458+
// expected-error@-1 {{arguments are of different types ('float4' (vector of 4 'float' values) vs 'int3' (vector of 3 'int' values))}}
459+
460+
i = __builtin_elementwise_pow(uv, iv);
461+
// expected-error@-1 {{arguments are of different types ('unsigned3' (vector of 3 'unsigned int' values) vs 'int3' (vector of 3 'int' values))}}
462+
463+
}
464+
465+
441466
void test_builtin_elementwise_roundeven(int i, float f, double d, float4 v, int3 iv, unsigned u, unsigned4 uv) {
442467

443468
struct Foo s = __builtin_elementwise_roundeven(f);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-feature +d \
2+
// RUN: -target-feature +v -target-feature +zfh -target-feature +experimental-zvfh \
3+
// RUN: -disable-O0-optnone -o - -fsyntax-only %s -verify
4+
// REQUIRES: riscv-registered-target
5+
6+
#include <riscv_vector.h>
7+
8+
9+
vfloat32mf2_t test_pow_vv_i8mf8(vfloat32mf2_t v) {
10+
11+
return __builtin_elementwise_pow(v, v);
12+
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
13+
}

clang/test/SemaCXX/builtins-elementwise-math.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,3 +198,11 @@ void test_builtin_elementwise_fma() {
198198
static_assert(!is_const<decltype(__builtin_elementwise_fma(b, a, c))>::value);
199199
static_assert(!is_const<decltype(__builtin_elementwise_fma(c, c, c))>::value);
200200
}
201+
202+
void test_builtin_elementwise_pow() {
203+
const double a = 2;
204+
double b = 1;
205+
static_assert(!is_const<decltype(__builtin_elementwise_pow(a, b))>::value);
206+
static_assert(!is_const<decltype(__builtin_elementwise_pow(b, a))>::value);
207+
static_assert(!is_const<decltype(__builtin_elementwise_pow(a, a))>::value);
208+
}

0 commit comments

Comments
 (0)