Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit ce04770

Browse files
authored
Merge pull request rust-lang#951 from bjorn3/simd_improvements
Simd improvements
2 parents 66343bf + e02ffdf commit ce04770

File tree

8 files changed

+94
-28
lines changed

8 files changed

+94
-28
lines changed

src/abi/comments.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ pub(super) fn add_local_place_comments<'tcx>(
8282
assert_eq!(local, place_local);
8383
("ssa", Cow::Owned(format!(",var=({}, {})", var1.index(), var2.index())))
8484
}
85+
CPlaceInner::VarLane(_local, _var, _lane) => unreachable!(),
8586
CPlaceInner::Addr(ptr, meta) => {
8687
let meta = if let Some(meta) = meta {
8788
Cow::Owned(format!(",meta={}", meta))

src/abi/pass_mode.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,13 @@ pub(super) fn get_pass_mode<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>)
100100
}
101101

102102
// FIXME implement Vector Abi in a cg_llvm compatible way
103-
Abi::Vector { .. } => PassMode::ByRef { size: Some(layout.size) },
103+
Abi::Vector { .. } => {
104+
if let Some(vector_ty) = crate::intrinsics::clif_vector_type(tcx, layout) {
105+
PassMode::ByVal(vector_ty)
106+
} else {
107+
PassMode::ByRef { size: Some(layout.size) }
108+
}
109+
}
104110

105111
Abi::Aggregate { sized: true } => PassMode::ByRef { size: Some(layout.size) },
106112
Abi::Aggregate { sized: false } => PassMode::ByRef { size: None },

src/common.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,18 @@ fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<types::Typ
6262
pointer_ty(tcx)
6363
}
6464
}
65+
ty::Adt(adt_def, _) if adt_def.repr.simd() => {
66+
let (element, count) = match &tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().abi {
67+
Abi::Vector { element, count } => (element.clone(), *count),
68+
_ => unreachable!(),
69+
};
70+
71+
match scalar_to_clif_type(tcx, element).by(u16::try_from(count).unwrap()) {
72+
// Cranelift currently only implements icmp for 128bit vectors.
73+
Some(vector_ty) if vector_ty.bits() == 128 => vector_ty,
74+
_ => return None,
75+
}
76+
}
6577
ty::Param(_) => bug!("ty param {:?}", ty),
6678
_ => return None,
6779
})
@@ -71,10 +83,12 @@ fn clif_pair_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<(type
7183
Some(match ty.kind {
7284
ty::Tuple(substs) if substs.len() == 2 => {
7385
let mut types = substs.types();
74-
(
75-
clif_type_from_ty(tcx, types.next().unwrap())?,
76-
clif_type_from_ty(tcx, types.next().unwrap())?,
77-
)
86+
let a = clif_type_from_ty(tcx, types.next().unwrap())?;
87+
let b = clif_type_from_ty(tcx, types.next().unwrap())?;
88+
if a.is_vector() || b.is_vector() {
89+
return None;
90+
}
91+
(a, b)
7892
}
7993
ty::RawPtr(TypeAndMut { ty: pointee_ty, mutbl: _ }) | ty::Ref(_, pointee_ty, _) => {
8094
if has_ptr_meta(tcx, pointee_ty) {

src/debuginfo/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,11 @@ fn place_location<'tcx>(
411411

412412
AttributeValue::Exprloc(Expression::new())
413413
}
414+
CPlaceInner::VarLane(_, _, _) => {
415+
// FIXME implement this
416+
417+
AttributeValue::Exprloc(Expression::new())
418+
}
414419
CPlaceInner::Addr(_, _) => {
415420
// FIXME implement this (used by arguments and returns)
416421

src/intrinsics/mod.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,17 +175,15 @@ fn lane_type_and_count<'tcx>(
175175
(lane_layout, lane_count)
176176
}
177177

178-
fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> Option<Type> {
178+
pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> Option<Type> {
179179
let (element, count) = match &layout.abi {
180180
Abi::Vector { element, count } => (element.clone(), *count),
181181
_ => unreachable!(),
182182
};
183183

184184
match scalar_to_clif_type(tcx, element).by(u16::try_from(count).unwrap()) {
185-
// Cranelift currently only implements icmp for 128bit vectors. While 64bit lanes are
186-
// supported, this needs either the `use_sse41_simd` or `use_sse42_simd` target flag
187-
// to be enabled.
188-
Some(vector_ty) if vector_ty.bits() == 128 && vector_ty.lane_type() != types::I64 => Some(vector_ty),
185+
// Cranelift currently only implements icmp for 128bit vectors.
186+
Some(vector_ty) if vector_ty.bits() == 128 => Some(vector_ty),
189187
_ => None,
190188
}
191189
}

src/lib.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,8 @@ fn build_isa(sess: &Session, enable_pic: bool) -> Box<dyn isa::TargetIsa + 'stat
299299
};
300300
flags_builder.set("tls_model", tls_model).unwrap();
301301

302+
flags_builder.set("enable_simd", "true").unwrap();
303+
302304
// FIXME(CraneStation/cranelift#732) fix LICM in presence of jump tables
303305
/*
304306
use rustc_session::config::OptLevel;
@@ -316,9 +318,12 @@ fn build_isa(sess: &Session, enable_pic: bool) -> Box<dyn isa::TargetIsa + 'stat
316318
}*/
317319

318320
let flags = settings::Flags::new(flags_builder);
319-
cranelift_codegen::isa::lookup(target_triple)
320-
.unwrap()
321-
.finish(flags)
321+
322+
let mut isa_builder = cranelift_codegen::isa::lookup(target_triple).unwrap();
323+
// Don't use "haswell", as it implies `has_lzcnt`.macOS CI is still at Ivy Bridge EP, so `lzcnt`
324+
// is interpreted as `bsr`.
325+
isa_builder.enable("nehalem").unwrap();
326+
isa_builder.finish(flags)
322327
}
323328

324329
/// This is the entrypoint for a hot plugged rustc_codegen_cranelift

src/pretty_clif.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,8 @@ pub(crate) fn write_clif_file<'tcx>(
248248
let target_triple = crate::target_triple(tcx.sess);
249249
writeln!(file, "test compile").unwrap();
250250
writeln!(file, "set is_pic").unwrap();
251-
writeln!(file, "target {}", target_triple).unwrap();
251+
writeln!(file, "set enable_simd").unwrap();
252+
writeln!(file, "target {} haswell", target_triple).unwrap();
252253
writeln!(file, "").unwrap();
253254
file.write(clif.as_bytes()).unwrap();
254255
}

src/value_and_place.rs

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ pub(crate) struct CPlace<'tcx> {
272272
pub(crate) enum CPlaceInner {
273273
Var(Local, Variable),
274274
VarPair(Local, Variable, Variable),
275+
VarLane(Local, Variable, u8),
275276
Addr(Pointer, Option<Value>),
276277
}
277278

@@ -374,6 +375,12 @@ impl<'tcx> CPlace<'tcx> {
374375
fx.bcx.set_val_label(val2, cranelift_codegen::ir::ValueLabel::new(var2.index()));
375376
CValue::by_val_pair(val1, val2, layout)
376377
}
378+
CPlaceInner::VarLane(_local, var, lane) => {
379+
let val = fx.bcx.use_var(var);
380+
fx.bcx.set_val_label(val, cranelift_codegen::ir::ValueLabel::new(var.index()));
381+
let val = fx.bcx.ins().extractlane(val, lane);
382+
CValue::by_val(val, layout)
383+
}
377384
CPlaceInner::Addr(ptr, extra) => {
378385
if let Some(extra) = extra {
379386
CValue::by_ref_unsized(ptr, extra, layout)
@@ -395,7 +402,8 @@ impl<'tcx> CPlace<'tcx> {
395402
match self.inner {
396403
CPlaceInner::Addr(ptr, extra) => (ptr, extra),
397404
CPlaceInner::Var(_, _)
398-
| CPlaceInner::VarPair(_, _, _) => bug!("Expected CPlace::Addr, found {:?}", self),
405+
| CPlaceInner::VarPair(_, _, _)
406+
| CPlaceInner::VarLane(_, _, _) => bug!("Expected CPlace::Addr, found {:?}", self),
399407
}
400408
}
401409

@@ -527,6 +535,22 @@ impl<'tcx> CPlace<'tcx> {
527535
transmute_value(fx, var2, data2, dst_ty2);
528536
return;
529537
}
538+
CPlaceInner::VarLane(_local, var, lane) => {
539+
let data = from.load_scalar(fx);
540+
541+
// First get the old vector
542+
let vector = fx.bcx.use_var(var);
543+
fx.bcx.set_val_label(vector, cranelift_codegen::ir::ValueLabel::new(var.index()));
544+
545+
// Next insert the written lane into the vector
546+
let vector = fx.bcx.ins().insertlane(vector, data, lane);
547+
548+
// Finally write the new vector
549+
fx.bcx.set_val_label(vector, cranelift_codegen::ir::ValueLabel::new(var.index()));
550+
fx.bcx.def_var(var, vector);
551+
552+
return;
553+
}
530554
CPlaceInner::Addr(ptr, None) => {
531555
if dst_layout.size == Size::ZERO || dst_layout.abi == Abi::Uninhabited {
532556
return;
@@ -590,20 +614,32 @@ impl<'tcx> CPlace<'tcx> {
590614
field: mir::Field,
591615
) -> CPlace<'tcx> {
592616
let layout = self.layout();
593-
if let CPlaceInner::VarPair(local, var1, var2) = self.inner {
594-
let layout = layout.field(&*fx, field.index());
595-
596-
match field.as_u32() {
597-
0 => return CPlace {
598-
inner: CPlaceInner::Var(local, var1),
599-
layout,
600-
},
601-
1 => return CPlace {
602-
inner: CPlaceInner::Var(local, var2),
603-
layout,
604-
},
605-
_ => unreachable!("field should be 0 or 1"),
617+
618+
match self.inner {
619+
CPlaceInner::Var(local, var) => {
620+
if let Abi::Vector { .. } = layout.abi {
621+
return CPlace {
622+
inner: CPlaceInner::VarLane(local, var, field.as_u32().try_into().unwrap()),
623+
layout: layout.field(fx, field.as_u32().try_into().unwrap()),
624+
};
625+
}
626+
}
627+
CPlaceInner::VarPair(local, var1, var2) => {
628+
let layout = layout.field(&*fx, field.index());
629+
630+
match field.as_u32() {
631+
0 => return CPlace {
632+
inner: CPlaceInner::Var(local, var1),
633+
layout,
634+
},
635+
1 => return CPlace {
636+
inner: CPlaceInner::Var(local, var2),
637+
layout,
638+
},
639+
_ => unreachable!("field should be 0 or 1"),
640+
}
606641
}
642+
_ => {}
607643
}
608644

609645
let (base, extra) = self.to_ptr_maybe_unsized();

0 commit comments

Comments
 (0)