diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index d0ed4aafc430..84feece31792 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -5750,8 +5750,8 @@ pub const FuncGen = struct { const elem_ty = array_ty.childType(); if (isByRef(array_ty)) { const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs }; - const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, array_llvm_val, &indices, indices.len, ""); if (isByRef(elem_ty)) { + const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, array_llvm_val, &indices, indices.len, ""); if (canElideLoad(self, body_tail)) return elem_ptr; @@ -5772,11 +5772,13 @@ pub const FuncGen = struct { .struct_field_ptr_index_3 => { const load_ptr_inst = try self.resolveInst(load_ptr); const gep = self.builder.buildInBoundsGEP(array_llvm_ty, load_ptr_inst, &indices, indices.len, ""); + array_llvm_val.removeUnusedLoadArray(); return self.builder.buildLoad(elem_llvm_ty, gep, ""); }, else => {} } } + const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, array_llvm_val, &indices, indices.len, ""); return self.builder.buildLoad(elem_llvm_ty, elem_ptr, ""); } } diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index 90d0f51c7b36..23337893a448 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -256,6 +256,9 @@ pub const Value = opaque { pub const addByValAttr = ZigLLVMAddByValAttr; extern fn ZigLLVMAddByValAttr(Fn: *Value, ArgNo: c_uint, type: *Type) void; + + pub const removeUnusedLoadArray = ZigLLVMRemoveUnusedLoadArray; + extern fn ZigLLVMRemoveUnusedLoadArray(Val: *Value) void; }; pub const Type = opaque { diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index c38e311f6790..1c7bff213b10 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -186,6 +186,20 @@ unsigned ZigLLVMDataLayoutGetProgramAddressSpace(LLVMTargetDataRef TD) { return unwrap(TD)->getProgramAddressSpace(); } +void ZigLLVMRemoveUnusedLoadArray(LLVMValueRef Val) { + auto *Ptr = unwrap(Val); + if (auto *AI = dyn_cast(Ptr)) { + if (AI->hasOneUse()) { + if (auto *CI = dyn_cast(AI->user_back())) { + if (CI->getIntrinsicID() == Intrinsic::memcpy) { + CI->eraseFromParent(); + AI->eraseFromParent(); + } + } + } + } +} + namespace { // LLVM's time profiler can provide a hierarchy view of the time spent // in each component. It generates JSON report in Chrome's "Trace Event" diff --git a/src/zig_llvm.h b/src/zig_llvm.h index 7f9bd0a1619d..14b487668c74 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -599,4 +599,6 @@ ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type, ZIG_EXTERN_C unsigned ZigLLVMDataLayoutGetStackAlignment(LLVMTargetDataRef TD); ZIG_EXTERN_C unsigned ZigLLVMDataLayoutGetProgramAddressSpace(LLVMTargetDataRef TD); +ZIG_EXTERN_C void ZigLLVMRemoveUnusedLoadArray(LLVMValueRef Val); + #endif