authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-18 10:24:28-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-18 10:24:28-04:00
log558b4ac1f0fd7123ebe25f3e59eef275b066c50a
treea776d9e13cddf773a737fdba5a66c2722434637d
parent0e3ca4c63ecb8e43af8261020d21bc6888d18fc0
signaturelock-open Commit is signed but in an unrecognized format.

adjust codegen of casting between arrays and vectors

* bitcasting is still better when the size_in_bits aligns with the ABI size of the element type. Logic is reworked to do bitcasting when possible * rather than using insertelement/extractelement to work with arrays, store/load elements directly. This matches codegen for arrays elsewhere.

2 files changed, 52 insertions(+), 19 deletions(-)

src/all_types.hpp+1-1
...@@ -1351,7 +1351,7 @@ struct ZigTypeBoundFn {...@@ -1351,7 +1351,7 @@ struct ZigTypeBoundFn {
1351};1351};
13521352
1353struct ZigTypeVector {1353struct ZigTypeVector {
1354 // The type must be a pointer, integer, or float1354 // The type must be a pointer, integer, bool, or float
1355 ZigType *elem_type;1355 ZigType *elem_type;
1356 uint32_t len;1356 uint32_t len;
1357};1357};
src/codegen.cpp+51-18
...@@ -5549,14 +5549,29 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab...@@ -5549,14 +5549,29 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab
5549 assert(handle_is_ptr(array_type));5549 assert(handle_is_ptr(array_type));
5550 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);5550 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
5551 LLVMValueRef vector = ir_llvm_value(g, instruction->vector);5551 LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
5552 LLVMValueRef array = LLVMGetUndef(get_llvm_type(g, array_type));5552
5553 for (uintptr_t i = 0; i < instruction->vector->value.type->data.vector.len; i++) {5553 ZigType *elem_type = array_type->data.array.child_type;
5554 LLVMValueRef index = LLVMConstInt(g->builtin_types.entry_u32->llvm_type, i, false);5554 bool bitcast_ok = (elem_type->size_in_bits * 8) == elem_type->abi_size;
5555 LLVMValueRef elem = LLVMBuildExtractElement(g->builder, vector,5555 if (bitcast_ok) {
5556 index, "vector_to_array");5556 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc,
5557 array = LLVMBuildInsertValue(g->builder, array, elem, i, "");5557 LLVMPointerType(get_llvm_type(g, instruction->vector->value.type), 0), "");
5558 }5558 uint32_t alignment = get_ptr_align(g, instruction->result_loc->value.type);
5559 LLVMBuildStore(g->builder, array, result_loc);5559 gen_store_untyped(g, vector, casted_ptr, alignment, false);
5560 } else {
5561 // If the ABI size of the element type is not evenly divisible by size_in_bits, a simple bitcast
5562 // will not work, and we fall back to extractelement.
5563 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
5564 LLVMTypeRef u32_type_ref = LLVMInt32Type();
5565 LLVMValueRef zero = LLVMConstInt(usize_type_ref, 0, false);
5566 for (uintptr_t i = 0; i < instruction->vector->value.type->data.vector.len; i++) {
5567 LLVMValueRef index_usize = LLVMConstInt(usize_type_ref, i, false);
5568 LLVMValueRef index_u32 = LLVMConstInt(u32_type_ref, i, false);
5569 LLVMValueRef indexes[] = { zero, index_usize };
5570 LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, result_loc, indexes, 2, "");
5571 LLVMValueRef elem = LLVMBuildExtractElement(g->builder, vector, index_u32, "");
5572 LLVMBuildStore(g->builder, elem, elem_ptr);
5573 }
5574 }
5560 return result_loc;5575 return result_loc;
5561}5576}
55625577
...@@ -5567,16 +5582,34 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab...@@ -5567,16 +5582,34 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab
5567 assert(vector_type->id == ZigTypeIdVector);5582 assert(vector_type->id == ZigTypeIdVector);
5568 assert(!handle_is_ptr(vector_type));5583 assert(!handle_is_ptr(vector_type));
5569 LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array);5584 LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array);
5570 LLVMValueRef array = LLVMBuildLoad2(g->builder, get_llvm_type(g, instruction->array->value.type),5585 LLVMTypeRef vector_type_ref = get_llvm_type(g, vector_type);
5571 array_ptr, "");5586
5572 LLVMValueRef vector = LLVMGetUndef(get_llvm_type(g, vector_type));5587 ZigType *elem_type = vector_type->data.vector.elem_type;
5573 for (uintptr_t i = 0; i < instruction->base.value.type->data.vector.len; i++) {5588 bool bitcast_ok = (elem_type->size_in_bits * 8) == elem_type->abi_size;
5574 LLVMValueRef index = LLVMConstInt(g->builtin_types.entry_u32->llvm_type, i, false);5589 if (bitcast_ok) {
5575 LLVMValueRef elem = LLVMBuildExtractValue(g->builder, array,5590 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr,
5576 i, "vector_to_array");5591 LLVMPointerType(vector_type_ref, 0), "");
5577 vector = LLVMBuildInsertElement(g->builder, vector, elem, index, "");5592 ZigType *array_type = instruction->array->value.type;
5578 }5593 assert(array_type->id == ZigTypeIdArray);
5579 return vector;5594 uint32_t alignment = get_abi_alignment(g, array_type->data.array.child_type);
5595 return gen_load_untyped(g, casted_ptr, alignment, false, "");
5596 } else {
5597 // If the ABI size of the element type is not evenly divisible by size_in_bits, a simple bitcast
5598 // will not work, and we fall back to insertelement.
5599 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
5600 LLVMTypeRef u32_type_ref = LLVMInt32Type();
5601 LLVMValueRef zero = LLVMConstInt(usize_type_ref, 0, false);
5602 LLVMValueRef vector = LLVMGetUndef(vector_type_ref);
5603 for (uintptr_t i = 0; i < instruction->base.value.type->data.vector.len; i++) {
5604 LLVMValueRef index_usize = LLVMConstInt(usize_type_ref, i, false);
5605 LLVMValueRef index_u32 = LLVMConstInt(u32_type_ref, i, false);
5606 LLVMValueRef indexes[] = { zero, index_usize };
5607 LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indexes, 2, "");
5608 LLVMValueRef elem = LLVMBuildLoad(g->builder, elem_ptr, "");
5609 vector = LLVMBuildInsertElement(g->builder, vector, elem, index_u32, "");
5610 }
5611 return vector;
5612 }
5580}5613}
55815614
5582static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable,5615static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable,