Remove early DCE of builtins

Early DCE was sometimes cleaning up functions that we actaully still needed.
At some point we can come back to it and try to properly protect all special functions.
Until then, this still enables DCE, but it runs later with the full generated Roc module.
This commit is contained in:
Brendan Hansknecht 2023-12-11 08:23:56 -08:00
parent 3120dee509
commit fb049b661a
No known key found for this signature in database
GPG key ID: 0EA784685083E75B
2 changed files with 5 additions and 35 deletions

View file

@ -1060,44 +1060,18 @@ pub fn module_from_builtins<'ctx>(
// In testing, this adds about 20ms extra to compilation. // In testing, this adds about 20ms extra to compilation.
// Long term it would be best if we could do this on the zig side. // Long term it would be best if we could do this on the zig side.
// This change enables us to dce all the parts of compiler-rt we don't use. // The core issue is that we have to properly labael certain functions as private and DCE them.
// That said, it would be better to dce them before roc app compiltation time. // Otherwise, now that zig bundles all of compiler-rt, we would optimize and compile the entire library.
// Anything not depended on by a `roc_builtin.` function could alread by DCE'd theoretically. // Anything not depended on by a `roc_builtin.` function could already by DCE'd theoretically.
// That said, this workaround is good enough and fixes compilations times. // That said, this workaround is good enough and fixes compilations times.
// Also, must_keep is the functions we depend on that would normally be provide by libc. // Also, must_keep is the functions we depend on that would normally be provide by libc.
// They are magically linked to by llvm builtins, so we must specify that they can't be DCE'd. // They are magically linked to by llvm builtins, so we must specify that they can't be DCE'd.
let must_keep = [ let must_keep = ["_fltused", "floorf", "memcpy", "memset"];
"_fltused",
"floorf",
"memcpy",
"memset",
// Roc special functions
"__roc_force_longjmp",
"__roc_force_setjmp",
"set_shared_buffer",
];
for func in module.get_functions() { for func in module.get_functions() {
let has_definition = func.count_basic_blocks() > 0; let has_definition = func.count_basic_blocks() > 0;
let name = func.get_name().to_string_lossy(); let name = func.get_name().to_string_lossy();
if has_definition if has_definition && !must_keep.contains(&name.as_ref()) {
&& !name.starts_with("roc_builtins.")
&& !must_keep.contains(&name.as_ref())
{
func.set_linkage(Linkage::Private);
}
}
// Note, running DCE here is faster then waiting until full app DCE.
let mpm = PassManager::create(());
mpm.add_global_dce_pass();
mpm.run_on(&module);
// Now that the unused compiler-rt functions have been removed,
// mark that the builtin functions are allowed to be DCE'd if they aren't used.
for func in module.get_functions() {
let name = func.get_name().to_string_lossy();
if name.starts_with("roc_builtins.") {
func.set_linkage(Linkage::Private); func.set_linkage(Linkage::Private);
} }
} }

View file

@ -80,10 +80,6 @@ pub(crate) fn add_intrinsics<'ctx>(ctx: &'ctx Context, module: &Module<'ctx>) {
let i32_type = ctx.i32_type(); let i32_type = ctx.i32_type();
let void_type = ctx.void_type(); let void_type = ctx.void_type();
if let Some(func) = module.get_function("__muloti4") {
func.set_linkage(Linkage::WeakAny);
}
add_intrinsic( add_intrinsic(
ctx, ctx,
module, module,