Rollup merge of #151150 - revert-vec-append, r=Zalathar

Revert "avoid phi node for pointers flowing into Vec appends #130998"

This reverts PR rust-lang/rust#130998 because the added test seems to be flaky / non-deterministic, and has been failing in unrelated PRs during merge CI:

- https://github.com/rust-lang/rust/pull/151129#issuecomment-3751597908
- https://github.com/rust-lang/rust/pull/150772#issuecomment-3751696578
- https://github.com/rust-lang/rust/pull/150925#issuecomment-3752431118
- https://github.com/rust-lang/rust/pull/151145#issuecomment-3752500686

See also [#t-infra > Tree ops](https://rust-lang.zulipchat.com/#narrow/channel/242791-t-infra/topic/Tree.20ops/with/568111767).

> [!NOTE]
>
> This is a "fallback" PR in case the FileCheck failure isn't obvious (i.e. fix-forward). This PR reverts rust-lang/rust#130998 wholesale in case the failure is genuine and indicative of a bug in the actual implementation change.
This commit is contained in:
Stuart Cook 2026-01-15 14:10:21 +11:00 committed by GitHub
commit 11b00792ba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 5 additions and 50 deletions

View file

@ -517,16 +517,7 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
to_add.push(llvm::CreateAllocKindAttr(cx.llcx, AllocKindFlags::Free));
// applies to argument place instead of function place
let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx);
let attrs: &[_] = if llvm_util::get_version() >= (21, 0, 0) {
// "Does not capture provenance" means "if the function call stashes the pointer somewhere,
// accessing that pointer after the function returns is UB". That is definitely the case here since
// freeing will destroy the provenance.
let captures_addr = AttributeKind::CapturesAddress.create_attr(cx.llcx);
&[allocated_pointer, captures_addr]
} else {
&[allocated_pointer]
};
attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), attrs);
attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]);
}
if let Some(align) = codegen_fn_attrs.alignment {
llvm::set_alignment(llfn, align);

View file

@ -448,11 +448,9 @@ impl<T> [T] {
// SAFETY:
// allocated above with the capacity of `s`, and initialize to `s.len()` in
// ptr::copy_to_non_overlapping below.
if s.len() > 0 {
unsafe {
s.as_ptr().copy_to_nonoverlapping(v.as_mut_ptr(), s.len());
v.set_len(s.len());
}
unsafe {
s.as_ptr().copy_to_nonoverlapping(v.as_mut_ptr(), s.len());
v.set_len(s.len());
}
v
}

View file

@ -2818,11 +2818,7 @@ impl<T, A: Allocator> Vec<T, A> {
let count = other.len();
self.reserve(count);
let len = self.len();
if count > 0 {
unsafe {
ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count)
};
}
unsafe { ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count) };
self.len += count;
}

View file

@ -1,30 +0,0 @@
//@ compile-flags: -O -Zmerge-functions=disabled
//@ min-llvm-version: 21
#![crate_type = "lib"]
//! Check that a temporary intermediate allocations can eliminated and replaced
//! with memcpy forwarding.
//! This requires Vec code to be structured in a way that avoids phi nodes from the
//! zero-capacity length flowing into the memcpy arguments.
// CHECK-LABEL: @vec_append_with_temp_alloc
#[no_mangle]
pub fn vec_append_with_temp_alloc(dst: &mut Vec<u8>, src: &[u8]) {
// CHECK-NOT: call void @llvm.memcpy
// CHECK: call void @llvm.memcpy.{{.*}}%dst.i{{.*}}%src.0
// CHECK-NOT: call void @llvm.memcpy
let temp = src.to_vec();
dst.extend(&temp);
// CHECK: ret
}
// CHECK-LABEL: @string_append_with_temp_alloc
#[no_mangle]
pub fn string_append_with_temp_alloc(dst: &mut String, src: &str) {
// CHECK-NOT: call void @llvm.memcpy
// CHECK: call void @llvm.memcpy.{{.*}}%dst.i{{.*}}%src.0
// CHECK-NOT: call void @llvm.memcpy
let temp = src.to_string();
dst.push_str(&temp);
// CHECK: ret
}