From 0f3bd2afa320252d4f0ece627917feaade734064 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 19 Jan 2022 22:39:14 +0200 Subject: [PATCH] stage1: handle compiler-rt calls on vectors of f80 --- src/stage1/codegen.cpp | 63 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 9 deletions(-) diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index f8e12e1d78..548abebc6f 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -3237,10 +3237,10 @@ static LLVMValueRef get_soft_f80_bin_op_func(CodeGen *g, const char *name, int p static LLVMValueRef ir_render_soft_f80_bin_op(CodeGen *g, Stage1Air *executable, Stage1AirInstBinOp *bin_op_instruction) { - // TODO support vectors IrBinOp op_id = bin_op_instruction->op_id; Stage1AirInst *op1 = bin_op_instruction->op1; Stage1AirInst *op2 = bin_op_instruction->op2; + uint32_t vector_len = op1->value->type->id == ZigTypeIdVector ? op1->value->type->data.vector.len : 0; LLVMValueRef op1_value = ir_llvm_value(g, op1); LLVMValueRef op2_value = ir_llvm_value(g, op2); @@ -3334,21 +3334,63 @@ static LLVMValueRef ir_render_soft_f80_bin_op(CodeGen *g, Stage1Air *executable, LLVMValueRef func_ref = get_soft_f80_bin_op_func(g, func_name, param_count, return_type); - LLVMValueRef params[2] = {op1_value, op2_value}; - LLVMValueRef result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); + LLVMValueRef result; + if (vector_len == 0) { + LLVMValueRef params[2] = {op1_value, op2_value}; + result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); + } else { + result = build_alloca(g, op1->value->type, "", 0); + } + + LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type; + for (uint32_t i = 0; i < vector_len; i++) { + LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false); + LLVMValueRef params[2] = { + LLVMBuildExtractElement(g->builder, op1_value, index_value, ""), + LLVMBuildExtractElement(g->builder, op2_value, index_value, ""), + }; + LLVMValueRef call_result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); + LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""), + call_result, index_value, ""); + } if (div_exact_safety_check) { // Safety check: a / b == floor(a / b) - func_ref = get_soft_f80_bin_op_func(g, "__floorx", 1, return_type); - LLVMValueRef floored = LLVMBuildCall(g->builder, func_ref, &result, 1, ""); + LLVMValueRef floor_func = get_soft_f80_bin_op_func(g, "__floorx", 1, return_type); + LLVMValueRef eq_func = get_soft_f80_bin_op_func(g, "__eqxf2", 2, g->builtin_types.entry_i32->llvm_type); + LLVMValueRef ok_bit; + if (vector_len == 0) { + LLVMValueRef floored = LLVMBuildCall(g->builder, floor_func, &result, 1, ""); + + LLVMValueRef params[2] = {result, floored}; + ok_bit = LLVMBuildCall(g->builder, eq_func, params, 2, ""); + } else { + ZigType *bool_vec_ty = get_vector_type(g, vector_len, g->builtin_types.entry_bool); + ok_bit = build_alloca(g, bool_vec_ty, "", 0); + } + + for (uint32_t i = 0; i < vector_len; i++) { + LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false); + LLVMValueRef div_res = LLVMBuildExtractElement(g->builder, + LLVMBuildLoad(g->builder, result, ""), index_value, ""); + + LLVMValueRef params[2] = { + div_res, + LLVMBuildCall(g->builder, floor_func, &div_res, 1, ""), + }; + LLVMValueRef cmp_res = LLVMBuildCall(g->builder, eq_func, params, 2, ""); + cmp_res = LLVMBuildTrunc(g->builder, cmp_res, g->builtin_types.entry_bool->llvm_type, ""); + LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, ok_bit, ""), + cmp_res, index_value, ""); + } + + if (vector_len != 0) { + ok_bit = ZigLLVMBuildAndReduce(g->builder, LLVMBuildLoad(g->builder, ok_bit, "")); + } LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactOk"); LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactFail"); - LLVMValueRef params[2] = {result, floored}; - func_ref = get_soft_f80_bin_op_func(g, "__eqxf2", 2, g->builtin_types.entry_i32->llvm_type); - LLVMValueRef ok_bit = LLVMBuildCall(g->builder, func_ref, params, 2, ""); - LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); LLVMPositionBuilderAtEnd(g->builder, fail_block); @@ -3357,6 +3399,9 @@ static LLVMValueRef ir_render_soft_f80_bin_op(CodeGen *g, Stage1Air *executable, LLVMPositionBuilderAtEnd(g->builder, ok_block); } + if (vector_len != 0) { + result = LLVMBuildLoad(g->builder, result, ""); + } return result; }