authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-01-19 22:39:14+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-28 11:45:04-07:00
log0f3bd2afa320252d4f0ece627917feaade734064
tree84d3074974efb72f28c0c22a452c0a7dd8374a50
parent8e9fd042b8a56fc4bb8eeae3878b095af96eb1a6

stage1: handle compiler-rt calls on vectors of f80


1 files changed, 54 insertions(+), 9 deletions(-)

src/stage1/codegen.cpp+54-9
......@@ -3237,10 +3237,10 @@ static LLVMValueRef get_soft_f80_bin_op_func(CodeGen *g, const char *name, int p
32373237static LLVMValueRef ir_render_soft_f80_bin_op(CodeGen *g, Stage1Air *executable,
32383238 Stage1AirInstBinOp *bin_op_instruction)
32393239{
3240 // TODO support vectors
32413240 IrBinOp op_id = bin_op_instruction->op_id;
32423241 Stage1AirInst *op1 = bin_op_instruction->op1;
32433242 Stage1AirInst *op2 = bin_op_instruction->op2;
3243 uint32_t vector_len = op1->value->type->id == ZigTypeIdVector ? op1->value->type->data.vector.len : 0;
32443244
32453245 LLVMValueRef op1_value = ir_llvm_value(g, op1);
32463246 LLVMValueRef op2_value = ir_llvm_value(g, op2);
......@@ -3334,21 +3334,63 @@ static LLVMValueRef ir_render_soft_f80_bin_op(CodeGen *g, Stage1Air *executable,
33343334
33353335 LLVMValueRef func_ref = get_soft_f80_bin_op_func(g, func_name, param_count, return_type);
33363336
3337 LLVMValueRef params[2] = {op1_value, op2_value};
3338 LLVMValueRef result = LLVMBuildCall(g->builder, func_ref, params, param_count, "");
3337 LLVMValueRef result;
3338 if (vector_len == 0) {
3339 LLVMValueRef params[2] = {op1_value, op2_value};
3340 result = LLVMBuildCall(g->builder, func_ref, params, param_count, "");
3341 } else {
3342 result = build_alloca(g, op1->value->type, "", 0);
3343 }
3344
3345 LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type;
3346 for (uint32_t i = 0; i < vector_len; i++) {
3347 LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false);
3348 LLVMValueRef params[2] = {
3349 LLVMBuildExtractElement(g->builder, op1_value, index_value, ""),
3350 LLVMBuildExtractElement(g->builder, op2_value, index_value, ""),
3351 };
3352 LLVMValueRef call_result = LLVMBuildCall(g->builder, func_ref, params, param_count, "");
3353 LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""),
3354 call_result, index_value, "");
3355 }
33393356
33403357 if (div_exact_safety_check) {
33413358 // Safety check: a / b == floor(a / b)
3342 func_ref = get_soft_f80_bin_op_func(g, "__floorx", 1, return_type);
3343 LLVMValueRef floored = LLVMBuildCall(g->builder, func_ref, &result, 1, "");
3359 LLVMValueRef floor_func = get_soft_f80_bin_op_func(g, "__floorx", 1, return_type);
3360 LLVMValueRef eq_func = get_soft_f80_bin_op_func(g, "__eqxf2", 2, g->builtin_types.entry_i32->llvm_type);
3361
3362 LLVMValueRef ok_bit;
3363 if (vector_len == 0) {
3364 LLVMValueRef floored = LLVMBuildCall(g->builder, floor_func, &result, 1, "");
3365
3366 LLVMValueRef params[2] = {result, floored};
3367 ok_bit = LLVMBuildCall(g->builder, eq_func, params, 2, "");
3368 } else {
3369 ZigType *bool_vec_ty = get_vector_type(g, vector_len, g->builtin_types.entry_bool);
3370 ok_bit = build_alloca(g, bool_vec_ty, "", 0);
3371 }
3372
3373 for (uint32_t i = 0; i < vector_len; i++) {
3374 LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false);
3375 LLVMValueRef div_res = LLVMBuildExtractElement(g->builder,
3376 LLVMBuildLoad(g->builder, result, ""), index_value, "");
33443377
3378 LLVMValueRef params[2] = {
3379 div_res,
3380 LLVMBuildCall(g->builder, floor_func, &div_res, 1, ""),
3381 };
3382 LLVMValueRef cmp_res = LLVMBuildCall(g->builder, eq_func, params, 2, "");
3383 cmp_res = LLVMBuildTrunc(g->builder, cmp_res, g->builtin_types.entry_bool->llvm_type, "");
3384 LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, ok_bit, ""),
3385 cmp_res, index_value, "");
3386 }
3387
3388 if (vector_len != 0) {
3389 ok_bit = ZigLLVMBuildAndReduce(g->builder, LLVMBuildLoad(g->builder, ok_bit, ""));
3390 }
33453391 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactOk");
33463392 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactFail");
33473393
3348 LLVMValueRef params[2] = {result, floored};
3349 func_ref = get_soft_f80_bin_op_func(g, "__eqxf2", 2, g->builtin_types.entry_i32->llvm_type);
3350 LLVMValueRef ok_bit = LLVMBuildCall(g->builder, func_ref, params, 2, "");
3351
33523394 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
33533395
33543396 LLVMPositionBuilderAtEnd(g->builder, fail_block);
......@@ -3357,6 +3399,9 @@ static LLVMValueRef ir_render_soft_f80_bin_op(CodeGen *g, Stage1Air *executable,
33573399 LLVMPositionBuilderAtEnd(g->builder, ok_block);
33583400 }
33593401
3402 if (vector_len != 0) {
3403 result = LLVMBuildLoad(g->builder, result, "");
3404 }
33603405 return result;
33613406}
33623407