diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index afbef86bd089e..950a4112ebfae 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -86,7 +86,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .layout_of(bx.typing_env().as_query_input(pointee)) .expect("expected pointee to have a layout"); let elem_size = pointee_layout.layout.size().bytes(); - let bytes = bx.mul(count, bx.const_usize(elem_size)); + let bytes = bx.unchecked_sumul(count, bx.const_usize(elem_size)); let align = pointee_layout.layout.align.abi; let dst = dst_val.immediate(); diff --git a/tests/codegen-llvm/intrinsics/copy_nonoverlapping.rs b/tests/codegen-llvm/intrinsics/copy_nonoverlapping.rs new file mode 100644 index 0000000000000..84a1f713ce68c --- /dev/null +++ b/tests/codegen-llvm/intrinsics/copy_nonoverlapping.rs @@ -0,0 +1,17 @@ +//@ compile-flags: -Copt-level=3 -C no-prepopulate-passes +//@ only-64bit (so I don't need to worry about usize) + +#![crate_type = "lib"] +#![feature(core_intrinsics)] + +// This deals in a count of elements, not bytes, so we need to multiply. +// Ensure we preserve UB from a count too high to be valid. +use std::intrinsics::copy_nonoverlapping; + +// CHECK-LABEL: @copy_u16( +#[no_mangle] +pub unsafe fn copy_u16(src: *const u16, dst: *mut u16, count: usize) { + // CHECK: [[BYTES:%.+]] = mul nuw nsw i64 %count, 2 + // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 2 %dst, ptr align 2 %src, i64 [[BYTES]], i1 false) + copy_nonoverlapping(src, dst, count) +}