From 8e939916347888e755d737c579042b034e215aa8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 29 Aug 2019 16:25:24 -0400 Subject: [PATCH] avoid unnecessarily requiring alignment for array elem pointers --- src/ir.cpp | 39 +++++++++++++++++++++++++-------------- std/mem.zig | 11 ++++++----- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 67b5157c9..ec414a5ad 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -16899,12 +16899,6 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct return ira->codegen->invalid_instruction; bool safety_check_on = elem_ptr_instruction->safety_check_on; - if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; - - uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type); - uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type); - uint64_t ptr_align = get_ptr_align(ira->codegen, return_type); if (instr_is_comptime(casted_elem_index)) { uint64_t index = bigint_as_u64(&casted_elem_index->value.data.x_bigint); if (array_type->id == ZigTypeIdArray) { @@ -16918,8 +16912,16 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct safety_check_on = false; } - { + if (return_type->data.pointer.explicit_alignment != 0) { // figure out the largest alignment possible + + if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown))) + return ira->codegen->invalid_instruction; + + uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type); + uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type); + uint64_t ptr_align = get_ptr_align(ira->codegen, return_type); + uint64_t chosen_align = abi_align; if (ptr_align >= abi_align) { while (ptr_align > abi_align) { @@ -17148,15 +17150,24 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct case ReqCompTimeNo: break; } - if (ptr_align < abi_align) { - if (elem_size >= ptr_align && elem_size % ptr_align == 0) { - return_type = adjust_ptr_align(ira->codegen, return_type, ptr_align); + + if (return_type->data.pointer.explicit_alignment != 0) { + if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown))) + return ira->codegen->invalid_instruction; + + uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type); + uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type); + uint64_t ptr_align = get_ptr_align(ira->codegen, return_type); + if (ptr_align < abi_align) { + if (elem_size >= ptr_align && elem_size % ptr_align == 0) { + return_type = adjust_ptr_align(ira->codegen, return_type, ptr_align); + } else { + // can't get here because guaranteed elem_size >= abi_align + zig_unreachable(); + } } else { - // can't get here because guaranteed elem_size >= abi_align - zig_unreachable(); + return_type = adjust_ptr_align(ira->codegen, return_type, abi_align); } - } else { - return_type = adjust_ptr_align(ira->codegen, return_type, abi_align); } } diff --git a/std/mem.zig b/std/mem.zig index ef001d5da..49a143dff 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -75,15 +75,16 @@ pub const Allocator = struct { new_alignment: u29, ) []u8, - /// Call `destroy` with the result. - /// Returns undefined memory. + /// Returns a pointer to undefined memory. + /// Call `destroy` with the result to free the memory. pub fn create(self: *Allocator, comptime T: type) Error!*T { if (@sizeOf(T) == 0) return &(T{}); const slice = try self.alloc(T, 1); return &slice[0]; } - /// `ptr` should be the return value of `create` + /// `ptr` should be the return value of `create`, or otherwise + /// have the same address and alignment property. pub fn destroy(self: *Allocator, ptr: var) void { const T = @typeOf(ptr).Child; if (@sizeOf(T) == 0) return; @@ -92,7 +93,7 @@ pub const Allocator = struct { assert(shrink_result.len == 0); } - pub fn alloc(self: *Allocator, comptime T: type, n: usize) ![]T { + pub fn alloc(self: *Allocator, comptime T: type, n: usize) Error![]T { return self.alignedAlloc(T, @alignOf(T), n); } @@ -101,7 +102,7 @@ pub const Allocator = struct { comptime T: type, comptime alignment: u29, n: usize, - ) ![]align(alignment) T { + ) Error![]align(alignment) T { if (n == 0) { return ([*]align(alignment) T)(undefined)[0..0]; }