Skip to content

Commit

Permalink
codegen/llvm: improve loadTruncate() to use a simple load when possible
Browse files Browse the repository at this point in the history
forcing llvm to truncate the padding bits prevents some optimizations.

fixes 370662c
see ziglang#17768
  • Loading branch information
xxxbxxx authored and andrewrk committed May 9, 2024
1 parent 4163126 commit 5a99ca7
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 1 deletion.
23 changes: 22 additions & 1 deletion src/codegen/llvm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8953,7 +8953,12 @@ pub const FuncGen = struct {
alignment: Builder.Alignment,
) Allocator.Error!Builder.Value {
const o = self.dg.object;
return self.buildAlloca(try o.builder.arrayType(ty.abiSize(o.module), .i8), alignment);
const ip = &o.module.intern_pool;
const pointee_llvm_ty = if (ip.isUnion(ty.toIntern()) or ip.isAggregateType(ty.toIntern()))
try o.builder.arrayType(ty.abiSize(o.module), .i8)
else
try o.lowerType(ty);
return self.buildAlloca(pointee_llvm_ty, alignment);
}

fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !Builder.Value {
Expand Down Expand Up @@ -10532,6 +10537,22 @@ pub const FuncGen = struct {
try o.builder.intType(@intCast(abi_size * 8))
else
payload_llvm_ty;
if (payload_llvm_ty != load_llvm_ty) {
const is_localvar_load = switch (payload_ptr.unwrap()) {
.instruction => |insn| if (insn.getAllocaPointeeTypeWip(&fg.wip)) |localvar_llvm_type|
(localvar_llvm_type == payload_llvm_ty)
else
false,
.constant => true,
};
if (is_localvar_load) {
// When loading from a local alloca var, let's assume it was written by a "store of the same type"
// and that no masking is needed.
// This helps with llvm optimizers, see https://github.com/ziglang/zig/issues/17768
return try fg.wip.load(access_kind, payload_llvm_ty, payload_ptr, payload_alignment, "");
}
}

const loaded = try fg.wip.load(access_kind, load_llvm_ty, payload_ptr, payload_alignment, "");
const shifted = if (payload_llvm_ty != load_llvm_ty and o.target.cpu.arch.endian() == .big)
try fg.wip.bin(.lshr, loaded, try o.builder.intValue(
Expand Down
10 changes: 10 additions & 0 deletions src/codegen/llvm/Builder.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4325,6 +4325,16 @@ pub const Function = struct {
};
}

/// if the instruction is alloca returns pointee type, otherwise returns null
pub fn getAllocaPointeeTypeWip(self: Instruction.Index, wip: *const WipFunction) ?Type {
const instruction = wip.instructions.get(@intFromEnum(self));
return switch (instruction.tag) {
.alloca, .@"alloca inalloca" => return wip.extraData(Alloca, instruction.data).type,

else => null,
};
}

pub fn typeOfWip(self: Instruction.Index, wip: *const WipFunction) Type {
const instruction = wip.instructions.get(@intFromEnum(self));
return switch (instruction.tag) {
Expand Down

0 comments on commit 5a99ca7

Please sign in to comment.