From c268dd2c5e6b277af82f48c72044df63634c1fa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 4 Aug 2026 11:30:06 +0200 Subject: [PATCH] Revert "llvm: workaround crash on large inline memset" This reverts commit 84c2d809ec90aa3d5934adac33551f82656625ee. closes https://codeberg.org/ziglang/zig/issues/31701 --- src/codegen/llvm/FuncGen.zig | 43 ++++-------------------------------- test/tests.zig | 4 ---- 2 files changed, 4 insertions(+), 43 deletions(-) diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index f213d7cf7bf3ec2d1d7d0e4764a1002d9b590dc3..6ddb1d7f73aa18c1792c08c4aad3e227176ff774 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -1071,7 +1071,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo const val_is_undef = if (un_op.toInterned()) |i| Value.fromInterned(i).isUndef(zcu) else false; const ret_ty_align = ret_ty.abiAlignment(zcu); - if (val_is_undef and safety and !self.needMemsetWorkaround(ret_ty.abiSize(zcu))) { + if (val_is_undef and safety) { const rp = switch (self.ret_ptr) { .none => try self.buildZigAlloca(ret_ty, .none), else => |rp| rp, @@ -5069,7 +5069,7 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu }; const val_is_undef = if (bin_op.rhs.toInterned()) |i| Value.fromInterned(i).isUndef(zcu) else false; - if (val_is_undef and !fg.needMemsetWorkaround(elem_ty.abiSize(zcu))) { + if (val_is_undef) { const owner_mod = fg.ownerModule(); // Even if safety is disabled, we still emit a memset to undefined since it conveys @@ -5585,11 +5585,6 @@ fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error self.maybeMarkAllowZeroAccess(ptr_ty.ptrInfo(zcu)); - const allow_byte_memset = !self.needMemsetWorkaround(switch (ptr_ty.ptrSize(zcu)) { - .one => ptr_ty.childType(zcu).abiSize(zcu), - .slice => null, - .many, .c => unreachable, - }); const len_bytes = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); try self.lowerMemset( @@ -5600,7 +5595,6 @@ fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error len_bytes, access_kind, safety, - allow_byte_memset, ); return .none; } @@ -5614,12 +5608,11 @@ fn lowerMemset( len_bytes: Builder.Value, access_kind: Builder.MemoryAccessKind, safety: bool, - allow_byte_memset: bool, ) Allocator.Error!void { const o = self.object; const zcu = o.zcu; - if (allow_byte_memset) if (elem_ref.toInterned()) |elem_ip_index| { + if (elem_ref.toInterned()) |elem_ip_index| { const elem_val: Value = .fromInterned(elem_ip_index); if (elem_val.isUndef(zcu)) { // Even if safety is disabled, we still emit a memset to undefined since it conveys @@ -5660,13 +5653,12 @@ fn lowerMemset( ); return; } - }; + } const value = try self.resolveInst(elem_ref); const elem_abi_size = elem_ty.abiSize(zcu); intrinsic: { - if (!allow_byte_memset) break :intrinsic; if (elem_abi_size != 1) break :intrinsic; // To use LLVM's intrinsic, we need to convert the operand to a raw 8-bit integer value. const fill_byte: Builder.Value = byte: { @@ -6023,7 +6015,6 @@ fn airSplat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value len_bytes_llvm, .normal, false, - !self.needMemsetWorkaround(len_bytes), ); if (array_info.sentinel) |sent_val| { @@ -8143,32 +8134,6 @@ fn llvmAllocaAddressSpace(target: *const std.Target) Builder.AddrSpace { }; } -/// Due to an LLVM bug, calls to `@llvm.memset.inline.*` with large constant length arguments cause -/// LLVM to crash. As a mitigation, this function returns `true` if we should avoid emitting a -/// memset call of the given length. -/// -/// Most of our call sites are just setting memory to `undefined`, so can simply skip the memset -/// call if we return `true`. -/// -/// Upstream issue: https://github.com/llvm/llvm-project/issues/189161 -/// Zig issue: https://codeberg.org/ziglang/zig/issues/31701 -fn needMemsetWorkaround(fg: *const FuncGen, maybe_len: ?u64) bool { - if (!fg.disable_intrinsics) { - // The bug is limited to `@llvm.memset.inline.*`: normal memset calls are fine. - return false; - } - const len = maybe_len orelse { - // We don't think the length is constant, but a trivial optimization on LLVM's side could - // turn it into one and potentially trigger the bug. Therefore, always apply the workaround - // if the length is not a known constant. - return true; - }; - // Empirically, the crash first happens at 1048561 bytes, which is 1 MiB less 15 bytes. To be - // safe (just in case the limit is target-specific or something like that), let's just set the - // cap at half of that, i.e. 512 KiB. - return len > 1024 * 512; -} - const mips_clobber_overrides = std.StaticStringMap(enum { @"$msair", @"$msacsr", diff --git a/test/tests.zig b/test/tests.zig index 9a188f595d35226d2be773fc0ac93a4d46c81651..aa86dc0879884bc116e2c113942d8a7a54df1501 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -2933,10 +2933,6 @@ fn addOneModuleTest( }); these_tests.linkage = test_target.linkage; these_tests.use_new_linker = test_target.new_linker; - // https://codeberg.org/ziglang/zig/issues/31701 - if (!(mem.eql(u8, options.name, "compiler-rt") or mem.eql(u8, options.name, "libc"))) { - if (options.no_builtin) these_tests.root_module.no_builtin = true; - } // https://codeberg.org/ziglang/zig/issues/31702 if (mem.eql(u8, options.name, "compiler-rt") or mem.eql(u8, options.name, "libc")) { these_tests.root_module.stack_protector = false; -- 2.54.0