Copy 1-element arrays as scalars, not vectors

For `[T; 1]` it's silly to copy as `<1 x T>` when we can just copy as `T`.
This commit is contained in:
Scott McMurray 2023-10-06 01:17:09 -07:00
parent 579be69de9
commit ae9cec5839
4 changed files with 80 additions and 1 deletions

View File

@ -397,7 +397,12 @@ fn scalar_copy_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Option<&'a Type
// extracts all the individual values. // extracts all the individual values.
let ety = element.llvm_type(cx); let ety = element.llvm_type(cx);
return Some(cx.type_vector(ety, *count)); if *count == 1 {
// Emitting `<1 x T>` would be silly; just use the scalar.
return Some(ety);
} else {
return Some(cx.type_vector(ety, *count));
}
} }
// FIXME: The above only handled integer arrays; surely more things // FIXME: The above only handled integer arrays; surely more things

View File

@ -0,0 +1,19 @@
// assembly-output: emit-asm
// compile-flags: --crate-type=lib -O -C llvm-args=-x86-asm-syntax=intel
// only-x86_64
// ignore-sgx
// Depending on various codegen choices, this might end up copying
// a `<2 x i8>`, an `i16`, or two `i8`s.
// Regardless of those choices, make sure the instructions use (2-byte) words.
// CHECK-LABEL: array_copy_2_elements:
#[no_mangle]
pub fn array_copy_2_elements(a: &[u8; 2], p: &mut [u8; 2]) {
// CHECK-NOT: byte
// CHECK-NOT: mov
// CHECK: mov{{.+}}, word ptr
// CHECK-NEXT: mov word ptr
// CHECK-NEXT: ret
*p = *a;
}

View File

@ -32,3 +32,25 @@
// CHECK: store <4 x i8> %[[TEMP2]], ptr %p, align 1 // CHECK: store <4 x i8> %[[TEMP2]], ptr %p, align 1
*p = *a; *p = *a;
} }
// CHECK-LABEL: @array_copy_1_element
#[no_mangle]
pub fn array_copy_1_element(a: &[u8; 1], p: &mut [u8; 1]) {
// CHECK: %[[LOCAL:.+]] = alloca [1 x i8], align 1
// CHECK: %[[TEMP1:.+]] = load i8, ptr %a, align 1
// CHECK: store i8 %[[TEMP1]], ptr %[[LOCAL]], align 1
// CHECK: %[[TEMP2:.+]] = load i8, ptr %[[LOCAL]], align 1
// CHECK: store i8 %[[TEMP2]], ptr %p, align 1
*p = *a;
}
// CHECK-LABEL: @array_copy_2_elements
#[no_mangle]
pub fn array_copy_2_elements(a: &[u8; 2], p: &mut [u8; 2]) {
// CHECK: %[[LOCAL:.+]] = alloca [2 x i8], align 1
// CHECK: %[[TEMP1:.+]] = load <2 x i8>, ptr %a, align 1
// CHECK: store <2 x i8> %[[TEMP1]], ptr %[[LOCAL]], align 1
// CHECK: %[[TEMP2:.+]] = load <2 x i8>, ptr %[[LOCAL]], align 1
// CHECK: store <2 x i8> %[[TEMP2]], ptr %p, align 1
*p = *a;
}

View File

@ -0,0 +1,33 @@
// compile-flags: -O
#![crate_type = "lib"]
// CHECK-LABEL: @array_copy_1_element
#[no_mangle]
pub fn array_copy_1_element(a: &[u8; 1], p: &mut [u8; 1]) {
// CHECK-NOT: alloca
// CHECK: %[[TEMP:.+]] = load i8, ptr %a, align 1
// CHECK: store i8 %[[TEMP]], ptr %p, align 1
// CHECK: ret
*p = *a;
}
// CHECK-LABEL: @array_copy_2_elements
#[no_mangle]
pub fn array_copy_2_elements(a: &[u8; 2], p: &mut [u8; 2]) {
// CHECK-NOT: alloca
// CHECK: %[[TEMP:.+]] = load <2 x i8>, ptr %a, align 1
// CHECK: store <2 x i8> %[[TEMP]], ptr %p, align 1
// CHECK: ret
*p = *a;
}
// CHECK-LABEL: @array_copy_4_elements
#[no_mangle]
pub fn array_copy_4_elements(a: &[u8; 4], p: &mut [u8; 4]) {
// CHECK-NOT: alloca
// CHECK: %[[TEMP:.+]] = load <4 x i8>, ptr %a, align 1
// CHECK: store <4 x i8> %[[TEMP]], ptr %p, align 1
// CHECK: ret
*p = *a;
}