Skip to content

add intrinsics for portable packed simd vector reductions #48983

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Mar 17, 2018
42 changes: 42 additions & 0 deletions src/librustc_llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,7 @@ extern "C" {
pub fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong;
pub fn LLVMRustConstInt128Get(ConstantVal: ValueRef, SExt: bool,
high: *mut u64, low: *mut u64) -> bool;
pub fn LLVMConstRealGetDouble (ConstantVal: ValueRef, losesInfo: *mut Bool) -> f64;


// Operations on composite constants
Expand Down Expand Up @@ -1201,6 +1202,46 @@ extern "C" {
Name: *const c_char)
-> ValueRef;

pub fn LLVMRustBuildVectorReduceFAdd(B: BuilderRef,
Acc: ValueRef,
Src: ValueRef)
-> ValueRef;
pub fn LLVMRustBuildVectorReduceFMul(B: BuilderRef,
Acc: ValueRef,
Src: ValueRef)
-> ValueRef;
pub fn LLVMRustBuildVectorReduceAdd(B: BuilderRef,
Src: ValueRef)
-> ValueRef;
pub fn LLVMRustBuildVectorReduceMul(B: BuilderRef,
Src: ValueRef)
-> ValueRef;
pub fn LLVMRustBuildVectorReduceAnd(B: BuilderRef,
Src: ValueRef)
-> ValueRef;
pub fn LLVMRustBuildVectorReduceOr(B: BuilderRef,
Src: ValueRef)
-> ValueRef;
pub fn LLVMRustBuildVectorReduceXor(B: BuilderRef,
Src: ValueRef)
-> ValueRef;
pub fn LLVMRustBuildVectorReduceMin(B: BuilderRef,
Src: ValueRef,
IsSigned: bool)
-> ValueRef;
pub fn LLVMRustBuildVectorReduceMax(B: BuilderRef,
Src: ValueRef,
IsSigned: bool)
-> ValueRef;
pub fn LLVMRustBuildVectorReduceFMin(B: BuilderRef,
Src: ValueRef,
IsNaN: bool)
-> ValueRef;
pub fn LLVMRustBuildVectorReduceFMax(B: BuilderRef,
Src: ValueRef,
IsNaN: bool)
-> ValueRef;

pub fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef;
pub fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef;
pub fn LLVMBuildPtrDiff(B: BuilderRef,
Expand Down Expand Up @@ -1567,6 +1608,7 @@ extern "C" {
pub fn LLVMRustWriteValueToString(value_ref: ValueRef, s: RustStringRef);

pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef;
pub fn LLVMIsAConstantFP(value_ref: ValueRef) -> ValueRef;

pub fn LLVMRustPassKind(Pass: PassRef) -> PassKind;
pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef;
Expand Down
141 changes: 141 additions & 0 deletions src/librustc_trans/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,147 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}

pub fn vector_reduce_fadd_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef {
self.count_insn("vector.reduce.fadd_fast");
unsafe {
// FIXME: add a non-fast math version once
// https://bugs.llvm.org/show_bug.cgi?id=36732
// is fixed.
let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src);
if instr.is_null() {
bug!("LLVMRustBuildVectorReduceFAdd is not available in LLVM version < 5.0");
}
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
instr
}
}
pub fn vector_reduce_fmul_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef {
self.count_insn("vector.reduce.fmul_fast");
unsafe {
// FIXME: add a non-fast math version once
// https://bugs.llvm.org/show_bug.cgi?id=36732
// is fixed.
let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src);
if instr.is_null() {
bug!("LLVMRustBuildVectorReduceFMul is not available in LLVM version < 5.0");
}
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
instr
}
}
pub fn vector_reduce_add(&self, src: ValueRef) -> ValueRef {
self.count_insn("vector.reduce.add");
unsafe {
let instr = llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src);
if instr.is_null() {
bug!("LLVMRustBuildVectorReduceAdd is not available in LLVM version < 5.0");
}
instr
}
}
pub fn vector_reduce_mul(&self, src: ValueRef) -> ValueRef {
self.count_insn("vector.reduce.mul");
unsafe {
let instr = llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src);
if instr.is_null() {
bug!("LLVMRustBuildVectorReduceMul is not available in LLVM version < 5.0");
}
instr
}
}
pub fn vector_reduce_and(&self, src: ValueRef) -> ValueRef {
self.count_insn("vector.reduce.and");
unsafe {
let instr = llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src);
if instr.is_null() {
bug!("LLVMRustBuildVectorReduceAnd is not available in LLVM version < 5.0");
}
instr
}
}
pub fn vector_reduce_or(&self, src: ValueRef) -> ValueRef {
self.count_insn("vector.reduce.or");
unsafe {
let instr = llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src);
if instr.is_null() {
bug!("LLVMRustBuildVectorReduceOr is not available in LLVM version < 5.0");
}
instr
}
}
pub fn vector_reduce_xor(&self, src: ValueRef) -> ValueRef {
self.count_insn("vector.reduce.xor");
unsafe {
let instr = llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src);
if instr.is_null() {
bug!("LLVMRustBuildVectorReduceXor is not available in LLVM version < 5.0");
}
instr
}
}
pub fn vector_reduce_fmin(&self, src: ValueRef) -> ValueRef {
self.count_insn("vector.reduce.fmin");
unsafe {
let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, true);
if instr.is_null() {
bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0");
}
instr
}
}
pub fn vector_reduce_fmax(&self, src: ValueRef) -> ValueRef {
self.count_insn("vector.reduce.fmax");
unsafe {
let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, true);
if instr.is_null() {
bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0");
}
instr
}
}
pub fn vector_reduce_fmin_fast(&self, src: ValueRef) -> ValueRef {
self.count_insn("vector.reduce.fmin_fast");
unsafe {
let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, false);
if instr.is_null() {
bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0");
}
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
instr
}
}
pub fn vector_reduce_fmax_fast(&self, src: ValueRef) -> ValueRef {
self.count_insn("vector.reduce.fmax_fast");
unsafe {
let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, false);
if instr.is_null() {
bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0");
}
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
instr
}
}
pub fn vector_reduce_min(&self, src: ValueRef, is_signed: bool) -> ValueRef {
self.count_insn("vector.reduce.min");
unsafe {
let instr = llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed);
if instr.is_null() {
bug!("LLVMRustBuildVectorReduceMin is not available in LLVM version < 5.0");
}
instr
}
}
pub fn vector_reduce_max(&self, src: ValueRef, is_signed: bool) -> ValueRef {
self.count_insn("vector.reduce.max");
unsafe {
let instr = llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed);
if instr.is_null() {
bug!("LLVMRustBuildVectorReduceMax is not available in LLVM version < 5.0");
}
instr
}
}

pub fn extract_value(&self, agg_val: ValueRef, idx: u64) -> ValueRef {
self.count_insn("extractvalue");
assert_eq!(idx as c_uint as u64, idx);
Expand Down
20 changes: 20 additions & 0 deletions src/librustc_trans/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,19 @@ pub fn const_get_elt(v: ValueRef, idx: u64) -> ValueRef {
}
}

pub fn const_get_real(v: ValueRef) -> Option<(f64, bool)> {
unsafe {
if is_const_real(v) {
let mut loses_info: llvm::Bool = ::std::mem::uninitialized();
let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info as *mut llvm::Bool);
let loses_info = if loses_info == 1 { true } else { false };
Some((r, loses_info))
} else {
None
}
}
}

pub fn const_to_uint(v: ValueRef) -> u64 {
unsafe {
llvm::LLVMConstIntGetZExtValue(v)
Expand All @@ -282,6 +295,13 @@ pub fn is_const_integral(v: ValueRef) -> bool {
}
}

pub fn is_const_real(v: ValueRef) -> bool {
unsafe {
!llvm::LLVMIsAConstantFP(v).is_null()
}
}


#[inline]
fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
((hi as u128) << 64) | (lo as u128)
Expand Down
Loading