Open oli-obk opened 9 years ago
hmmm, I'm not so sure if it's a regression. It still works for vectors: http://is.gd/yNAFF6 . Maybe it never worked for boxes?
So, where do we go with this ticket? Was/is this a regression? is it worth tracking?
@steveklabnik Probably a regression from when we moved from actual zeroing-drop to using the non-zero drop pattern. The check for that pattern basically says "leak this if the adress matches the drop pattern", so LLVM cannot remove the allocation because that would change semantics. Dynamic drop will fix this, and I think we should keep this open to track that, just to make sure.
This appears to be fixed: https://is.gd/kT0Gs9 Is this worth creating some kind of regression test for?
We could test it by adding a run pass test that uses a custom allocator (which doesn't allocate, but panics).
tentatively needstest, then. Maybe a src/test/codegen test?
Seems to not work again on nightly.
I've used @Mark-Simulacrum 's bisection tool to find out the regressing commit. It was the LLVM 4.0 upgrade, commit 0777c757a6832dc5f8f218377f99960f5477311f .
Assigning myself just so it stays on my to-do list. Not immediately working on it, though. Feel free to take over if you want.
Historically this optimization was done by https://github.com/rust-lang/llvm/commit/4daef480d1241d040a247440d24013cbdeb741e7 but this commit was not carried forward to our current branch when the 4.0 upgrade was done because it no longer applies cleanly (IIRC)
Sadly, I couldn’t make the patch above to work. In fact, some testing seems to indicate that the responsibility for eliding allocations has been moved out of LLVM into clang.
Namely, code like this
#include<stdlib.h>
void wowzers(int y) {
void *z = malloc(y);
if(z != NULL) free(z);
}
when compiled with clang test.c -emit-llvm -S -O3 -fno-builtin
(clang version being 4.0) has the allocations in the produced IR
; Function Attrs: nounwind sspstrong uwtable
define void @wowzers(i32) local_unnamed_addr #0 {
%2 = zext i32 %0 to i64
%3 = tail call noalias i8* @malloc(i64 %2) #2
%4 = icmp eq i8* %3, null
br i1 %4, label %6, label %5
; <label>:5: ; preds = %1
tail call void @free(i8* nonnull %3) #2
br label %6
; <label>:6: ; preds = %1, %5
ret void
}
whereas if the special handling of the built-ins is not disabled (i.e. without -fno-builtin
), it compiles to a ret void
even with -O0
.
This seems to suggest to me that, unless we do some serious patchwork on LLVM (pretty sure we don’t want to do that), it falls onto rustc to optimise out heap allocations now.
This could also very well be a bug. I have a test case on hand that does optimise out on 3.9 but not on 4.0. I might do a bisection.
Okay, never mind. I got it to work.
The LLVM upgrade reintroduces optimisation for _rust_allocate, but the optimisation for __rust_allocate_zeroed was backed out due to weird UB-like behaviour with bitvec iterators in rustc_data_structures.
Should investigate eventually. Assigning myself.
cc @arielb1 you were interested in this yesterday.
I believe this is no longer a regression, so untagging as a regression.
It's not very clear to me whether this is still actionable. The original snippet doesn't seem to be misoptimised anymore. Can someone produce a new snippet that demonstrates the continued existence of the issue? Should the issue be closed?
Cc @rust-lang/wg-codegen
This should stay open as only a handful of alllocating functions are currently handled (i.e. malloc equivalent but not realloc IIRC).
On Mon, Apr 2, 2018, 14:37 Anthony Ramine notifications@github.com wrote:
It's not very clear to me whether this is still actionable. The original snippet doesn't seem to be misoptimised anymore. Can someone produce a new snippet that demonstrates the continued existence of the issue? Should the issue be closed?
Cc @rust-lang/wg-codegen https://github.com/orgs/rust-lang/teams/wg-codegen
— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/rust-lang/rust/issues/24194#issuecomment-377912330, or mute the thread https://github.com/notifications/unsubscribe-auth/AApc0mikNK6SdwDWKu-Gccdw9qaNIrHUks5tkg2RgaJpZM4D8f_0 .
Or was it calloc-equivalent.
On Tue, Apr 3, 2018, 12:13 Simonas Kazlauskas s@kazlauskas.me wrote:
This should stay open as only a handful of alllocating functions are currently handled (i.e. malloc equivalent but not realloc IIRC).
On Mon, Apr 2, 2018, 14:37 Anthony Ramine notifications@github.com wrote:
It's not very clear to me whether this is still actionable. The original snippet doesn't seem to be misoptimised anymore. Can someone produce a new snippet that demonstrates the continued existence of the issue? Should the issue be closed?
Cc @rust-lang/wg-codegen https://github.com/orgs/rust-lang/teams/wg-codegen
— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/rust-lang/rust/issues/24194#issuecomment-377912330, or mute the thread https://github.com/notifications/unsubscribe-auth/AApc0mikNK6SdwDWKu-Gccdw9qaNIrHUks5tkg2RgaJpZM4D8f_0 .
@nagisa Any snippet demonstrating the issue?
#![feature(allocator_api)]
use std::heap::{Heap, Layout, Alloc};
pub unsafe fn alloc_zeroed_doesnt_optimise() {
let _ = Heap.alloc_zeroed(Layout::from_size_align_unchecked(4, 8));
}
extern "C" {
fn foo(x: *mut u8);
}
pub unsafe fn alloc_zeroed_should_optimise_rezeroing() {
let a = Heap.alloc_zeroed(Layout::from_size_align_unchecked(16, 8)).unwrap();
let slc = ::std::slice::from_raw_parts_mut(a, 16);
for i in slc.iter_mut() {
*i = 0;
}
foo(slc.as_mut_ptr());
}
For searchability purposes, the functions are now called __rust_alloc_zeroed
and __rust_dealloc
.
This was noticed in the wild on Stack Overflow.
It would be nice if we didn't have to patch LLVM to support custom allocation functions. Unfortunately the last discussion on that topic didn't really end up anywhere: http://lists.llvm.org/pipermail/llvm-dev/2016-January/093625.html
The only way around that is to guarantee this optimization via MIR optimizations. But our MIR optimization story is nowhere near the level required for that.
Couldn't this be generalized by having a "pure, no side-effects" unsafe attribute?
22159 was closed after a llvm update (#22526). It used to work (I remember I tried it out). Now it doesn't work anymore.
http://is.gd/Wekr7w
LLVM-IR: