From 64e60d8ae2c06689a2e0533eb43a1c6a8ff01259 Mon Sep 17 00:00:00 2001 From: Vexu Date: Wed, 11 Mar 2020 10:29:15 +0200 Subject: [PATCH] special case atomic operations on zero bit types --- src/ir.cpp | 37 ++++++++++++++++++++++++++------ test/stage1/behavior/atomics.zig | 27 ++++++++++++++++------- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 9465be8b0b..2e87bd2687 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -25199,12 +25199,22 @@ static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxch return ira->codegen->invalid_inst_gen; } + ZigType *result_type = get_optional_type(ira->codegen, operand_type); + + // special case zero bit types + if (type_has_one_possible_value(ira->codegen, operand_type) == OnePossibleValueYes) { + ZigValue *val = ira->codegen->pass1_arena->allocate(1); + val->special = ConstValSpecialStatic; + val->type = result_type; + set_optional_value_to_null(val); + return ir_const_move(ira, &instruction->base.base, val); + } + if (instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar && instr_is_comptime(casted_cmp_value) && instr_is_comptime(casted_new_value)) { zig_panic("TODO compile-time execution of cmpxchg"); } - ZigType *result_type = get_optional_type(ira->codegen, operand_type); IrInstGen *result_loc; if (handle_is_ptr(ira->codegen, result_type)) { result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc, @@ -28317,18 +28327,23 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op, Zi *actual_type = nullptr; if (operand_type->id == ZigTypeIdInt || operand_type->id == ZigTypeIdEnum) { + ZigType *int_type; if (operand_type->id == ZigTypeIdEnum) { - operand_type = operand_type->data.enumeration.tag_int_type; + int_type = operand_type->data.enumeration.tag_int_type; + } else { + int_type = operand_type; } + auto bit_count = int_type->data.integral.bit_count; + bool is_signed = int_type->data.integral.is_signed; uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch); - if (operand_type->data.integral.bit_count > max_atomic_bits) { + + if (bit_count > max_atomic_bits) { ir_add_error(ira, &op->base, buf_sprintf("expected %" PRIu32 "-bit integer type or smaller, found %" PRIu32 "-bit integer type", - max_atomic_bits, operand_type->data.integral.bit_count)); + max_atomic_bits, bit_count)); return ira->codegen->builtin_types.entry_invalid; } - auto bit_count = operand_type->data.integral.bit_count; - bool is_signed = operand_type->data.integral.is_signed; + if (bit_count < 2 || !is_power_of_2(bit_count)) { if (bit_count < 8) { *actual_type = get_int_type(ira->codegen, is_signed, 8); @@ -28423,6 +28438,11 @@ static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAto return ira->codegen->invalid_inst_gen; } + // special case zero bit types + if (type_has_one_possible_value(ira->codegen, operand_type) == OnePossibleValueYes) { + return ir_const_move(ira, &instruction->base.base, get_the_one_possible_value(ira->codegen, operand_type)); + } + if (instr_is_comptime(casted_operand) && instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar) { ir_add_error(ira, &instruction->base.base, @@ -28504,6 +28524,11 @@ static IrInstGen *ir_analyze_instruction_atomic_store(IrAnalyze *ira, IrInstSrcA return ira->codegen->invalid_inst_gen; } + // special case zero bit types + if (type_has_one_possible_value(ira->codegen, operand_type) == OnePossibleValueYes) { + return ir_const_void(ira, &instruction->base.base); + } + if (instr_is_comptime(casted_value) && instr_is_comptime(casted_ptr)) { IrInstGen *result = ir_analyze_store_ptr(ira, &instruction->base.base, casted_ptr, value, false); result->value->type = ira->codegen->builtin_types.entry_void; diff --git a/test/stage1/behavior/atomics.zig b/test/stage1/behavior/atomics.zig index bda0a8469c..edc712d85b 100644 --- a/test/stage1/behavior/atomics.zig +++ b/test/stage1/behavior/atomics.zig @@ -162,12 +162,23 @@ fn testAtomicRmwFloat() void { expect(x == 4); } -test "atomics with bool" { - var x = false; - @atomicStore(bool, &x, true, .SeqCst); - expect(x == true); - expect(@atomicLoad(bool, &x, .SeqCst) == true); - expect(@atomicRmw(bool, &x, .Xchg, false, .SeqCst) == true); - expect(@cmpxchgStrong(bool, &x, false, true, .SeqCst, .SeqCst) == null); - expect(@cmpxchgStrong(bool, &x, false, true, .SeqCst, .SeqCst).? == true); +test "atomics with different types" { + // testAtomicsWithType(bool, true, false); + // inline for (.{ u1, i5, u33 }) |T| { + // var x: T = 0; + // testAtomicsWithType(T, 0, 1); + // } + testAtomicsWithType(u0, 0, 0); + testAtomicsWithType(i0, 0, 0); +} + +fn testAtomicsWithType(comptime T: type, a: T, b: T) void { + var x: T = b; + @atomicStore(T, &x, a, .SeqCst); + expect(x == a); + expect(@atomicLoad(T, &x, .SeqCst) == a); + expect(@atomicRmw(T, &x, .Xchg, b, .SeqCst) == a); + expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst) == null); + if (@sizeOf(T) != 0) + expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst).? == a); }