Skip to content

Commit a2d7c81

Browse files
committed
Auto merge of #135258 - oli-obk:push-ktzskvxuwnlt, r=saethlin
Use llvm.memset.p0i8.* to initialize all same-bytes arrays Similar to #43488 debug builds can now handle `0x0101_u16` and other multi-byte scalars that have all the same bytes (instead of special casing just `0`)
2 parents 7648efa + 65b01cb commit a2d7c81

File tree

2 files changed

+47
-7
lines changed

2 files changed

+47
-7
lines changed

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+21-7
Original file line numberDiff line numberDiff line change
@@ -93,23 +93,37 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
9393
return;
9494
}
9595

96-
if let OperandValue::Immediate(v) = cg_elem.val {
96+
let try_init_all_same = |bx: &mut Bx, v| {
9797
let start = dest.val.llval;
9898
let size = bx.const_usize(dest.layout.size.bytes());
9999

100-
// Use llvm.memset.p0i8.* to initialize all zero arrays
101-
if bx.cx().const_to_opt_u128(v, false) == Some(0) {
102-
let fill = bx.cx().const_u8(0);
103-
bx.memset(start, fill, size, dest.val.align, MemFlags::empty());
104-
return;
100+
// Use llvm.memset.p0i8.* to initialize all same byte arrays
101+
if let Some(int) = bx.cx().const_to_opt_u128(v, false) {
102+
let bytes = &int.to_le_bytes()[..cg_elem.layout.size.bytes_usize()];
103+
let first = bytes[0];
104+
if bytes[1..].iter().all(|&b| b == first) {
105+
let fill = bx.cx().const_u8(first);
106+
bx.memset(start, fill, size, dest.val.align, MemFlags::empty());
107+
return true;
108+
}
105109
}
106110

107111
// Use llvm.memset.p0i8.* to initialize byte arrays
108112
let v = bx.from_immediate(v);
109113
if bx.cx().val_ty(v) == bx.cx().type_i8() {
110114
bx.memset(start, v, size, dest.val.align, MemFlags::empty());
111-
return;
115+
return true;
116+
}
117+
false
118+
};
119+
120+
match cg_elem.val {
121+
OperandValue::Immediate(v) => {
122+
if try_init_all_same(bx, v) {
123+
return;
124+
}
112125
}
126+
_ => (),
113127
}
114128

115129
let count = self

tests/codegen/slice-init.rs

+26
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,32 @@ pub fn nonzero_integer_array() {
6363
opaque(&x);
6464
}
6565

66+
const N: usize = 100;
67+
68+
// CHECK-LABEL: @u16_init_one_bytes
69+
#[no_mangle]
70+
pub fn u16_init_one_bytes() -> [u16; N] {
71+
// CHECK-NOT: select
72+
// CHECK-NOT: br
73+
// CHECK-NOT: switch
74+
// CHECK-NOT: icmp
75+
// CHECK: call void @llvm.memset.p0
76+
[const { u16::from_be_bytes([1, 1]) }; N]
77+
}
78+
79+
// FIXME: undef bytes can just be initialized with the same value as the
80+
// defined bytes, if the defines bytes are all the same.
81+
// CHECK-LABEL: @option_none_init
82+
#[no_mangle]
83+
pub fn option_none_init() -> [Option<u8>; N] {
84+
// CHECK-NOT: select
85+
// CHECK: br label %repeat_loop_header{{.*}}
86+
// CHECK-NOT: switch
87+
// CHECK: icmp
88+
// CHECK-NOT: call void @llvm.memset.p0
89+
[None; N]
90+
}
91+
6692
// Use an opaque function to prevent rustc from removing useless drops.
6793
#[inline(never)]
6894
pub fn opaque(_: impl Sized) {}

0 commit comments

Comments
 (0)