about summary refs log tree commit diff
path: root/src/rustllvm/RustWrapper.cpp
diff options
context:
space:
mode:
authorkennytm <kennytm@gmail.com>2018-03-17 17:20:43 +0800
committerGitHub <noreply@github.com>2018-03-17 17:20:43 +0800
commitb724c6937462d19cb4e45431c2875f4ee051f6d3 (patch)
tree9e3886ece108b6ffb1e23001f047b543811f6060 /src/rustllvm/RustWrapper.cpp
parentc9d06a4a4e07e59c9d5099325a66242321f7c392 (diff)
parent06148cb4b0f83ecec70148de8b589644b618e66f (diff)
downloadrust-b724c6937462d19cb4e45431c2875f4ee051f6d3.tar.gz
rust-b724c6937462d19cb4e45431c2875f4ee051f6d3.zip
Rollup merge of #48983 - gnzlbg:red, r=alexcrichton
add intrinsics for portable packed simd vector reductions

Adds the following portable vector reduction intrinsics:

* fn simd_reduce_add<T, U>(x: T) -> U;
* fn simd_reduce_mul<T, U>(x: T) -> U;
* fn simd_reduce_min<T, U>(x: T) -> U;
* fn simd_reduce_max<T, U>(x: T) -> U;
* fn simd_reduce_and<T, U>(x: T) -> U;
* fn simd_reduce_or<T, U>(x: T) -> U;
* fn simd_reduce_xor<T, U>(x: T) -> U;

I've also added:

* fn simd_reduce_all<T>(x: T) -> bool;
* fn simd_reduce_any<T>(x: T) -> bool;

These produce better code that what we are currently producing in `stdsimd`, but the code is still not optimal due to this LLVM bug:  https://bugs.llvm.org/show_bug.cgi?id=36702

r? @alexcrichton
Diffstat (limited to 'src/rustllvm/RustWrapper.cpp')
-rw-r--r--src/rustllvm/RustWrapper.cpp97
1 files changed, 97 insertions, 0 deletions
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 27d5496f576..a5644d6f9e2 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -21,6 +21,8 @@
 
 #if LLVM_VERSION_GE(5, 0)
 #include "llvm/ADT/Optional.h"
+#else
+#include <cstdlib>
 #endif
 
 //===----------------------------------------------------------------------===
@@ -1395,3 +1397,98 @@ LLVMRustModuleCost(LLVMModuleRef M) {
   auto f = unwrap(M)->functions();
   return std::distance(std::begin(f), std::end(f));
 }
+
+// Vector reductions:
+#if LLVM_VERSION_GE(5, 0)
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
+    return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
+    return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
+    return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
+    return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
+    return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
+    return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
+    return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
+    return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
+    return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
+   return wrap(unwrap(B)->CreateFPMinReduce(unwrap(Src), NoNaN));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
+  return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN));
+}
+
+#else
+
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFMul(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceAdd(LLVMBuilderRef, LLVMValueRef) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceMul(LLVMBuilderRef, LLVMValueRef) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceAnd(LLVMBuilderRef, LLVMValueRef) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceOr(LLVMBuilderRef, LLVMValueRef) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceXor(LLVMBuilderRef, LLVMValueRef) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceMin(LLVMBuilderRef, LLVMValueRef, bool) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceMax(LLVMBuilderRef, LLVMValueRef, bool) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFMin(LLVMBuilderRef, LLVMValueRef, bool) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFMax(LLVMBuilderRef, LLVMValueRef, bool) {
+  return nullptr;
+}
+#endif