Skip to content

Commit

Permalink
Improve codegen for arrays of repeated enums
Browse files Browse the repository at this point in the history
  • Loading branch information
clubby789 committed Nov 14, 2022
1 parent e631891 commit c1b1d73
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 9 deletions.
18 changes: 18 additions & 0 deletions compiler/rustc_codegen_llvm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,24 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
count: u64,
dest: PlaceRef<'tcx, &'ll Value>,
) -> Self {
if let OperandValue::Pair(mut v1, mut v2) = cg_elem.val && count < 1024 {
v1 = self.from_immediate(v1);
v2 = self.from_immediate(v2);
let ty = self.cx().val_ty(v1);
// Create a vector of size 2*count and store it in one instruction
if ty == self.cx().val_ty(v2) {
let count = count * 2;
let vec = unsafe { llvm::LLVMGetUndef(self.type_vector(ty, count as u64)) };
let vec = (0..count as usize).fold(vec, |acc, x| {
let elt = [v1, v2][x % 2];
self.insert_element(acc, elt, self.cx.const_i32(x as i32))
});
let vec = OperandRef::from_immediate_or_packed_pair(&mut self, vec, dest.layout);
vec.val.store(&mut self, dest);
return self;
}
}

let zero = self.const_usize(0);
let count = self.const_usize(count);
let start = dest.project_index(&mut self, zero).llval;
Expand Down
10 changes: 1 addition & 9 deletions compiler/rustc_codegen_ssa/src/mir/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::Ty;
use rustc_target::abi::{Abi, Align, Size};

use std::fmt;

/// The representation of a Rust value. The enum variant is in fact
/// uniquely determined by the value's type, but is kept as a
/// safety check.
Expand All @@ -38,7 +36,7 @@ pub enum OperandValue<V> {
/// to avoid nasty edge cases. In particular, using `Builder::store`
/// directly is sure to cause problems -- use `OperandRef::store`
/// instead.
#[derive(Copy, Clone)]
#[derive(Copy, Clone, Debug)]
pub struct OperandRef<'tcx, V> {
// The value.
pub val: OperandValue<V>,
Expand All @@ -47,12 +45,6 @@ pub struct OperandRef<'tcx, V> {
pub layout: TyAndLayout<'tcx>,
}

impl<V: CodegenObject> fmt::Debug for OperandRef<'_, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "OperandRef({:?} @ {:?})", self.val, self.layout)
}
}

impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
pub fn new_zst<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
bx: &mut Bx,
Expand Down
19 changes: 19 additions & 0 deletions src/test/codegen/enum-repeat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// compile-flags: -O

#![crate_type = "lib"]

// CHECK-LABEL: @none_repeat
#[no_mangle]
pub fn none_repeat() -> [Option<u8>; 64] {
// CHECK: store <128 x i8>
// CHECK-NEXT: ret void
[None; 64]
}

// CHECK-LABEL: @some_repeat
#[no_mangle]
pub fn some_repeat() -> [Option<u8>; 64] {
// CHECK: store <128 x i8>
// CHECK-NEXT: ret void
[Some(0); 64]
}

0 comments on commit c1b1d73

Please sign in to comment.