Skip to content

Commit c1b1d73

Browse files
committed
Improve codegen for arrays of repeated enums
1 parent e631891 commit c1b1d73

File tree

3 files changed

+38
-9
lines changed

3 files changed

+38
-9
lines changed

compiler/rustc_codegen_llvm/src/builder.rs

+18
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,24 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
561561
count: u64,
562562
dest: PlaceRef<'tcx, &'ll Value>,
563563
) -> Self {
564+
if let OperandValue::Pair(mut v1, mut v2) = cg_elem.val && count < 1024 {
565+
v1 = self.from_immediate(v1);
566+
v2 = self.from_immediate(v2);
567+
let ty = self.cx().val_ty(v1);
568+
// Create a vector of size 2*count and store it in one instruction
569+
if ty == self.cx().val_ty(v2) {
570+
let count = count * 2;
571+
let vec = unsafe { llvm::LLVMGetUndef(self.type_vector(ty, count as u64)) };
572+
let vec = (0..count as usize).fold(vec, |acc, x| {
573+
let elt = [v1, v2][x % 2];
574+
self.insert_element(acc, elt, self.cx.const_i32(x as i32))
575+
});
576+
let vec = OperandRef::from_immediate_or_packed_pair(&mut self, vec, dest.layout);
577+
vec.val.store(&mut self, dest);
578+
return self;
579+
}
580+
}
581+
564582
let zero = self.const_usize(0);
565583
let count = self.const_usize(count);
566584
let start = dest.project_index(&mut self, zero).llval;

compiler/rustc_codegen_ssa/src/mir/operand.rs

+1-9
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
1212
use rustc_middle::ty::Ty;
1313
use rustc_target::abi::{Abi, Align, Size};
1414

15-
use std::fmt;
16-
1715
/// The representation of a Rust value. The enum variant is in fact
1816
/// uniquely determined by the value's type, but is kept as a
1917
/// safety check.
@@ -38,7 +36,7 @@ pub enum OperandValue<V> {
3836
/// to avoid nasty edge cases. In particular, using `Builder::store`
3937
/// directly is sure to cause problems -- use `OperandRef::store`
4038
/// instead.
41-
#[derive(Copy, Clone)]
39+
#[derive(Copy, Clone, Debug)]
4240
pub struct OperandRef<'tcx, V> {
4341
// The value.
4442
pub val: OperandValue<V>,
@@ -47,12 +45,6 @@ pub struct OperandRef<'tcx, V> {
4745
pub layout: TyAndLayout<'tcx>,
4846
}
4947

50-
impl<V: CodegenObject> fmt::Debug for OperandRef<'_, V> {
51-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52-
write!(f, "OperandRef({:?} @ {:?})", self.val, self.layout)
53-
}
54-
}
55-
5648
impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
5749
pub fn new_zst<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
5850
bx: &mut Bx,

src/test/codegen/enum-repeat.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// compile-flags: -O
2+
3+
#![crate_type = "lib"]
4+
5+
// CHECK-LABEL: @none_repeat
6+
#[no_mangle]
7+
pub fn none_repeat() -> [Option<u8>; 64] {
8+
// CHECK: store <128 x i8>
9+
// CHECK-NEXT: ret void
10+
[None; 64]
11+
}
12+
13+
// CHECK-LABEL: @some_repeat
14+
#[no_mangle]
15+
pub fn some_repeat() -> [Option<u8>; 64] {
16+
// CHECK: store <128 x i8>
17+
// CHECK-NEXT: ret void
18+
[Some(0); 64]
19+
}

0 commit comments

Comments
 (0)