bob80905 created this revision.
Herald added subscribers: luke, Anastasia, frasercrmck, luismarques, apazos, 
sameer.abuasal, s.egerton, Jim, jocewei, PkmX, the_o, brucehoult, 
MartinMosbeck, rogfer01, edward-jones, zzheng, jrtc27, niosHD, sabuasal, 
simoncook, johnrusso, rbar, asb.
Herald added a project: All.
bob80905 requested review of this revision.
Herald added subscribers: cfe-commits, wangpc.
Herald added a project: clang.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D153310

Files:
  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/Sema/aarch64-sve-vector-pow-ops.c
  clang/test/Sema/builtins-elementwise-math.c
  clang/test/Sema/riscv-sve-vector-pow-ops.c
  clang/test/SemaCXX/builtins-elementwise-math.cpp

Index: clang/test/SemaCXX/builtins-elementwise-math.cpp
===================================================================
--- clang/test/SemaCXX/builtins-elementwise-math.cpp
+++ clang/test/SemaCXX/builtins-elementwise-math.cpp
@@ -108,3 +108,11 @@
   static_assert(!is_const<decltype(__builtin_elementwise_log2(a))>::value);
   static_assert(!is_const<decltype(__builtin_elementwise_log2(b))>::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);
+}
Index: clang/test/Sema/riscv-sve-vector-pow-ops.c
===================================================================
--- /dev/null
+++ 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}}
+}
\ No newline at end of file
Index: clang/test/Sema/builtins-elementwise-math.c
===================================================================
--- clang/test/Sema/builtins-elementwise-math.c
+++ 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);
Index: clang/test/Sema/aarch64-sve-vector-pow-ops.c
===================================================================
--- /dev/null
+++ 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}}
+}
\ No newline at end of file
Index: clang/test/CodeGen/builtins-elementwise-math.c
===================================================================
--- clang/test/CodeGen/builtins-elementwise-math.c
+++ 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(
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ 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:
Index: clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ 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"));
Index: clang/include/clang/Basic/Builtins.def
===================================================================
--- clang/include/clang/Basic/Builtins.def
+++ 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")
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ 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
 ------------
Index: clang/docs/LanguageExtensions.rst
===================================================================
--- clang/docs/LanguageExtensions.rst
+++ 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
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to