| ... | @@ -78,7 +78,6 @@ const LoopDepth = u16; | ... | @@ -78,7 +78,6 @@ const LoopDepth = u16; |
| 78 | const Local = struct { | 78 | const Local = struct { |
| 79 | cty_idx: CType.Index, | 79 | cty_idx: CType.Index, |
| 80 | alignas: CType.AlignAs, | 80 | alignas: CType.AlignAs, |
| 81 | is_in_clone: bool, | | |
| 82 | | 81 | |
| 83 | pub fn getType(local: Local) LocalType { | 82 | pub fn getType(local: Local) LocalType { |
| 84 | return .{ .cty_idx = local.cty_idx, .alignas = local.alignas }; | 83 | return .{ .cty_idx = local.cty_idx, .alignas = local.alignas }; |
| ... | @@ -275,16 +274,13 @@ pub const Function = struct { | ... | @@ -275,16 +274,13 @@ pub const Function = struct { |
| 275 | /// All the locals, to be emitted at the top of the function. | 274 | /// All the locals, to be emitted at the top of the function. |
| 276 | locals: std.ArrayListUnmanaged(Local) = .{}, | 275 | locals: std.ArrayListUnmanaged(Local) = .{}, |
| 277 | /// Which locals are available for reuse, based on Type. | 276 | /// Which locals are available for reuse, based on Type. |
| 278 | /// Only locals in the last stack entry are available for reuse, | | |
| 279 | /// other entries will become available on loop exit. | | |
| 280 | free_locals_map: LocalsMap = .{}, | 277 | free_locals_map: LocalsMap = .{}, |
| 281 | is_in_clone: bool = false, | | |
| 282 | /// Locals which will not be freed by Liveness. This is used after a | 278 | /// Locals which will not be freed by Liveness. This is used after a |
| 283 | /// Function body is lowered in order to make `free_locals_map` have | 279 | /// Function body is lowered in order to make `free_locals_map` have |
| 284 | /// 100% of the locals within so that it can be used to render the block | 280 | /// 100% of the locals within so that it can be used to render the block |
| 285 | /// of variable declarations at the top of a function, sorted descending | 281 | /// of variable declarations at the top of a function, sorted descending |
| 286 | /// by type alignment. | 282 | /// by type alignment. |
| 287 | /// The value is whether the alloc is static or not. | 283 | /// The value is whether the alloc needs to be emitted in the header. |
| 288 | allocs: std.AutoArrayHashMapUnmanaged(LocalIndex, bool) = .{}, | 284 | allocs: std.AutoArrayHashMapUnmanaged(LocalIndex, bool) = .{}, |
| 289 | /// Needed for memory used by the keys of free_locals_map entries. | 285 | /// Needed for memory used by the keys of free_locals_map entries. |
| 290 | arena: std.heap.ArenaAllocator, | 286 | arena: std.heap.ArenaAllocator, |
| ... | @@ -302,7 +298,7 @@ pub const Function = struct { | ... | @@ -302,7 +298,7 @@ pub const Function = struct { |
| 302 | const alignment = 0; | 298 | const alignment = 0; |
| 303 | const decl_c_value = try f.allocLocalValue(ty, alignment); | 299 | const decl_c_value = try f.allocLocalValue(ty, alignment); |
| 304 | const gpa = f.object.dg.gpa; | 300 | const gpa = f.object.dg.gpa; |
| 305 | try f.allocs.put(gpa, decl_c_value.new_local, true); | 301 | try f.allocs.put(gpa, decl_c_value.new_local, false); |
| 306 | try writer.writeAll("static "); | 302 | try writer.writeAll("static "); |
| 307 | try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, alignment, .complete); | 303 | try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, alignment, .complete); |
| 308 | try writer.writeAll(" = "); | 304 | try writer.writeAll(" = "); |
| ... | @@ -323,14 +319,15 @@ pub const Function = struct { | ... | @@ -323,14 +319,15 @@ pub const Function = struct { |
| 323 | }; | 319 | }; |
| 324 | } | 320 | } |
| 325 | | 321 | |
| 326 | /// Skips the reuse logic. | 322 | /// Skips the reuse logic. This function should be used for any persistent allocation, i.e. |
| | 323 | /// those which go into `allocs`. This function does not add the resulting local into `allocs`; |
| | 324 | /// that responsibility lies with the caller. |
| 327 | fn allocLocalValue(f: *Function, ty: Type, alignment: u32) !CValue { | 325 | fn allocLocalValue(f: *Function, ty: Type, alignment: u32) !CValue { |
| 328 | const gpa = f.object.dg.gpa; | 326 | const gpa = f.object.dg.gpa; |
| 329 | const target = f.object.dg.module.getTarget(); | 327 | const target = f.object.dg.module.getTarget(); |
| 330 | try f.locals.append(gpa, .{ | 328 | try f.locals.append(gpa, .{ |
| 331 | .cty_idx = try f.typeToIndex(ty, .complete), | 329 | .cty_idx = try f.typeToIndex(ty, .complete), |
| 332 | .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(target)), | 330 | .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(target)), |
| 333 | .is_in_clone = f.is_in_clone, | | |
| 334 | }); | 331 | }); |
| 335 | return .{ .new_local = @intCast(LocalIndex, f.locals.items.len - 1) }; | 332 | return .{ .new_local = @intCast(LocalIndex, f.locals.items.len - 1) }; |
| 336 | } | 333 | } |
| ... | @@ -341,7 +338,8 @@ pub const Function = struct { | ... | @@ -341,7 +338,8 @@ pub const Function = struct { |
| 341 | return result; | 338 | return result; |
| 342 | } | 339 | } |
| 343 | | 340 | |
| 344 | /// Only allocates the local; does not print anything. | 341 | /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should |
| | 342 | /// not be used for persistent locals (i.e. those in `allocs`). |
| 345 | fn allocAlignedLocal(f: *Function, ty: Type, _: CQualifiers, alignment: u32) !CValue { | 343 | fn allocAlignedLocal(f: *Function, ty: Type, _: CQualifiers, alignment: u32) !CValue { |
| 346 | const target = f.object.dg.module.getTarget(); | 344 | const target = f.object.dg.module.getTarget(); |
| 347 | if (f.free_locals_map.getPtr(.{ | 345 | if (f.free_locals_map.getPtr(.{ |
| ... | @@ -2586,7 +2584,7 @@ pub fn genFunc(f: *Function) !void { | ... | @@ -2586,7 +2584,7 @@ pub fn genFunc(f: *Function) !void { |
| 2586 | f.free_locals_map.clearRetainingCapacity(); | 2584 | f.free_locals_map.clearRetainingCapacity(); |
| 2587 | | 2585 | |
| 2588 | const main_body = f.air.getMainBody(); | 2586 | const main_body = f.air.getMainBody(); |
| 2589 | try genBody(f, main_body); | 2587 | try genBodyResolveState(f, undefined, &.{}, main_body, false); |
| 2590 | | 2588 | |
| 2591 | try o.indent_writer.insertNewline(); | 2589 | try o.indent_writer.insertNewline(); |
| 2592 | | 2590 | |
| ... | @@ -2597,8 +2595,8 @@ pub fn genFunc(f: *Function) !void { | ... | @@ -2597,8 +2595,8 @@ pub fn genFunc(f: *Function) !void { |
| 2597 | // alignment, descending. | 2595 | // alignment, descending. |
| 2598 | const free_locals = &f.free_locals_map; | 2596 | const free_locals = &f.free_locals_map; |
| 2599 | assert(f.value_map.count() == 0); // there must not be any unfreed locals | 2597 | assert(f.value_map.count() == 0); // there must not be any unfreed locals |
| 2600 | for (f.allocs.keys(), f.allocs.values()) |local_index, value| { | 2598 | for (f.allocs.keys(), f.allocs.values()) |local_index, should_emit| { |
| 2601 | if (value) continue; // static | 2599 | if (!should_emit) continue; |
| 2602 | const local = f.locals.items[local_index]; | 2600 | const local = f.locals.items[local_index]; |
| 2603 | log.debug("inserting local {d} into free_locals", .{local_index}); | 2601 | log.debug("inserting local {d} into free_locals", .{local_index}); |
| 2604 | const gop = try free_locals.getOrPut(gpa, local.getType()); | 2602 | const gop = try free_locals.getOrPut(gpa, local.getType()); |
| ... | @@ -2715,6 +2713,10 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { | ... | @@ -2715,6 +2713,10 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { |
| 2715 | } | 2713 | } |
| 2716 | } | 2714 | } |
| 2717 | | 2715 | |
| | 2716 | /// Generate code for an entire body which ends with a `noreturn` instruction. The states of |
| | 2717 | /// `value_map` and `free_locals_map` are undefined after the generation, and new locals may not |
| | 2718 | /// have been added to `free_locals_map`. For a version of this function that restores this state, |
| | 2719 | /// see `genBodyResolveState`. |
| 2718 | fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void { | 2720 | fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void { |
| 2719 | const writer = f.object.writer(); | 2721 | const writer = f.object.writer(); |
| 2720 | if (body.len == 0) { | 2722 | if (body.len == 0) { |
| ... | @@ -2728,10 +2730,69 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO | ... | @@ -2728,10 +2730,69 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 2728 | } | 2730 | } |
| 2729 | } | 2731 | } |
| 2730 | | 2732 | |
| | 2733 | /// Generate code for an entire body which ends with a `noreturn` instruction. The states of |
| | 2734 | /// `value_map` and `free_locals_map` are restored to their original values, and any non-allocated |
| | 2735 | /// locals introduced within the body are correctly added to `free_locals_map`. Operands in |
| | 2736 | /// `leading_deaths` have their deaths processed before the body is generated. |
| | 2737 | /// A scope is introduced (using braces) only if `inner` is `false`. |
| | 2738 | /// If `leading_deaths` is empty, `inst` may be `undefined`. |
| | 2739 | fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []const Air.Inst.Index, body: []const Air.Inst.Index, inner: bool) error{ AnalysisFail, OutOfMemory }!void { |
| | 2740 | if (body.len == 0) { |
| | 2741 | // Don't go to the expense of cloning everything! |
| | 2742 | if (!inner) try f.object.writer().writeAll("{}"); |
| | 2743 | return; |
| | 2744 | } |
| | 2745 | |
| | 2746 | // TODO: we can probably avoid the copies in some other common cases too. |
| | 2747 | |
| | 2748 | const gpa = f.object.dg.gpa; |
| | 2749 | |
| | 2750 | // Save the original value_map and free_locals_map so that we can restore them after the body. |
| | 2751 | var old_value_map = try f.value_map.clone(); |
| | 2752 | defer old_value_map.deinit(); |
| | 2753 | var old_free_locals = try cloneFreeLocalsMap(gpa, &f.free_locals_map); |
| | 2754 | defer deinitFreeLocalsMap(gpa, &old_free_locals); |
| | 2755 | |
| | 2756 | // Remember how many locals there were before entering the body so that we can free any that |
| | 2757 | // were newly introduced. Any new locals must necessarily be logically free after the then |
| | 2758 | // branch is complete. |
| | 2759 | const pre_locals_len = @intCast(LocalIndex, f.locals.items.len); |
| | 2760 | |
| | 2761 | for (leading_deaths) |death| { |
| | 2762 | try die(f, inst, Air.indexToRef(death)); |
| | 2763 | } |
| | 2764 | |
| | 2765 | if (inner) { |
| | 2766 | try genBodyInner(f, body); |
| | 2767 | } else { |
| | 2768 | try genBody(f, body); |
| | 2769 | } |
| | 2770 | |
| | 2771 | f.value_map.deinit(); |
| | 2772 | f.value_map = old_value_map.move(); |
| | 2773 | deinitFreeLocalsMap(gpa, &f.free_locals_map); |
| | 2774 | f.free_locals_map = old_free_locals.move(); |
| | 2775 | |
| | 2776 | // Now, use the lengths we stored earlier to detect any locals the body generated, and free |
| | 2777 | // them, unless they were used to store allocs. |
| | 2778 | |
| | 2779 | for (pre_locals_len..f.locals.items.len) |local_i| { |
| | 2780 | const local_index = @intCast(LocalIndex, local_i); |
| | 2781 | if (f.allocs.contains(local_index)) { |
| | 2782 | continue; |
| | 2783 | } |
| | 2784 | try freeLocal(f, inst, local_index, 0); |
| | 2785 | } |
| | 2786 | } |
| | 2787 | |
| 2731 | fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void { | 2788 | fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void { |
| 2732 | const air_tags = f.air.instructions.items(.tag); | 2789 | const air_tags = f.air.instructions.items(.tag); |
| 2733 | | 2790 | |
| 2734 | for (body) |inst| { | 2791 | for (body) |inst| { |
| | 2792 | if (f.liveness.isUnused(inst) and !f.air.mustLower(inst)) { |
| | 2793 | continue; |
| | 2794 | } |
| | 2795 | |
| 2735 | const result_value = switch (air_tags[inst]) { | 2796 | const result_value = switch (air_tags[inst]) { |
| 2736 | // zig fmt: off | 2797 | // zig fmt: off |
| 2737 | .constant => unreachable, // excluded from function bodies | 2798 | .constant => unreachable, // excluded from function bodies |
| ... | @@ -3009,11 +3070,6 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, | ... | @@ -3009,11 +3070,6 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 3009 | fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: []const u8) !CValue { | 3070 | fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: []const u8) !CValue { |
| 3010 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 3071 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 3011 | | 3072 | |
| 3012 | if (f.liveness.isUnused(inst)) { | | |
| 3013 | try reap(f, inst, &.{ty_op.operand}); | | |
| 3014 | return .none; | | |
| 3015 | } | | |
| 3016 | | | |
| 3017 | const inst_ty = f.air.typeOfIndex(inst); | 3073 | const inst_ty = f.air.typeOfIndex(inst); |
| 3018 | const operand = try f.resolveInst(ty_op.operand); | 3074 | const operand = try f.resolveInst(ty_op.operand); |
| 3019 | try reap(f, inst, &.{ty_op.operand}); | 3075 | try reap(f, inst, &.{ty_op.operand}); |
| ... | @@ -3032,10 +3088,7 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [ | ... | @@ -3032,10 +3088,7 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [ |
| 3032 | fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | 3088 | fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3033 | const inst_ty = f.air.typeOfIndex(inst); | 3089 | const inst_ty = f.air.typeOfIndex(inst); |
| 3034 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 3090 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 3035 | const ptr_ty = f.air.typeOf(bin_op.lhs); | 3091 | if (!inst_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3036 | if ((!ptr_ty.isVolatilePtr() and f.liveness.isUnused(inst)) or | | |
| 3037 | !inst_ty.hasRuntimeBitsIgnoreComptime()) | | |
| 3038 | { | | |
| 3039 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 3092 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3040 | return .none; | 3093 | return .none; |
| 3041 | } | 3094 | } |
| ... | @@ -3074,11 +3127,6 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3074,11 +3127,6 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3074 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 3127 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 3075 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; | 3128 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3076 | | 3129 | |
| 3077 | if (f.liveness.isUnused(inst)) { | | |
| 3078 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | | |
| 3079 | return .none; | | |
| 3080 | } | | |
| 3081 | | | |
| 3082 | const inst_ty = f.air.typeOfIndex(inst); | 3130 | const inst_ty = f.air.typeOfIndex(inst); |
| 3083 | const ptr_ty = f.air.typeOf(bin_op.lhs); | 3131 | const ptr_ty = f.air.typeOf(bin_op.lhs); |
| 3084 | const child_ty = ptr_ty.childType(); | 3132 | const child_ty = ptr_ty.childType(); |
| ... | @@ -3116,10 +3164,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3116,10 +3164,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3116 | fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | 3164 | fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3117 | const inst_ty = f.air.typeOfIndex(inst); | 3165 | const inst_ty = f.air.typeOfIndex(inst); |
| 3118 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 3166 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 3119 | const slice_ty = f.air.typeOf(bin_op.lhs); | 3167 | if (!inst_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3120 | if ((!slice_ty.isVolatilePtr() and f.liveness.isUnused(inst)) or | | |
| 3121 | !inst_ty.hasRuntimeBitsIgnoreComptime()) | | |
| 3122 | { | | |
| 3123 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 3168 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3124 | return .none; | 3169 | return .none; |
| 3125 | } | 3170 | } |
| ... | @@ -3158,11 +3203,6 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3158,11 +3203,6 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3158 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 3203 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 3159 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; | 3204 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3160 | | 3205 | |
| 3161 | if (f.liveness.isUnused(inst)) { | | |
| 3162 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | | |
| 3163 | return .none; | | |
| 3164 | } | | |
| 3165 | | | |
| 3166 | const slice_ty = f.air.typeOf(bin_op.lhs); | 3206 | const slice_ty = f.air.typeOf(bin_op.lhs); |
| 3167 | const child_ty = slice_ty.elemType2(); | 3207 | const child_ty = slice_ty.elemType2(); |
| 3168 | const slice = try f.resolveInst(bin_op.lhs); | 3208 | const slice = try f.resolveInst(bin_op.lhs); |
| ... | @@ -3188,7 +3228,7 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3188,7 +3228,7 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3188 | fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | 3228 | fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3189 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 3229 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 3190 | const inst_ty = f.air.typeOfIndex(inst); | 3230 | const inst_ty = f.air.typeOfIndex(inst); |
| 3191 | if (f.liveness.isUnused(inst) or !inst_ty.hasRuntimeBitsIgnoreComptime()) { | 3231 | if (!inst_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3192 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 3232 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3193 | return .none; | 3233 | return .none; |
| 3194 | } | 3234 | } |
| ... | @@ -3224,40 +3264,34 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3224,40 +3264,34 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3224 | } | 3264 | } |
| 3225 | | 3265 | |
| 3226 | fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { | 3266 | fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3227 | if (f.liveness.isUnused(inst)) return .none; | | |
| 3228 | | | |
| 3229 | const inst_ty = f.air.typeOfIndex(inst); | 3267 | const inst_ty = f.air.typeOfIndex(inst); |
| 3230 | const elem_type = inst_ty.elemType(); | 3268 | const elem_type = inst_ty.elemType(); |
| 3231 | if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime()) return .{ .undef = inst_ty }; | 3269 | if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime()) return .{ .undef = inst_ty }; |
| 3232 | | 3270 | |
| 3233 | const target = f.object.dg.module.getTarget(); | 3271 | const target = f.object.dg.module.getTarget(); |
| 3234 | const local = try f.allocAlignedLocal( | 3272 | const local = try f.allocLocalValue( |
| 3235 | elem_type, | 3273 | elem_type, |
| 3236 | CQualifiers.init(.{ .@"const" = inst_ty.isConstPtr() }), | | |
| 3237 | inst_ty.ptrAlignment(target), | 3274 | inst_ty.ptrAlignment(target), |
| 3238 | ); | 3275 | ); |
| 3239 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); | 3276 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); |
| 3240 | const gpa = f.object.dg.module.gpa; | 3277 | const gpa = f.object.dg.module.gpa; |
| 3241 | try f.allocs.put(gpa, local.new_local, false); | 3278 | try f.allocs.put(gpa, local.new_local, true); |
| 3242 | return .{ .local_ref = local.new_local }; | 3279 | return .{ .local_ref = local.new_local }; |
| 3243 | } | 3280 | } |
| 3244 | | 3281 | |
| 3245 | fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { | 3282 | fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3246 | if (f.liveness.isUnused(inst)) return .none; | | |
| 3247 | | | |
| 3248 | const inst_ty = f.air.typeOfIndex(inst); | 3283 | const inst_ty = f.air.typeOfIndex(inst); |
| 3249 | const elem_ty = inst_ty.elemType(); | 3284 | const elem_ty = inst_ty.elemType(); |
| 3250 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime()) return .{ .undef = inst_ty }; | 3285 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime()) return .{ .undef = inst_ty }; |
| 3251 | | 3286 | |
| 3252 | const target = f.object.dg.module.getTarget(); | 3287 | const target = f.object.dg.module.getTarget(); |
| 3253 | const local = try f.allocAlignedLocal( | 3288 | const local = try f.allocLocalValue( |
| 3254 | elem_ty, | 3289 | elem_ty, |
| 3255 | CQualifiers.init(.{ .@"const" = inst_ty.isConstPtr() }), | | |
| 3256 | inst_ty.ptrAlignment(target), | 3290 | inst_ty.ptrAlignment(target), |
| 3257 | ); | 3291 | ); |
| 3258 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); | 3292 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); |
| 3259 | const gpa = f.object.dg.module.gpa; | 3293 | const gpa = f.object.dg.module.gpa; |
| 3260 | try f.allocs.put(gpa, local.new_local, false); | 3294 | try f.allocs.put(gpa, local.new_local, true); |
| 3261 | return .{ .local_ref = local.new_local }; | 3295 | return .{ .local_ref = local.new_local }; |
| 3262 | } | 3296 | } |
| 3263 | | 3297 | |
| ... | @@ -3293,9 +3327,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3293,9 +3327,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3293 | const ptr_info = ptr_scalar_ty.ptrInfo().data; | 3327 | const ptr_info = ptr_scalar_ty.ptrInfo().data; |
| 3294 | const src_ty = ptr_info.pointee_type; | 3328 | const src_ty = ptr_info.pointee_type; |
| 3295 | | 3329 | |
| 3296 | if (!src_ty.hasRuntimeBitsIgnoreComptime() or | 3330 | if (!src_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3297 | (!ptr_info.@"volatile" and f.liveness.isUnused(inst))) | | |
| 3298 | { | | |
| 3299 | try reap(f, inst, &.{ty_op.operand}); | 3331 | try reap(f, inst, &.{ty_op.operand}); |
| 3300 | return .none; | 3332 | return .none; |
| 3301 | } | 3333 | } |
| ... | @@ -3442,11 +3474,6 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { | ... | @@ -3442,11 +3474,6 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { |
| 3442 | fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { | 3474 | fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3443 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 3475 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 3444 | | 3476 | |
| 3445 | if (f.liveness.isUnused(inst)) { | | |
| 3446 | try reap(f, inst, &.{ty_op.operand}); | | |
| 3447 | return .none; | | |
| 3448 | } | | |
| 3449 | | | |
| 3450 | const operand = try f.resolveInst(ty_op.operand); | 3477 | const operand = try f.resolveInst(ty_op.operand); |
| 3451 | try reap(f, inst, &.{ty_op.operand}); | 3478 | try reap(f, inst, &.{ty_op.operand}); |
| 3452 | | 3479 | |
| ... | @@ -3470,10 +3497,6 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3470,10 +3497,6 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3470 | | 3497 | |
| 3471 | fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { | 3498 | fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3472 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 3499 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 3473 | if (f.liveness.isUnused(inst)) { | | |
| 3474 | try reap(f, inst, &.{ty_op.operand}); | | |
| 3475 | return .none; | | |
| 3476 | } | | |
| 3477 | | 3500 | |
| 3478 | const operand = try f.resolveInst(ty_op.operand); | 3501 | const operand = try f.resolveInst(ty_op.operand); |
| 3479 | try reap(f, inst, &.{ty_op.operand}); | 3502 | try reap(f, inst, &.{ty_op.operand}); |
| ... | @@ -3569,10 +3592,6 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3569,10 +3592,6 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3569 | | 3592 | |
| 3570 | fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue { | 3593 | fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3571 | const un_op = f.air.instructions.items(.data)[inst].un_op; | 3594 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 3572 | if (f.liveness.isUnused(inst)) { | | |
| 3573 | try reap(f, inst, &.{un_op}); | | |
| 3574 | return .none; | | |
| 3575 | } | | |
| 3576 | const operand = try f.resolveInst(un_op); | 3595 | const operand = try f.resolveInst(un_op); |
| 3577 | try reap(f, inst, &.{un_op}); | 3596 | try reap(f, inst, &.{un_op}); |
| 3578 | const writer = f.object.writer(); | 3597 | const writer = f.object.writer(); |
| ... | @@ -3746,11 +3765,6 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: | ... | @@ -3746,11 +3765,6 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: |
| 3746 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 3765 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 3747 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; | 3766 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3748 | | 3767 | |
| 3749 | if (f.liveness.isUnused(inst)) { | | |
| 3750 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | | |
| 3751 | return .none; | | |
| 3752 | } | | |
| 3753 | | | |
| 3754 | const lhs = try f.resolveInst(bin_op.lhs); | 3768 | const lhs = try f.resolveInst(bin_op.lhs); |
| 3755 | const rhs = try f.resolveInst(bin_op.rhs); | 3769 | const rhs = try f.resolveInst(bin_op.rhs); |
| 3756 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 3770 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| ... | @@ -3790,11 +3804,6 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3790,11 +3804,6 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3790 | const scalar_ty = operand_ty.scalarType(); | 3804 | const scalar_ty = operand_ty.scalarType(); |
| 3791 | if (scalar_ty.tag() != .bool) return try airUnBuiltinCall(f, inst, "not", .bits); | 3805 | if (scalar_ty.tag() != .bool) return try airUnBuiltinCall(f, inst, "not", .bits); |
| 3792 | | 3806 | |
| 3793 | if (f.liveness.isUnused(inst)) { | | |
| 3794 | try reap(f, inst, &.{ty_op.operand}); | | |
| 3795 | return .none; | | |
| 3796 | } | | |
| 3797 | | | |
| 3798 | const op = try f.resolveInst(ty_op.operand); | 3807 | const op = try f.resolveInst(ty_op.operand); |
| 3799 | try reap(f, inst, &.{ty_op.operand}); | 3808 | try reap(f, inst, &.{ty_op.operand}); |
| 3800 | | 3809 | |
| ... | @@ -3829,11 +3838,6 @@ fn airBinOp( | ... | @@ -3829,11 +3838,6 @@ fn airBinOp( |
| 3829 | if ((scalar_ty.isInt() and scalar_ty.bitSize(target) > 64) or scalar_ty.isRuntimeFloat()) | 3838 | if ((scalar_ty.isInt() and scalar_ty.bitSize(target) > 64) or scalar_ty.isRuntimeFloat()) |
| 3830 | return try airBinBuiltinCall(f, inst, operation, info); | 3839 | return try airBinBuiltinCall(f, inst, operation, info); |
| 3831 | | 3840 | |
| 3832 | if (f.liveness.isUnused(inst)) { | | |
| 3833 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | | |
| 3834 | return .none; | | |
| 3835 | } | | |
| 3836 | | | |
| 3837 | const lhs = try f.resolveInst(bin_op.lhs); | 3841 | const lhs = try f.resolveInst(bin_op.lhs); |
| 3838 | const rhs = try f.resolveInst(bin_op.rhs); | 3842 | const rhs = try f.resolveInst(bin_op.rhs); |
| 3839 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 3843 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| ... | @@ -3865,11 +3869,6 @@ fn airCmpOp( | ... | @@ -3865,11 +3869,6 @@ fn airCmpOp( |
| 3865 | data: anytype, | 3869 | data: anytype, |
| 3866 | operator: std.math.CompareOperator, | 3870 | operator: std.math.CompareOperator, |
| 3867 | ) !CValue { | 3871 | ) !CValue { |
| 3868 | if (f.liveness.isUnused(inst)) { | | |
| 3869 | try reap(f, inst, &.{ data.lhs, data.rhs }); | | |
| 3870 | return .none; | | |
| 3871 | } | | |
| 3872 | | | |
| 3873 | const operand_ty = f.air.typeOf(data.lhs); | 3872 | const operand_ty = f.air.typeOf(data.lhs); |
| 3874 | const scalar_ty = operand_ty.scalarType(); | 3873 | const scalar_ty = operand_ty.scalarType(); |
| 3875 | | 3874 | |
| ... | @@ -3918,11 +3917,6 @@ fn airEquality( | ... | @@ -3918,11 +3917,6 @@ fn airEquality( |
| 3918 | ) !CValue { | 3917 | ) !CValue { |
| 3919 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 3918 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 3920 | | 3919 | |
| 3921 | if (f.liveness.isUnused(inst)) { | | |
| 3922 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | | |
| 3923 | return .none; | | |
| 3924 | } | | |
| 3925 | | | |
| 3926 | const operand_ty = f.air.typeOf(bin_op.lhs); | 3920 | const operand_ty = f.air.typeOf(bin_op.lhs); |
| 3927 | const target = f.object.dg.module.getTarget(); | 3921 | const target = f.object.dg.module.getTarget(); |
| 3928 | const operand_bits = operand_ty.bitSize(target); | 3922 | const operand_bits = operand_ty.bitSize(target); |
| ... | @@ -3987,11 +3981,6 @@ fn airEquality( | ... | @@ -3987,11 +3981,6 @@ fn airEquality( |
| 3987 | fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { | 3981 | fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3988 | const un_op = f.air.instructions.items(.data)[inst].un_op; | 3982 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 3989 | | 3983 | |
| 3990 | if (f.liveness.isUnused(inst)) { | | |
| 3991 | try reap(f, inst, &.{un_op}); | | |
| 3992 | return .none; | | |
| 3993 | } | | |
| 3994 | | | |
| 3995 | const inst_ty = f.air.typeOfIndex(inst); | 3984 | const inst_ty = f.air.typeOfIndex(inst); |
| 3996 | const operand = try f.resolveInst(un_op); | 3985 | const operand = try f.resolveInst(un_op); |
| 3997 | try reap(f, inst, &.{un_op}); | 3986 | try reap(f, inst, &.{un_op}); |
| ... | @@ -4008,10 +3997,6 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4008,10 +3997,6 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4008 | fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { | 3997 | fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 4009 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 3998 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 4010 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; | 3999 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 4011 | if (f.liveness.isUnused(inst)) { | | |
| 4012 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | | |
| 4013 | return .none; | | |
| 4014 | } | | |
| 4015 | | 4000 | |
| 4016 | const lhs = try f.resolveInst(bin_op.lhs); | 4001 | const lhs = try f.resolveInst(bin_op.lhs); |
| 4017 | const rhs = try f.resolveInst(bin_op.rhs); | 4002 | const rhs = try f.resolveInst(bin_op.rhs); |
| ... | @@ -4059,11 +4044,6 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { | ... | @@ -4059,11 +4044,6 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 4059 | fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue { | 4044 | fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue { |
| 4060 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 4045 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 4061 | | 4046 | |
| 4062 | if (f.liveness.isUnused(inst)) { | | |
| 4063 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | | |
| 4064 | return .none; | | |
| 4065 | } | | |
| 4066 | | | |
| 4067 | const inst_ty = f.air.typeOfIndex(inst); | 4047 | const inst_ty = f.air.typeOfIndex(inst); |
| 4068 | const inst_scalar_ty = inst_ty.scalarType(); | 4048 | const inst_scalar_ty = inst_ty.scalarType(); |
| 4069 | | 4049 | |
| ... | @@ -4107,11 +4087,6 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4107,11 +4087,6 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4107 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 4087 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 4108 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; | 4088 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 4109 | | 4089 | |
| 4110 | if (f.liveness.isUnused(inst)) { | | |
| 4111 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | | |
| 4112 | return .none; | | |
| 4113 | } | | |
| 4114 | | | |
| 4115 | const ptr = try f.resolveInst(bin_op.lhs); | 4090 | const ptr = try f.resolveInst(bin_op.lhs); |
| 4116 | const len = try f.resolveInst(bin_op.rhs); | 4091 | const len = try f.resolveInst(bin_op.rhs); |
| 4117 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 4092 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| ... | @@ -4316,6 +4291,7 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4316,6 +4291,7 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4316 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 4291 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 4317 | const extra = f.air.extraData(Air.Block, ty_pl.payload); | 4292 | const extra = f.air.extraData(Air.Block, ty_pl.payload); |
| 4318 | const body = f.air.extra[extra.end..][0..extra.data.body_len]; | 4293 | const body = f.air.extra[extra.end..][0..extra.data.body_len]; |
| | 4294 | const liveness_block = f.liveness.getBlock(inst); |
| 4319 | | 4295 | |
| 4320 | const block_id: usize = f.next_block_index; | 4296 | const block_id: usize = f.next_block_index; |
| 4321 | f.next_block_index += 1; | 4297 | f.next_block_index += 1; |
| ... | @@ -4332,7 +4308,15 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4332,7 +4308,15 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4332 | .result = result, | 4308 | .result = result, |
| 4333 | }); | 4309 | }); |
| 4334 | | 4310 | |
| 4335 | try genBodyInner(f, body); | 4311 | try genBodyResolveState(f, inst, &.{}, body, true); |
| | 4312 | |
| | 4313 | assert(f.blocks.remove(inst)); |
| | 4314 | |
| | 4315 | // The body might result in some values we had beforehand being killed |
| | 4316 | for (liveness_block.deaths) |death| { |
| | 4317 | try die(f, inst, Air.indexToRef(death)); |
| | 4318 | } |
| | 4319 | |
| 4336 | try f.object.indent_writer.insertNewline(); | 4320 | try f.object.indent_writer.insertNewline(); |
| 4337 | // label might be unused, add a dummy goto | 4321 | // label might be unused, add a dummy goto |
| 4338 | // label must be followed by an expression, add an empty one. | 4322 | // label must be followed by an expression, add an empty one. |
| ... | @@ -4366,6 +4350,7 @@ fn lowerTry( | ... | @@ -4366,6 +4350,7 @@ fn lowerTry( |
| 4366 | ) !CValue { | 4350 | ) !CValue { |
| 4367 | const err_union = try f.resolveInst(operand); | 4351 | const err_union = try f.resolveInst(operand); |
| 4368 | const result_ty = f.air.typeOfIndex(inst); | 4352 | const result_ty = f.air.typeOfIndex(inst); |
| | 4353 | const liveness_condbr = f.liveness.getCondBr(inst); |
| 4369 | const writer = f.object.writer(); | 4354 | const writer = f.object.writer(); |
| 4370 | const payload_ty = err_union_ty.errorUnionPayload(); | 4355 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 4371 | const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(); | 4356 | const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(); |
| ... | @@ -4389,10 +4374,15 @@ fn lowerTry( | ... | @@ -4389,10 +4374,15 @@ fn lowerTry( |
| 4389 | } | 4374 | } |
| 4390 | try writer.writeByte(')'); | 4375 | try writer.writeByte(')'); |
| 4391 | | 4376 | |
| 4392 | try genBody(f, body); | 4377 | try genBodyResolveState(f, inst, liveness_condbr.else_deaths, body, false); |
| 4393 | try f.object.indent_writer.insertNewline(); | 4378 | try f.object.indent_writer.insertNewline(); |
| 4394 | } | 4379 | } |
| 4395 | | 4380 | |
| | 4381 | // Now we have the "then branch" (in terms of the liveness data); process any deaths. |
| | 4382 | for (liveness_condbr.then_deaths) |death| { |
| | 4383 | try die(f, inst, Air.indexToRef(death)); |
| | 4384 | } |
| | 4385 | |
| 4396 | if (!payload_has_bits) { | 4386 | if (!payload_has_bits) { |
| 4397 | if (!operand_is_ptr) { | 4387 | if (!operand_is_ptr) { |
| 4398 | return .none; | 4388 | return .none; |
| ... | @@ -4466,10 +4456,6 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4466,10 +4456,6 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4466 | fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { | 4456 | fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4467 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 4457 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 4468 | const dest_ty = f.air.typeOfIndex(inst); | 4458 | const dest_ty = f.air.typeOfIndex(inst); |
| 4469 | if (f.liveness.isUnused(inst)) { | | |
| 4470 | try reap(f, inst, &.{ty_op.operand}); | | |
| 4471 | return .none; | | |
| 4472 | } | | |
| 4473 | | 4459 | |
| 4474 | const operand = try f.resolveInst(ty_op.operand); | 4460 | const operand = try f.resolveInst(ty_op.operand); |
| 4475 | try reap(f, inst, &.{ty_op.operand}); | 4461 | try reap(f, inst, &.{ty_op.operand}); |
| ... | @@ -4593,7 +4579,6 @@ fn airBreakpoint(writer: anytype) !CValue { | ... | @@ -4593,7 +4579,6 @@ fn airBreakpoint(writer: anytype) !CValue { |
| 4593 | } | 4579 | } |
| 4594 | | 4580 | |
| 4595 | fn airRetAddr(f: *Function, inst: Air.Inst.Index) !CValue { | 4581 | fn airRetAddr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4596 | if (f.liveness.isUnused(inst)) return .none; | | |
| 4597 | const writer = f.object.writer(); | 4582 | const writer = f.object.writer(); |
| 4598 | const local = try f.allocLocal(inst, Type.usize); | 4583 | const local = try f.allocLocal(inst, Type.usize); |
| 4599 | try f.writeCValue(writer, local, .Other); | 4584 | try f.writeCValue(writer, local, .Other); |
| ... | @@ -4604,7 +4589,6 @@ fn airRetAddr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4604,7 +4589,6 @@ fn airRetAddr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4604 | } | 4589 | } |
| 4605 | | 4590 | |
| 4606 | fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue { | 4591 | fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4607 | if (f.liveness.isUnused(inst)) return .none; | | |
| 4608 | const writer = f.object.writer(); | 4592 | const writer = f.object.writer(); |
| 4609 | const local = try f.allocLocal(inst, Type.usize); | 4593 | const local = try f.allocLocal(inst, Type.usize); |
| 4610 | try f.writeCValue(writer, local, .Other); | 4594 | try f.writeCValue(writer, local, .Other); |
| ... | @@ -4640,7 +4624,7 @@ fn airLoop(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4640,7 +4624,7 @@ fn airLoop(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4640 | const writer = f.object.writer(); | 4624 | const writer = f.object.writer(); |
| 4641 | | 4625 | |
| 4642 | try writer.writeAll("for (;;) "); | 4626 | try writer.writeAll("for (;;) "); |
| 4643 | try genBody(f, body); | 4627 | try genBody(f, body); // no need to restore state, we're noreturn |
| 4644 | try writer.writeByte('\n'); | 4628 | try writer.writeByte('\n'); |
| 4645 | | 4629 | |
| 4646 | return .none; | 4630 | return .none; |
| ... | @@ -4656,61 +4640,24 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4656,61 +4640,24 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4656 | const liveness_condbr = f.liveness.getCondBr(inst); | 4640 | const liveness_condbr = f.liveness.getCondBr(inst); |
| 4657 | const writer = f.object.writer(); | 4641 | const writer = f.object.writer(); |
| 4658 | | 4642 | |
| 4659 | // Keep using the original for the then branch; use a clone of the value | | |
| 4660 | // map for the else branch. | | |
| 4661 | const gpa = f.object.dg.gpa; | | |
| 4662 | var cloned_map = try f.value_map.clone(); | | |
| 4663 | defer cloned_map.deinit(); | | |
| 4664 | var cloned_frees = try cloneFreeLocalsMap(gpa, &f.free_locals_map); | | |
| 4665 | defer deinitFreeLocalsMap(gpa, &cloned_frees); | | |
| 4666 | | | |
| 4667 | // Remember how many locals there were before entering the then branch so | | |
| 4668 | // that we can notice and use them in the else branch. Any new locals must | | |
| 4669 | // necessarily be free already after the then branch is complete. | | |
| 4670 | const pre_locals_len = @intCast(LocalIndex, f.locals.items.len); | | |
| 4671 | // Remember how many allocs there were before entering the then branch so | | |
| 4672 | // that we can notice and make sure not to use them in the else branch. | | |
| 4673 | // Any new allocs must be removed from the free list. | | |
| 4674 | const pre_allocs_len = @intCast(LocalIndex, f.allocs.count()); | | |
| 4675 | const was_in_clone = f.is_in_clone; | | |
| 4676 | f.is_in_clone = true; | | |
| 4677 | | | |
| 4678 | for (liveness_condbr.then_deaths) |operand| { | | |
| 4679 | try die(f, inst, Air.indexToRef(operand)); | | |
| 4680 | } | | |
| 4681 | | | |
| 4682 | try writer.writeAll("if ("); | 4643 | try writer.writeAll("if ("); |
| 4683 | try f.writeCValue(writer, cond, .Other); | 4644 | try f.writeCValue(writer, cond, .Other); |
| 4684 | try writer.writeAll(") "); | 4645 | try writer.writeAll(") "); |
| 4685 | try genBody(f, then_body); | | |
| 4686 | | 4646 | |
| 4687 | // TODO: If body ends in goto, elide the else block? | 4647 | try genBodyResolveState(f, inst, liveness_condbr.then_deaths, then_body, false); |
| 4688 | const needs_else = then_body.len <= 0 or f.air.instructions.items(.tag)[then_body[then_body.len - 1]] != .br; | | |
| 4689 | if (needs_else) { | | |
| 4690 | try writer.writeAll(" else "); | | |
| 4691 | } else { | | |
| 4692 | try writer.writeByte('\n'); | | |
| 4693 | } | | |
| 4694 | | 4648 | |
| 4695 | f.value_map.deinit(); | 4649 | // We don't need to use `genBodyResolveState` for the else block, because this instruction is |
| 4696 | f.value_map = cloned_map.move(); | 4650 | // noreturn so must terminate a body, therefore we don't need to leave `value_map` or |
| 4697 | const free_locals = &f.free_locals_map; | 4651 | // `free_locals_map` well defined (our parent is responsible for doing that). |
| 4698 | deinitFreeLocalsMap(gpa, free_locals); | | |
| 4699 | free_locals.* = cloned_frees.move(); | | |
| 4700 | f.is_in_clone = was_in_clone; | | |
| 4701 | for (liveness_condbr.else_deaths) |operand| { | | |
| 4702 | try die(f, inst, Air.indexToRef(operand)); | | |
| 4703 | } | | |
| 4704 | | | |
| 4705 | try noticeBranchFrees(f, pre_locals_len, pre_allocs_len, inst); | | |
| 4706 | | 4652 | |
| 4707 | if (needs_else) { | 4653 | for (liveness_condbr.else_deaths) |death| { |
| 4708 | try genBody(f, else_body); | 4654 | try die(f, inst, Air.indexToRef(death)); |
| 4709 | } else { | | |
| 4710 | try genBodyInner(f, else_body); | | |
| 4711 | } | 4655 | } |
| 4712 | | 4656 | |
| 4713 | try f.object.indent_writer.insertNewline(); | 4657 | // We never actually need an else block, because our branches are noreturn so must (for |
| | 4658 | // instance) `br` to a block (label). |
| | 4659 | |
| | 4660 | try genBodyInner(f, else_body); |
| 4714 | | 4661 | |
| 4715 | return .none; | 4662 | return .none; |
| 4716 | } | 4663 | } |
| ... | @@ -4741,9 +4688,8 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4741,9 +4688,8 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4741 | const liveness = try f.liveness.getSwitchBr(gpa, inst, switch_br.data.cases_len + 1); | 4688 | const liveness = try f.liveness.getSwitchBr(gpa, inst, switch_br.data.cases_len + 1); |
| 4742 | defer gpa.free(liveness.deaths); | 4689 | defer gpa.free(liveness.deaths); |
| 4743 | | 4690 | |
| 4744 | // On the final iteration we do not clone the map. This ensures that | 4691 | // On the final iteration we do not need to fix any state. This is because, like in the `else` |
| 4745 | // lowering proceeds after the switch_br taking into account the | 4692 | // branch of a `cond_br`, our parent has to do it for this entire body anyway. |
| 4746 | // mutations to the liveness information. | | |
| 4747 | const last_case_i = switch_br.data.cases_len - @boolToInt(switch_br.data.else_body_len == 0); | 4693 | const last_case_i = switch_br.data.cases_len - @boolToInt(switch_br.data.else_body_len == 0); |
| 4748 | | 4694 | |
| 4749 | var extra_index: usize = switch_br.end; | 4695 | var extra_index: usize = switch_br.end; |
| ... | @@ -4767,56 +4713,23 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4767,56 +4713,23 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4767 | try writer.writeByte(' '); | 4713 | try writer.writeByte(' '); |
| 4768 | | 4714 | |
| 4769 | if (case_i != last_case_i) { | 4715 | if (case_i != last_case_i) { |
| 4770 | const old_value_map = f.value_map; | 4716 | try genBodyResolveState(f, inst, liveness.deaths[case_i], case_body, false); |
| 4771 | f.value_map = try old_value_map.clone(); | | |
| 4772 | var free_locals = &f.free_locals_map; | | |
| 4773 | const old_free_locals = free_locals.*; | | |
| 4774 | free_locals.* = try cloneFreeLocalsMap(gpa, free_locals); | | |
| 4775 | | | |
| 4776 | // Remember how many locals there were before entering each branch so that | | |
| 4777 | // we can notice and use them in subsequent branches. Any new locals must | | |
| 4778 | // necessarily be free already after the previous branch is complete. | | |
| 4779 | const pre_locals_len = @intCast(LocalIndex, f.locals.items.len); | | |
| 4780 | // Remember how many allocs there were before entering each branch so that | | |
| 4781 | // we can notice and make sure not to use them in subsequent branches. | | |
| 4782 | // Any new allocs must be removed from the free list. | | |
| 4783 | const pre_allocs_len = @intCast(LocalIndex, f.allocs.count()); | | |
| 4784 | const was_in_clone = f.is_in_clone; | | |
| 4785 | f.is_in_clone = true; | | |
| 4786 | | | |
| 4787 | { | | |
| 4788 | defer { | | |
| 4789 | f.is_in_clone = was_in_clone; | | |
| 4790 | f.value_map.deinit(); | | |
| 4791 | deinitFreeLocalsMap(gpa, free_locals); | | |
| 4792 | f.value_map = old_value_map; | | |
| 4793 | free_locals.* = old_free_locals; | | |
| 4794 | } | | |
| 4795 | | | |
| 4796 | for (liveness.deaths[case_i]) |operand| { | | |
| 4797 | try die(f, inst, Air.indexToRef(operand)); | | |
| 4798 | } | | |
| 4799 | | | |
| 4800 | try genBody(f, case_body); | | |
| 4801 | } | | |
| 4802 | | | |
| 4803 | try noticeBranchFrees(f, pre_locals_len, pre_allocs_len, inst); | | |
| 4804 | } else { | 4717 | } else { |
| 4805 | for (liveness.deaths[case_i]) |operand| { | 4718 | for (liveness.deaths[case_i]) |death| { |
| 4806 | try die(f, inst, Air.indexToRef(operand)); | 4719 | try die(f, inst, Air.indexToRef(death)); |
| 4807 | } | 4720 | } |
| 4808 | try genBody(f, case_body); | 4721 | try genBody(f, case_body); |
| 4809 | } | 4722 | } |
| 4810 | | 4723 | |
| 4811 | // The case body must be noreturn so we don't need to insert a break. | 4724 | // The case body must be noreturn so we don't need to insert a break. |
| 4812 | | | |
| 4813 | } | 4725 | } |
| 4814 | | 4726 | |
| 4815 | const else_body = f.air.extra[extra_index..][0..switch_br.data.else_body_len]; | 4727 | const else_body = f.air.extra[extra_index..][0..switch_br.data.else_body_len]; |
| 4816 | try f.object.indent_writer.insertNewline(); | 4728 | try f.object.indent_writer.insertNewline(); |
| 4817 | if (else_body.len > 0) { | 4729 | if (else_body.len > 0) { |
| 4818 | for (liveness.deaths[liveness.deaths.len - 1]) |operand| { | 4730 | // Note that this must be the last case (i.e. the `last_case_i` case was not hit above) |
| 4819 | try die(f, inst, Air.indexToRef(operand)); | 4731 | for (liveness.deaths[liveness.deaths.len - 1]) |death| { |
| | 4732 | try die(f, inst, Air.indexToRef(death)); |
| 4820 | } | 4733 | } |
| 4821 | try writer.writeAll("default: "); | 4734 | try writer.writeAll("default: "); |
| 4822 | try genBody(f, else_body); | 4735 | try genBody(f, else_body); |
| ... | @@ -4843,6 +4756,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4843,6 +4756,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4843 | const extra = f.air.extraData(Air.Asm, ty_pl.payload); | 4756 | const extra = f.air.extraData(Air.Asm, ty_pl.payload); |
| 4844 | const is_volatile = @truncate(u1, extra.data.flags >> 31) != 0; | 4757 | const is_volatile = @truncate(u1, extra.data.flags >> 31) != 0; |
| 4845 | const clobbers_len = @truncate(u31, extra.data.flags); | 4758 | const clobbers_len = @truncate(u31, extra.data.flags); |
| | 4759 | const gpa = f.object.dg.gpa; |
| 4846 | var extra_i: usize = extra.end; | 4760 | var extra_i: usize = extra.end; |
| 4847 | const outputs = @ptrCast([]const Air.Inst.Ref, f.air.extra[extra_i..][0..extra.data.outputs_len]); | 4761 | const outputs = @ptrCast([]const Air.Inst.Ref, f.air.extra[extra_i..][0..extra.data.outputs_len]); |
| 4848 | extra_i += outputs.len; | 4762 | extra_i += outputs.len; |
| ... | @@ -4850,8 +4764,6 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4850,8 +4764,6 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4850 | extra_i += inputs.len; | 4764 | extra_i += inputs.len; |
| 4851 | | 4765 | |
| 4852 | const result = result: { | 4766 | const result = result: { |
| 4853 | if (!is_volatile and f.liveness.isUnused(inst)) break :result .none; | | |
| 4854 | | | |
| 4855 | const writer = f.object.writer(); | 4767 | const writer = f.object.writer(); |
| 4856 | const inst_ty = f.air.typeOfIndex(inst); | 4768 | const inst_ty = f.air.typeOfIndex(inst); |
| 4857 | const local = if (inst_ty.hasRuntimeBitsIgnoreComptime()) local: { | 4769 | const local = if (inst_ty.hasRuntimeBitsIgnoreComptime()) local: { |
| ... | @@ -4887,6 +4799,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4887,6 +4799,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4887 | try writer.writeAll("register "); | 4799 | try writer.writeAll("register "); |
| 4888 | const alignment = 0; | 4800 | const alignment = 0; |
| 4889 | const local_value = try f.allocLocalValue(output_ty, alignment); | 4801 | const local_value = try f.allocLocalValue(output_ty, alignment); |
| | 4802 | try f.allocs.put(gpa, local_value.new_local, false); |
| 4890 | try f.object.dg.renderTypeAndName(writer, output_ty, local_value, .{}, alignment, .complete); | 4803 | try f.object.dg.renderTypeAndName(writer, output_ty, local_value, .{}, alignment, .complete); |
| 4891 | try writer.writeAll(" __asm(\""); | 4804 | try writer.writeAll(" __asm(\""); |
| 4892 | try writer.writeAll(constraint["={".len .. constraint.len - "}".len]); | 4805 | try writer.writeAll(constraint["={".len .. constraint.len - "}".len]); |
| ... | @@ -4919,6 +4832,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4919,6 +4832,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4919 | if (is_reg) try writer.writeAll("register "); | 4832 | if (is_reg) try writer.writeAll("register "); |
| 4920 | const alignment = 0; | 4833 | const alignment = 0; |
| 4921 | const local_value = try f.allocLocalValue(input_ty, alignment); | 4834 | const local_value = try f.allocLocalValue(input_ty, alignment); |
| | 4835 | try f.allocs.put(gpa, local_value.new_local, false); |
| 4922 | try f.object.dg.renderTypeAndName(writer, input_ty, local_value, Const, alignment, .complete); | 4836 | try f.object.dg.renderTypeAndName(writer, input_ty, local_value, Const, alignment, .complete); |
| 4923 | if (is_reg) { | 4837 | if (is_reg) { |
| 4924 | try writer.writeAll(" __asm(\""); | 4838 | try writer.writeAll(" __asm(\""); |
| ... | @@ -5101,11 +5015,6 @@ fn airIsNull( | ... | @@ -5101,11 +5015,6 @@ fn airIsNull( |
| 5101 | ) !CValue { | 5015 | ) !CValue { |
| 5102 | const un_op = f.air.instructions.items(.data)[inst].un_op; | 5016 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 5103 | | 5017 | |
| 5104 | if (f.liveness.isUnused(inst)) { | | |
| 5105 | try reap(f, inst, &.{un_op}); | | |
| 5106 | return .none; | | |
| 5107 | } | | |
| 5108 | | | |
| 5109 | const writer = f.object.writer(); | 5018 | const writer = f.object.writer(); |
| 5110 | const operand = try f.resolveInst(un_op); | 5019 | const operand = try f.resolveInst(un_op); |
| 5111 | try reap(f, inst, &.{un_op}); | 5020 | try reap(f, inst, &.{un_op}); |
| ... | @@ -5151,11 +5060,6 @@ fn airIsNull( | ... | @@ -5151,11 +5060,6 @@ fn airIsNull( |
| 5151 | fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { | 5060 | fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5152 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5061 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5153 | | 5062 | |
| 5154 | if (f.liveness.isUnused(inst)) { | | |
| 5155 | try reap(f, inst, &.{ty_op.operand}); | | |
| 5156 | return .none; | | |
| 5157 | } | | |
| 5158 | | | |
| 5159 | const operand = try f.resolveInst(ty_op.operand); | 5063 | const operand = try f.resolveInst(ty_op.operand); |
| 5160 | try reap(f, inst, &.{ty_op.operand}); | 5064 | try reap(f, inst, &.{ty_op.operand}); |
| 5161 | const opt_ty = f.air.typeOf(ty_op.operand); | 5065 | const opt_ty = f.air.typeOf(ty_op.operand); |
| ... | @@ -5203,11 +5107,6 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5203,11 +5107,6 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5203 | fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue { | 5107 | fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5204 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5108 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5205 | | 5109 | |
| 5206 | if (f.liveness.isUnused(inst)) { | | |
| 5207 | try reap(f, inst, &.{ty_op.operand}); | | |
| 5208 | return .none; | | |
| 5209 | } | | |
| 5210 | | | |
| 5211 | const writer = f.object.writer(); | 5110 | const writer = f.object.writer(); |
| 5212 | const operand = try f.resolveInst(ty_op.operand); | 5111 | const operand = try f.resolveInst(ty_op.operand); |
| 5213 | try reap(f, inst, &.{ty_op.operand}); | 5112 | try reap(f, inst, &.{ty_op.operand}); |
| ... | @@ -5337,11 +5236,6 @@ fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5337,11 +5236,6 @@ fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5337 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 5236 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 5338 | const extra = f.air.extraData(Air.StructField, ty_pl.payload).data; | 5237 | const extra = f.air.extraData(Air.StructField, ty_pl.payload).data; |
| 5339 | | 5238 | |
| 5340 | if (f.liveness.isUnused(inst)) { | | |
| 5341 | try reap(f, inst, &.{extra.struct_operand}); | | |
| 5342 | return .none; | | |
| 5343 | } | | |
| 5344 | | | |
| 5345 | const container_ptr_val = try f.resolveInst(extra.struct_operand); | 5239 | const container_ptr_val = try f.resolveInst(extra.struct_operand); |
| 5346 | try reap(f, inst, &.{extra.struct_operand}); | 5240 | try reap(f, inst, &.{extra.struct_operand}); |
| 5347 | const container_ptr_ty = f.air.typeOf(extra.struct_operand); | 5241 | const container_ptr_ty = f.air.typeOf(extra.struct_operand); |
| ... | @@ -5351,11 +5245,6 @@ fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5351,11 +5245,6 @@ fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5351 | fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue { | 5245 | fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue { |
| 5352 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5246 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5353 | | 5247 | |
| 5354 | if (f.liveness.isUnused(inst)) { | | |
| 5355 | try reap(f, inst, &.{ty_op.operand}); | | |
| 5356 | return .none; | | |
| 5357 | } | | |
| 5358 | | | |
| 5359 | const container_ptr_val = try f.resolveInst(ty_op.operand); | 5248 | const container_ptr_val = try f.resolveInst(ty_op.operand); |
| 5360 | try reap(f, inst, &.{ty_op.operand}); | 5249 | try reap(f, inst, &.{ty_op.operand}); |
| 5361 | const container_ptr_ty = f.air.typeOf(ty_op.operand); | 5250 | const container_ptr_ty = f.air.typeOf(ty_op.operand); |
| ... | @@ -5366,11 +5255,6 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5366,11 +5255,6 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5366 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 5255 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 5367 | const extra = f.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; | 5256 | const extra = f.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; |
| 5368 | | 5257 | |
| 5369 | if (f.liveness.isUnused(inst)) { | | |
| 5370 | try reap(f, inst, &.{extra.field_ptr}); | | |
| 5371 | return .none; | | |
| 5372 | } | | |
| 5373 | | | |
| 5374 | const target = f.object.dg.module.getTarget(); | 5258 | const target = f.object.dg.module.getTarget(); |
| 5375 | const container_ptr_ty = f.air.typeOfIndex(inst); | 5259 | const container_ptr_ty = f.air.typeOfIndex(inst); |
| 5376 | const container_ty = container_ptr_ty.childType(); | 5260 | const container_ty = container_ptr_ty.childType(); |
| ... | @@ -5489,11 +5373,6 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5489,11 +5373,6 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5489 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 5373 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 5490 | const extra = f.air.extraData(Air.StructField, ty_pl.payload).data; | 5374 | const extra = f.air.extraData(Air.StructField, ty_pl.payload).data; |
| 5491 | | 5375 | |
| 5492 | if (f.liveness.isUnused(inst)) { | | |
| 5493 | try reap(f, inst, &.{extra.struct_operand}); | | |
| 5494 | return .none; | | |
| 5495 | } | | |
| 5496 | | | |
| 5497 | const inst_ty = f.air.typeOfIndex(inst); | 5376 | const inst_ty = f.air.typeOfIndex(inst); |
| 5498 | if (!inst_ty.hasRuntimeBitsIgnoreComptime()) { | 5377 | if (!inst_ty.hasRuntimeBitsIgnoreComptime()) { |
| 5499 | try reap(f, inst, &.{extra.struct_operand}); | 5378 | try reap(f, inst, &.{extra.struct_operand}); |
| ... | @@ -5639,11 +5518,6 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5639,11 +5518,6 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5639 | fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { | 5518 | fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5640 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5519 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5641 | | 5520 | |
| 5642 | if (f.liveness.isUnused(inst)) { | | |
| 5643 | try reap(f, inst, &.{ty_op.operand}); | | |
| 5644 | return .none; | | |
| 5645 | } | | |
| 5646 | | | |
| 5647 | const inst_ty = f.air.typeOfIndex(inst); | 5521 | const inst_ty = f.air.typeOfIndex(inst); |
| 5648 | const operand = try f.resolveInst(ty_op.operand); | 5522 | const operand = try f.resolveInst(ty_op.operand); |
| 5649 | const operand_ty = f.air.typeOf(ty_op.operand); | 5523 | const operand_ty = f.air.typeOf(ty_op.operand); |
| ... | @@ -5676,11 +5550,6 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5676,11 +5550,6 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5676 | fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { | 5550 | fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { |
| 5677 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5551 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5678 | | 5552 | |
| 5679 | if (f.liveness.isUnused(inst)) { | | |
| 5680 | try reap(f, inst, &.{ty_op.operand}); | | |
| 5681 | return .none; | | |
| 5682 | } | | |
| 5683 | | | |
| 5684 | const inst_ty = f.air.typeOfIndex(inst); | 5553 | const inst_ty = f.air.typeOfIndex(inst); |
| 5685 | const operand = try f.resolveInst(ty_op.operand); | 5554 | const operand = try f.resolveInst(ty_op.operand); |
| 5686 | try reap(f, inst, &.{ty_op.operand}); | 5555 | try reap(f, inst, &.{ty_op.operand}); |
| ... | @@ -5718,11 +5587,6 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu | ... | @@ -5718,11 +5587,6 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu |
| 5718 | fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { | 5587 | fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5719 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5588 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5720 | | 5589 | |
| 5721 | if (f.liveness.isUnused(inst)) { | | |
| 5722 | try reap(f, inst, &.{ty_op.operand}); | | |
| 5723 | return .none; | | |
| 5724 | } | | |
| 5725 | | | |
| 5726 | const inst_ty = f.air.typeOfIndex(inst); | 5590 | const inst_ty = f.air.typeOfIndex(inst); |
| 5727 | const payload = try f.resolveInst(ty_op.operand); | 5591 | const payload = try f.resolveInst(ty_op.operand); |
| 5728 | try reap(f, inst, &.{ty_op.operand}); | 5592 | try reap(f, inst, &.{ty_op.operand}); |
| ... | @@ -5764,10 +5628,6 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5764,10 +5628,6 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5764 | | 5628 | |
| 5765 | fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { | 5629 | fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5766 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5630 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5767 | if (f.liveness.isUnused(inst)) { | | |
| 5768 | try reap(f, inst, &.{ty_op.operand}); | | |
| 5769 | return .none; | | |
| 5770 | } | | |
| 5771 | | 5631 | |
| 5772 | const writer = f.object.writer(); | 5632 | const writer = f.object.writer(); |
| 5773 | const operand = try f.resolveInst(ty_op.operand); | 5633 | const operand = try f.resolveInst(ty_op.operand); |
| ... | @@ -5831,7 +5691,7 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5831,7 +5691,7 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5831 | } | 5691 | } |
| 5832 | | 5692 | |
| 5833 | fn airErrReturnTrace(f: *Function, inst: Air.Inst.Index) !CValue { | 5693 | fn airErrReturnTrace(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5834 | if (f.liveness.isUnused(inst)) return .none; | 5694 | _ = inst; |
| 5835 | return f.fail("TODO: C backend: implement airErrReturnTrace", .{}); | 5695 | return f.fail("TODO: C backend: implement airErrReturnTrace", .{}); |
| 5836 | } | 5696 | } |
| 5837 | | 5697 | |
| ... | @@ -5847,10 +5707,6 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5847,10 +5707,6 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5847 | | 5707 | |
| 5848 | fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { | 5708 | fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5849 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5709 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5850 | if (f.liveness.isUnused(inst)) { | | |
| 5851 | try reap(f, inst, &.{ty_op.operand}); | | |
| 5852 | return .none; | | |
| 5853 | } | | |
| 5854 | | 5710 | |
| 5855 | const inst_ty = f.air.typeOfIndex(inst); | 5711 | const inst_ty = f.air.typeOfIndex(inst); |
| 5856 | const payload_ty = inst_ty.errorUnionPayload(); | 5712 | const payload_ty = inst_ty.errorUnionPayload(); |
| ... | @@ -5885,11 +5741,6 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5885,11 +5741,6 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5885 | fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !CValue { | 5741 | fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !CValue { |
| 5886 | const un_op = f.air.instructions.items(.data)[inst].un_op; | 5742 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 5887 | | 5743 | |
| 5888 | if (f.liveness.isUnused(inst)) { | | |
| 5889 | try reap(f, inst, &.{un_op}); | | |
| 5890 | return .none; | | |
| 5891 | } | | |
| 5892 | | | |
| 5893 | const writer = f.object.writer(); | 5744 | const writer = f.object.writer(); |
| 5894 | const operand = try f.resolveInst(un_op); | 5745 | const operand = try f.resolveInst(un_op); |
| 5895 | try reap(f, inst, &.{un_op}); | 5746 | try reap(f, inst, &.{un_op}); |
| ... | @@ -5923,11 +5774,6 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const | ... | @@ -5923,11 +5774,6 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const |
| 5923 | fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { | 5774 | fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5924 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5775 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5925 | | 5776 | |
| 5926 | if (f.liveness.isUnused(inst)) { | | |
| 5927 | try reap(f, inst, &.{ty_op.operand}); | | |
| 5928 | return .none; | | |
| 5929 | } | | |
| 5930 | | | |
| 5931 | const operand = try f.resolveInst(ty_op.operand); | 5777 | const operand = try f.resolveInst(ty_op.operand); |
| 5932 | try reap(f, inst, &.{ty_op.operand}); | 5778 | try reap(f, inst, &.{ty_op.operand}); |
| 5933 | const inst_ty = f.air.typeOfIndex(inst); | 5779 | const inst_ty = f.air.typeOfIndex(inst); |
| ... | @@ -5961,11 +5807,6 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5961,11 +5807,6 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5961 | fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { | 5807 | fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5962 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5808 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5963 | | 5809 | |
| 5964 | if (f.liveness.isUnused(inst)) { | | |
| 5965 | try reap(f, inst, &.{ty_op.operand}); | | |
| 5966 | return .none; | | |
| 5967 | } | | |
| 5968 | | | |
| 5969 | const inst_ty = f.air.typeOfIndex(inst); | 5810 | const inst_ty = f.air.typeOfIndex(inst); |
| 5970 | const operand = try f.resolveInst(ty_op.operand); | 5811 | const operand = try f.resolveInst(ty_op.operand); |
| 5971 | try reap(f, inst, &.{ty_op.operand}); | 5812 | try reap(f, inst, &.{ty_op.operand}); |
| ... | @@ -6009,11 +5850,6 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6009,11 +5850,6 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6009 | fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue { | 5850 | fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6010 | const un_op = f.air.instructions.items(.data)[inst].un_op; | 5851 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 6011 | | 5852 | |
| 6012 | if (f.liveness.isUnused(inst)) { | | |
| 6013 | try reap(f, inst, &.{un_op}); | | |
| 6014 | return .none; | | |
| 6015 | } | | |
| 6016 | | | |
| 6017 | const operand = try f.resolveInst(un_op); | 5853 | const operand = try f.resolveInst(un_op); |
| 6018 | try reap(f, inst, &.{un_op}); | 5854 | try reap(f, inst, &.{un_op}); |
| 6019 | const inst_ty = f.air.typeOfIndex(inst); | 5855 | const inst_ty = f.air.typeOfIndex(inst); |
| ... | @@ -6037,11 +5873,6 @@ fn airUnBuiltinCall( | ... | @@ -6037,11 +5873,6 @@ fn airUnBuiltinCall( |
| 6037 | ) !CValue { | 5873 | ) !CValue { |
| 6038 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 5874 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 6039 | | 5875 | |
| 6040 | if (f.liveness.isUnused(inst)) { | | |
| 6041 | try reap(f, inst, &.{ty_op.operand}); | | |
| 6042 | return .none; | | |
| 6043 | } | | |
| 6044 | | | |
| 6045 | const operand = try f.resolveInst(ty_op.operand); | 5876 | const operand = try f.resolveInst(ty_op.operand); |
| 6046 | try reap(f, inst, &.{ty_op.operand}); | 5877 | try reap(f, inst, &.{ty_op.operand}); |
| 6047 | const inst_ty = f.air.typeOfIndex(inst); | 5878 | const inst_ty = f.air.typeOfIndex(inst); |
| ... | @@ -6085,11 +5916,6 @@ fn airBinBuiltinCall( | ... | @@ -6085,11 +5916,6 @@ fn airBinBuiltinCall( |
| 6085 | ) !CValue { | 5916 | ) !CValue { |
| 6086 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 5917 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 6087 | | 5918 | |
| 6088 | if (f.liveness.isUnused(inst)) { | | |
| 6089 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | | |
| 6090 | return .none; | | |
| 6091 | } | | |
| 6092 | | | |
| 6093 | const operand_ty = f.air.typeOf(bin_op.lhs); | 5919 | const operand_ty = f.air.typeOf(bin_op.lhs); |
| 6094 | const operand_cty = try f.typeToCType(operand_ty, .complete); | 5920 | const operand_cty = try f.typeToCType(operand_ty, .complete); |
| 6095 | const is_big = operand_cty.tag() == .array; | 5921 | const is_big = operand_cty.tag() == .array; |
| ... | @@ -6142,11 +5968,6 @@ fn airCmpBuiltinCall( | ... | @@ -6142,11 +5968,6 @@ fn airCmpBuiltinCall( |
| 6142 | operation: enum { cmp, operator }, | 5968 | operation: enum { cmp, operator }, |
| 6143 | info: BuiltinInfo, | 5969 | info: BuiltinInfo, |
| 6144 | ) !CValue { | 5970 | ) !CValue { |
| 6145 | if (f.liveness.isUnused(inst)) { | | |
| 6146 | try reap(f, inst, &.{ data.lhs, data.rhs }); | | |
| 6147 | return .none; | | |
| 6148 | } | | |
| 6149 | | | |
| 6150 | const lhs = try f.resolveInst(data.lhs); | 5971 | const lhs = try f.resolveInst(data.lhs); |
| 6151 | const rhs = try f.resolveInst(data.rhs); | 5972 | const rhs = try f.resolveInst(data.rhs); |
| 6152 | try reap(f, inst, &.{ data.lhs, data.rhs }); | 5973 | try reap(f, inst, &.{ data.lhs, data.rhs }); |
| ... | @@ -6317,9 +6138,6 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6317,9 +6138,6 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6317 | const ptr = try f.resolveInst(atomic_load.ptr); | 6138 | const ptr = try f.resolveInst(atomic_load.ptr); |
| 6318 | try reap(f, inst, &.{atomic_load.ptr}); | 6139 | try reap(f, inst, &.{atomic_load.ptr}); |
| 6319 | const ptr_ty = f.air.typeOf(atomic_load.ptr); | 6140 | const ptr_ty = f.air.typeOf(atomic_load.ptr); |
| 6320 | if (!ptr_ty.isVolatilePtr() and f.liveness.isUnused(inst)) { | | |
| 6321 | return .none; | | |
| 6322 | } | | |
| 6323 | | 6141 | |
| 6324 | const inst_ty = f.air.typeOfIndex(inst); | 6142 | const inst_ty = f.air.typeOfIndex(inst); |
| 6325 | const writer = f.object.writer(); | 6143 | const writer = f.object.writer(); |
| ... | @@ -6463,11 +6281,6 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6463,11 +6281,6 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6463 | fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { | 6281 | fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6464 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 6282 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 6465 | | 6283 | |
| 6466 | if (f.liveness.isUnused(inst)) { | | |
| 6467 | try reap(f, inst, &.{ty_op.operand}); | | |
| 6468 | return .none; | | |
| 6469 | } | | |
| 6470 | | | |
| 6471 | const operand = try f.resolveInst(ty_op.operand); | 6284 | const operand = try f.resolveInst(ty_op.operand); |
| 6472 | try reap(f, inst, &.{ty_op.operand}); | 6285 | try reap(f, inst, &.{ty_op.operand}); |
| 6473 | | 6286 | |
| ... | @@ -6491,11 +6304,6 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6491,11 +6304,6 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6491 | fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { | 6304 | fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6492 | const un_op = f.air.instructions.items(.data)[inst].un_op; | 6305 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 6493 | | 6306 | |
| 6494 | if (f.liveness.isUnused(inst)) { | | |
| 6495 | try reap(f, inst, &.{un_op}); | | |
| 6496 | return .none; | | |
| 6497 | } | | |
| 6498 | | | |
| 6499 | const inst_ty = f.air.typeOfIndex(inst); | 6307 | const inst_ty = f.air.typeOfIndex(inst); |
| 6500 | const enum_ty = f.air.typeOf(un_op); | 6308 | const enum_ty = f.air.typeOf(un_op); |
| 6501 | const operand = try f.resolveInst(un_op); | 6309 | const operand = try f.resolveInst(un_op); |
| ... | @@ -6516,11 +6324,6 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6516,11 +6324,6 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6516 | fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue { | 6324 | fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6517 | const un_op = f.air.instructions.items(.data)[inst].un_op; | 6325 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 6518 | | 6326 | |
| 6519 | if (f.liveness.isUnused(inst)) { | | |
| 6520 | try reap(f, inst, &.{un_op}); | | |
| 6521 | return .none; | | |
| 6522 | } | | |
| 6523 | | | |
| 6524 | const writer = f.object.writer(); | 6327 | const writer = f.object.writer(); |
| 6525 | const inst_ty = f.air.typeOfIndex(inst); | 6328 | const inst_ty = f.air.typeOfIndex(inst); |
| 6526 | const operand = try f.resolveInst(un_op); | 6329 | const operand = try f.resolveInst(un_op); |
| ... | @@ -6537,11 +6340,6 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6537,11 +6340,6 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6537 | fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue { | 6340 | fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6538 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 6341 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 6539 | | 6342 | |
| 6540 | if (f.liveness.isUnused(inst)) { | | |
| 6541 | try reap(f, inst, &.{ty_op.operand}); | | |
| 6542 | return .none; | | |
| 6543 | } | | |
| 6544 | | | |
| 6545 | const operand = try f.resolveInst(ty_op.operand); | 6343 | const operand = try f.resolveInst(ty_op.operand); |
| 6546 | try reap(f, inst, &.{ty_op.operand}); | 6344 | try reap(f, inst, &.{ty_op.operand}); |
| 6547 | | 6345 | |
| ... | @@ -6573,11 +6371,6 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6573,11 +6371,6 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6573 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; | 6371 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; |
| 6574 | const extra = f.air.extraData(Air.Bin, pl_op.payload).data; | 6372 | const extra = f.air.extraData(Air.Bin, pl_op.payload).data; |
| 6575 | | 6373 | |
| 6576 | if (f.liveness.isUnused(inst)) { | | |
| 6577 | try reap(f, inst, &.{ pl_op.operand, extra.lhs, extra.rhs }); | | |
| 6578 | return .none; | | |
| 6579 | } | | |
| 6580 | | | |
| 6581 | const pred = try f.resolveInst(pl_op.operand); | 6374 | const pred = try f.resolveInst(pl_op.operand); |
| 6582 | const lhs = try f.resolveInst(extra.lhs); | 6375 | const lhs = try f.resolveInst(extra.lhs); |
| 6583 | const rhs = try f.resolveInst(extra.rhs); | 6376 | const rhs = try f.resolveInst(extra.rhs); |
| ... | @@ -6609,11 +6402,6 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6609,11 +6402,6 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6609 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 6402 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 6610 | const extra = f.air.extraData(Air.Shuffle, ty_pl.payload).data; | 6403 | const extra = f.air.extraData(Air.Shuffle, ty_pl.payload).data; |
| 6611 | | 6404 | |
| 6612 | if (f.liveness.isUnused(inst)) { | | |
| 6613 | try reap(f, inst, &.{ extra.a, extra.b }); | | |
| 6614 | return .none; | | |
| 6615 | } | | |
| 6616 | | | |
| 6617 | const mask = f.air.values[extra.mask]; | 6405 | const mask = f.air.values[extra.mask]; |
| 6618 | const lhs = try f.resolveInst(extra.a); | 6406 | const lhs = try f.resolveInst(extra.a); |
| 6619 | const rhs = try f.resolveInst(extra.b); | 6407 | const rhs = try f.resolveInst(extra.b); |
| ... | @@ -6655,11 +6443,6 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6655,11 +6443,6 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6655 | fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { | 6443 | fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6656 | const reduce = f.air.instructions.items(.data)[inst].reduce; | 6444 | const reduce = f.air.instructions.items(.data)[inst].reduce; |
| 6657 | | 6445 | |
| 6658 | if (f.liveness.isUnused(inst)) { | | |
| 6659 | try reap(f, inst, &.{reduce.operand}); | | |
| 6660 | return .none; | | |
| 6661 | } | | |
| 6662 | | | |
| 6663 | const target = f.object.dg.module.getTarget(); | 6446 | const target = f.object.dg.module.getTarget(); |
| 6664 | const scalar_ty = f.air.typeOfIndex(inst); | 6447 | const scalar_ty = f.air.typeOfIndex(inst); |
| 6665 | const operand = try f.resolveInst(reduce.operand); | 6448 | const operand = try f.resolveInst(reduce.operand); |
| ... | @@ -6831,8 +6614,6 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6831,8 +6614,6 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6831 | } | 6614 | } |
| 6832 | } | 6615 | } |
| 6833 | | 6616 | |
| 6834 | if (f.liveness.isUnused(inst)) return .none; | | |
| 6835 | | | |
| 6836 | const target = f.object.dg.module.getTarget(); | 6617 | const target = f.object.dg.module.getTarget(); |
| 6837 | | 6618 | |
| 6838 | const writer = f.object.writer(); | 6619 | const writer = f.object.writer(); |
| ... | @@ -6999,11 +6780,6 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6999,11 +6780,6 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6999 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 6780 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 7000 | const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data; | 6781 | const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data; |
| 7001 | | 6782 | |
| 7002 | if (f.liveness.isUnused(inst)) { | | |
| 7003 | try reap(f, inst, &.{extra.init}); | | |
| 7004 | return .none; | | |
| 7005 | } | | |
| 7006 | | | |
| 7007 | const union_ty = f.air.typeOfIndex(inst); | 6783 | const union_ty = f.air.typeOfIndex(inst); |
| 7008 | const target = f.object.dg.module.getTarget(); | 6784 | const target = f.object.dg.module.getTarget(); |
| 7009 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | 6785 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| ... | @@ -7070,8 +6846,6 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7070,8 +6846,6 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7070 | } | 6846 | } |
| 7071 | | 6847 | |
| 7072 | fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue { | 6848 | fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7073 | if (f.liveness.isUnused(inst)) return .none; | | |
| 7074 | | | |
| 7075 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; | 6849 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; |
| 7076 | | 6850 | |
| 7077 | const writer = f.object.writer(); | 6851 | const writer = f.object.writer(); |
| ... | @@ -7104,10 +6878,6 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7104,10 +6878,6 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7104 | | 6878 | |
| 7105 | fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { | 6879 | fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7106 | const un_op = f.air.instructions.items(.data)[inst].un_op; | 6880 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 7107 | if (f.liveness.isUnused(inst)) { | | |
| 7108 | try reap(f, inst, &.{un_op}); | | |
| 7109 | return .none; | | |
| 7110 | } | | |
| 7111 | | 6881 | |
| 7112 | const operand = try f.resolveInst(un_op); | 6882 | const operand = try f.resolveInst(un_op); |
| 7113 | try reap(f, inst, &.{un_op}); | 6883 | try reap(f, inst, &.{un_op}); |
| ... | @@ -7133,10 +6903,6 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7133,10 +6903,6 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7133 | | 6903 | |
| 7134 | fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { | 6904 | fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { |
| 7135 | const un_op = f.air.instructions.items(.data)[inst].un_op; | 6905 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 7136 | if (f.liveness.isUnused(inst)) { | | |
| 7137 | try reap(f, inst, &.{un_op}); | | |
| 7138 | return .none; | | |
| 7139 | } | | |
| 7140 | | 6906 | |
| 7141 | const operand = try f.resolveInst(un_op); | 6907 | const operand = try f.resolveInst(un_op); |
| 7142 | try reap(f, inst, &.{un_op}); | 6908 | try reap(f, inst, &.{un_op}); |
| ... | @@ -7164,10 +6930,6 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal | ... | @@ -7164,10 +6930,6 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal |
| 7164 | | 6930 | |
| 7165 | fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { | 6931 | fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { |
| 7166 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 6932 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 7167 | if (f.liveness.isUnused(inst)) { | | |
| 7168 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | | |
| 7169 | return .none; | | |
| 7170 | } | | |
| 7171 | | 6933 | |
| 7172 | const lhs = try f.resolveInst(bin_op.lhs); | 6934 | const lhs = try f.resolveInst(bin_op.lhs); |
| 7173 | const rhs = try f.resolveInst(bin_op.rhs); | 6935 | const rhs = try f.resolveInst(bin_op.rhs); |
| ... | @@ -7200,10 +6962,6 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa | ... | @@ -7200,10 +6962,6 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa |
| 7200 | fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { | 6962 | fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7201 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; | 6963 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; |
| 7202 | const bin_op = f.air.extraData(Air.Bin, pl_op.payload).data; | 6964 | const bin_op = f.air.extraData(Air.Bin, pl_op.payload).data; |
| 7203 | if (f.liveness.isUnused(inst)) { | | |
| 7204 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand }); | | |
| 7205 | return .none; | | |
| 7206 | } | | |
| 7207 | | 6965 | |
| 7208 | const mulend1 = try f.resolveInst(bin_op.lhs); | 6966 | const mulend1 = try f.resolveInst(bin_op.lhs); |
| 7209 | const mulend2 = try f.resolveInst(bin_op.rhs); | 6967 | const mulend2 = try f.resolveInst(bin_op.rhs); |
| ... | @@ -7236,8 +6994,6 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7236,8 +6994,6 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7236 | } | 6994 | } |
| 7237 | | 6995 | |
| 7238 | fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue { | 6996 | fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7239 | if (f.liveness.isUnused(inst)) return .none; | | |
| 7240 | | | |
| 7241 | const inst_ty = f.air.typeOfIndex(inst); | 6997 | const inst_ty = f.air.typeOfIndex(inst); |
| 7242 | const fn_cty = try f.typeToCType(f.object.dg.decl.?.ty, .complete); | 6998 | const fn_cty = try f.typeToCType(f.object.dg.decl.?.ty, .complete); |
| 7243 | const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len; | 6999 | const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len; |
| ... | @@ -7256,10 +7012,6 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7256,10 +7012,6 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7256 | | 7012 | |
| 7257 | fn airCVaArg(f: *Function, inst: Air.Inst.Index) !CValue { | 7013 | fn airCVaArg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7258 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 7014 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 7259 | if (f.liveness.isUnused(inst)) { | | |
| 7260 | try reap(f, inst, &.{ty_op.operand}); | | |
| 7261 | return .none; | | |
| 7262 | } | | |
| 7263 | | 7015 | |
| 7264 | const inst_ty = f.air.typeOfIndex(inst); | 7016 | const inst_ty = f.air.typeOfIndex(inst); |
| 7265 | const va_list = try f.resolveInst(ty_op.operand); | 7017 | const va_list = try f.resolveInst(ty_op.operand); |
| ... | @@ -7291,10 +7043,6 @@ fn airCVaEnd(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7291,10 +7043,6 @@ fn airCVaEnd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7291 | | 7043 | |
| 7292 | fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue { | 7044 | fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7293 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; | 7045 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 7294 | if (f.liveness.isUnused(inst)) { | | |
| 7295 | try reap(f, inst, &.{ty_op.operand}); | | |
| 7296 | return .none; | | |
| 7297 | } | | |
| 7298 | | 7046 | |
| 7299 | const inst_ty = f.air.typeOfIndex(inst); | 7047 | const inst_ty = f.air.typeOfIndex(inst); |
| 7300 | const va_list = try f.resolveInst(ty_op.operand); | 7048 | const va_list = try f.resolveInst(ty_op.operand); |
| ... | @@ -7858,7 +7606,6 @@ fn freeLocal(f: *Function, inst: Air.Inst.Index, local_index: LocalIndex, ref_in | ... | @@ -7858,7 +7606,6 @@ fn freeLocal(f: *Function, inst: Air.Inst.Index, local_index: LocalIndex, ref_in |
| 7858 | const gpa = f.object.dg.gpa; | 7606 | const gpa = f.object.dg.gpa; |
| 7859 | const local = &f.locals.items[local_index]; | 7607 | const local = &f.locals.items[local_index]; |
| 7860 | log.debug("%{d}: freeing t{d} (operand %{d})", .{ inst, local_index, ref_inst }); | 7608 | log.debug("%{d}: freeing t{d} (operand %{d})", .{ inst, local_index, ref_inst }); |
| 7861 | if (f.is_in_clone != local.is_in_clone) return; | | |
| 7862 | const gop = try f.free_locals_map.getOrPut(gpa, local.getType()); | 7609 | const gop = try f.free_locals_map.getOrPut(gpa, local.getType()); |
| 7863 | if (!gop.found_existing) gop.value_ptr.* = .{}; | 7610 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 7864 | if (std.debug.runtime_safety) { | 7611 | if (std.debug.runtime_safety) { |
| ... | @@ -7916,35 +7663,3 @@ fn deinitFreeLocalsMap(gpa: mem.Allocator, map: *LocalsMap) void { | ... | @@ -7916,35 +7663,3 @@ fn deinitFreeLocalsMap(gpa: mem.Allocator, map: *LocalsMap) void { |
| 7916 | } | 7663 | } |
| 7917 | map.deinit(gpa); | 7664 | map.deinit(gpa); |
| 7918 | } | 7665 | } |
| 7919 | | | |
| 7920 | fn noticeBranchFrees( | | |
| 7921 | f: *Function, | | |
| 7922 | pre_locals_len: LocalIndex, | | |
| 7923 | pre_allocs_len: LocalIndex, | | |
| 7924 | inst: Air.Inst.Index, | | |
| 7925 | ) !void { | | |
| 7926 | for (f.locals.items[pre_locals_len..], pre_locals_len..) |*local, local_i| { | | |
| 7927 | const local_index = @intCast(LocalIndex, local_i); | | |
| 7928 | if (f.allocs.contains(local_index)) { | | |
| 7929 | if (std.debug.runtime_safety) { | | |
| 7930 | // new allocs are no longer freeable, so make sure they aren't in the free list | | |
| 7931 | if (f.free_locals_map.getPtr(local.getType())) |locals_list| { | | |
| 7932 | assert(!locals_list.contains(local_index)); | | |
| 7933 | } | | |
| 7934 | } | | |
| 7935 | continue; | | |
| 7936 | } | | |
| 7937 | | | |
| 7938 | // free cloned locals from other branches at current cloned-ness | | |
| 7939 | std.debug.assert(local.is_in_clone or !f.is_in_clone); | | |
| 7940 | local.is_in_clone = f.is_in_clone; | | |
| 7941 | try freeLocal(f, inst, local_index, 0); | | |
| 7942 | } | | |
| 7943 | | | |
| 7944 | for (f.allocs.keys()[pre_allocs_len..]) |local_i| { | | |
| 7945 | const local_index = @intCast(LocalIndex, local_i); | | |
| 7946 | const local = &f.locals.items[local_index]; | | |
| 7947 | // new allocs are no longer freeable, so remove them from the free list | | |
| 7948 | if (f.free_locals_map.getPtr(local.getType())) |locals_list| _ = locals_list.swapRemove(local_index); | | |
| 7949 | } | | |
| 7950 | } | | |