Skip to content

Commit b724c69

Browse files
authored
Rollup merge of rust-lang#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
2 parents c9d06a4 + 06148cb commit b724c69

File tree

8 files changed

+728
-3
lines changed

8 files changed

+728
-3
lines changed

Diff for: src/librustc_llvm/ffi.rs

+42
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,7 @@ extern "C" {
621621
pub fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong;
622622
pub fn LLVMRustConstInt128Get(ConstantVal: ValueRef, SExt: bool,
623623
high: *mut u64, low: *mut u64) -> bool;
624+
pub fn LLVMConstRealGetDouble (ConstantVal: ValueRef, losesInfo: *mut Bool) -> f64;
624625

625626

626627
// Operations on composite constants
@@ -1201,6 +1202,46 @@ extern "C" {
12011202
Name: *const c_char)
12021203
-> ValueRef;
12031204

1205+
pub fn LLVMRustBuildVectorReduceFAdd(B: BuilderRef,
1206+
Acc: ValueRef,
1207+
Src: ValueRef)
1208+
-> ValueRef;
1209+
pub fn LLVMRustBuildVectorReduceFMul(B: BuilderRef,
1210+
Acc: ValueRef,
1211+
Src: ValueRef)
1212+
-> ValueRef;
1213+
pub fn LLVMRustBuildVectorReduceAdd(B: BuilderRef,
1214+
Src: ValueRef)
1215+
-> ValueRef;
1216+
pub fn LLVMRustBuildVectorReduceMul(B: BuilderRef,
1217+
Src: ValueRef)
1218+
-> ValueRef;
1219+
pub fn LLVMRustBuildVectorReduceAnd(B: BuilderRef,
1220+
Src: ValueRef)
1221+
-> ValueRef;
1222+
pub fn LLVMRustBuildVectorReduceOr(B: BuilderRef,
1223+
Src: ValueRef)
1224+
-> ValueRef;
1225+
pub fn LLVMRustBuildVectorReduceXor(B: BuilderRef,
1226+
Src: ValueRef)
1227+
-> ValueRef;
1228+
pub fn LLVMRustBuildVectorReduceMin(B: BuilderRef,
1229+
Src: ValueRef,
1230+
IsSigned: bool)
1231+
-> ValueRef;
1232+
pub fn LLVMRustBuildVectorReduceMax(B: BuilderRef,
1233+
Src: ValueRef,
1234+
IsSigned: bool)
1235+
-> ValueRef;
1236+
pub fn LLVMRustBuildVectorReduceFMin(B: BuilderRef,
1237+
Src: ValueRef,
1238+
IsNaN: bool)
1239+
-> ValueRef;
1240+
pub fn LLVMRustBuildVectorReduceFMax(B: BuilderRef,
1241+
Src: ValueRef,
1242+
IsNaN: bool)
1243+
-> ValueRef;
1244+
12041245
pub fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef;
12051246
pub fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef;
12061247
pub fn LLVMBuildPtrDiff(B: BuilderRef,
@@ -1567,6 +1608,7 @@ extern "C" {
15671608
pub fn LLVMRustWriteValueToString(value_ref: ValueRef, s: RustStringRef);
15681609

15691610
pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef;
1611+
pub fn LLVMIsAConstantFP(value_ref: ValueRef) -> ValueRef;
15701612

15711613
pub fn LLVMRustPassKind(Pass: PassRef) -> PassKind;
15721614
pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef;

Diff for: src/librustc_trans/builder.rs

+141
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,147 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
955955
}
956956
}
957957

958+
pub fn vector_reduce_fadd_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef {
959+
self.count_insn("vector.reduce.fadd_fast");
960+
unsafe {
961+
// FIXME: add a non-fast math version once
962+
// https://bugs.llvm.org/show_bug.cgi?id=36732
963+
// is fixed.
964+
let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src);
965+
if instr.is_null() {
966+
bug!("LLVMRustBuildVectorReduceFAdd is not available in LLVM version < 5.0");
967+
}
968+
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
969+
instr
970+
}
971+
}
972+
pub fn vector_reduce_fmul_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef {
973+
self.count_insn("vector.reduce.fmul_fast");
974+
unsafe {
975+
// FIXME: add a non-fast math version once
976+
// https://bugs.llvm.org/show_bug.cgi?id=36732
977+
// is fixed.
978+
let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src);
979+
if instr.is_null() {
980+
bug!("LLVMRustBuildVectorReduceFMul is not available in LLVM version < 5.0");
981+
}
982+
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
983+
instr
984+
}
985+
}
986+
pub fn vector_reduce_add(&self, src: ValueRef) -> ValueRef {
987+
self.count_insn("vector.reduce.add");
988+
unsafe {
989+
let instr = llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src);
990+
if instr.is_null() {
991+
bug!("LLVMRustBuildVectorReduceAdd is not available in LLVM version < 5.0");
992+
}
993+
instr
994+
}
995+
}
996+
pub fn vector_reduce_mul(&self, src: ValueRef) -> ValueRef {
997+
self.count_insn("vector.reduce.mul");
998+
unsafe {
999+
let instr = llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src);
1000+
if instr.is_null() {
1001+
bug!("LLVMRustBuildVectorReduceMul is not available in LLVM version < 5.0");
1002+
}
1003+
instr
1004+
}
1005+
}
1006+
pub fn vector_reduce_and(&self, src: ValueRef) -> ValueRef {
1007+
self.count_insn("vector.reduce.and");
1008+
unsafe {
1009+
let instr = llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src);
1010+
if instr.is_null() {
1011+
bug!("LLVMRustBuildVectorReduceAnd is not available in LLVM version < 5.0");
1012+
}
1013+
instr
1014+
}
1015+
}
1016+
pub fn vector_reduce_or(&self, src: ValueRef) -> ValueRef {
1017+
self.count_insn("vector.reduce.or");
1018+
unsafe {
1019+
let instr = llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src);
1020+
if instr.is_null() {
1021+
bug!("LLVMRustBuildVectorReduceOr is not available in LLVM version < 5.0");
1022+
}
1023+
instr
1024+
}
1025+
}
1026+
pub fn vector_reduce_xor(&self, src: ValueRef) -> ValueRef {
1027+
self.count_insn("vector.reduce.xor");
1028+
unsafe {
1029+
let instr = llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src);
1030+
if instr.is_null() {
1031+
bug!("LLVMRustBuildVectorReduceXor is not available in LLVM version < 5.0");
1032+
}
1033+
instr
1034+
}
1035+
}
1036+
pub fn vector_reduce_fmin(&self, src: ValueRef) -> ValueRef {
1037+
self.count_insn("vector.reduce.fmin");
1038+
unsafe {
1039+
let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, true);
1040+
if instr.is_null() {
1041+
bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0");
1042+
}
1043+
instr
1044+
}
1045+
}
1046+
pub fn vector_reduce_fmax(&self, src: ValueRef) -> ValueRef {
1047+
self.count_insn("vector.reduce.fmax");
1048+
unsafe {
1049+
let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, true);
1050+
if instr.is_null() {
1051+
bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0");
1052+
}
1053+
instr
1054+
}
1055+
}
1056+
pub fn vector_reduce_fmin_fast(&self, src: ValueRef) -> ValueRef {
1057+
self.count_insn("vector.reduce.fmin_fast");
1058+
unsafe {
1059+
let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, false);
1060+
if instr.is_null() {
1061+
bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0");
1062+
}
1063+
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
1064+
instr
1065+
}
1066+
}
1067+
pub fn vector_reduce_fmax_fast(&self, src: ValueRef) -> ValueRef {
1068+
self.count_insn("vector.reduce.fmax_fast");
1069+
unsafe {
1070+
let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, false);
1071+
if instr.is_null() {
1072+
bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0");
1073+
}
1074+
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
1075+
instr
1076+
}
1077+
}
1078+
pub fn vector_reduce_min(&self, src: ValueRef, is_signed: bool) -> ValueRef {
1079+
self.count_insn("vector.reduce.min");
1080+
unsafe {
1081+
let instr = llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed);
1082+
if instr.is_null() {
1083+
bug!("LLVMRustBuildVectorReduceMin is not available in LLVM version < 5.0");
1084+
}
1085+
instr
1086+
}
1087+
}
1088+
pub fn vector_reduce_max(&self, src: ValueRef, is_signed: bool) -> ValueRef {
1089+
self.count_insn("vector.reduce.max");
1090+
unsafe {
1091+
let instr = llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed);
1092+
if instr.is_null() {
1093+
bug!("LLVMRustBuildVectorReduceMax is not available in LLVM version < 5.0");
1094+
}
1095+
instr
1096+
}
1097+
}
1098+
9581099
pub fn extract_value(&self, agg_val: ValueRef, idx: u64) -> ValueRef {
9591100
self.count_insn("extractvalue");
9601101
assert_eq!(idx as c_uint as u64, idx);

Diff for: src/librustc_trans/common.rs

+20
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,19 @@ pub fn const_get_elt(v: ValueRef, idx: u64) -> ValueRef {
269269
}
270270
}
271271

272+
pub fn const_get_real(v: ValueRef) -> Option<(f64, bool)> {
273+
unsafe {
274+
if is_const_real(v) {
275+
let mut loses_info: llvm::Bool = ::std::mem::uninitialized();
276+
let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info as *mut llvm::Bool);
277+
let loses_info = if loses_info == 1 { true } else { false };
278+
Some((r, loses_info))
279+
} else {
280+
None
281+
}
282+
}
283+
}
284+
272285
pub fn const_to_uint(v: ValueRef) -> u64 {
273286
unsafe {
274287
llvm::LLVMConstIntGetZExtValue(v)
@@ -281,6 +294,13 @@ pub fn is_const_integral(v: ValueRef) -> bool {
281294
}
282295
}
283296

297+
pub fn is_const_real(v: ValueRef) -> bool {
298+
unsafe {
299+
!llvm::LLVMIsAConstantFP(v).is_null()
300+
}
301+
}
302+
303+
284304
#[inline]
285305
fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
286306
((hi as u128) << 64) | (lo as u128)

0 commit comments

Comments
 (0)