Commit 8e93991634

Andrew Kelley <andrew@ziglang.org>
2019-08-29 22:25:24
avoid unnecessarily requiring alignment for array elem pointers
1 parent 0512bec
Changed files (2)
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);
         }
     }
 
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];
         }