diff options
| author | Cody Tapscott <topolarity@tapscott.me> | 2022-11-10 12:03:17 -0700 |
|---|---|---|
| committer | Cody Tapscott <topolarity@tapscott.me> | 2022-11-10 12:22:40 -0700 |
| commit | a2f4de1663f815ae8c202ba6a8c68b0658b7d23f (patch) | |
| tree | e900f62b506072b35e8d4d106c7948ee6977879c /src/codegen/llvm.zig | |
| parent | 8f3880074fb76871d9a4f35d1f72d0304ac5b404 (diff) | |
| download | zig-a2f4de1663f815ae8c202ba6a8c68b0658b7d23f.tar.gz zig-a2f4de1663f815ae8c202ba6a8c68b0658b7d23f.zip | |
stage2 llvm: Elide more loads
Adds optimizations for by-ref types to:
- .struct_field_val
- .slice_elem_val
- .ptr_elem_val
I would have expected LLVM to be able to optimize away these
temporaries since we don't leak pointers to them and they are fed
straight from def to use, but empirically it does not.
Resolves https://github.com/ziglang/zig/issues/12713
Resolves https://github.com/ziglang/zig/issues/12638
Diffstat (limited to 'src/codegen/llvm.zig')
| -rw-r--r-- | src/codegen/llvm.zig | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index b727404bfb..e93152df02 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -5644,6 +5644,14 @@ pub const FuncGen = struct { const base_ptr = self.builder.buildExtractValue(slice, 0, ""); const indices: [1]*llvm.Value = .{index}; const ptr = self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); + if (isByRef(elem_ty)) { + if (self.canElideLoad(body_tail)) + return ptr; + + const target = self.dg.module.getTarget(); + return self.loadByRef(ptr, elem_ty, elem_ty.abiAlignment(target), false); + } + return self.load(ptr, slice_ty); } @@ -5709,6 +5717,14 @@ pub const FuncGen = struct { const indices: [1]*llvm.Value = .{rhs}; break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); }; + if (isByRef(elem_ty)) { + if (self.canElideLoad(body_tail)) + return ptr; + + const target = self.dg.module.getTarget(); + return self.loadByRef(ptr, elem_ty, elem_ty.abiAlignment(target), false); + } + return self.load(ptr, ptr_ty); } @@ -5832,7 +5848,14 @@ pub const FuncGen = struct { const struct_llvm_ty = try self.dg.lowerType(struct_ty); const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, struct_llvm_val, llvm_field_index, ""); const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base); - return self.load(field_ptr, field_ptr_ty); + if (isByRef(field_ty)) { + if (canElideLoad(self, body_tail)) + return field_ptr; + + return self.loadByRef(field_ptr, field_ty, ptr_ty_buf.data.alignment(target), false); + } else { + return self.load(field_ptr, field_ptr_ty); + } }, .Union => { const union_llvm_ty = try self.dg.lowerType(struct_ty); |
