| ... | ... | @@ -176,7 +176,10 @@ pub fn analyze(zcu: *Zcu, air: Air, intern_pool: *InternPool) Allocator.Error!Li |
| 176 | 176 | data.old_extra = a.extra; |
| 177 | 177 | a.extra = .{}; |
| 178 | 178 | try analyzeBody(&a, .main_analysis, &data, main_body); |
| 179 | | assert(data.live_set.count() == 0); |
| 179 | if (std.debug.runtime_safety and data.live_set.count() != 0) { |
| 180 | log.debug("instructions still in live set after analysis: {f}", .{fmtInstSet(&data.live_set)}); |
| 181 | @panic("liveness analysis failed"); |
| 182 | } |
| 180 | 183 | } |
| 181 | 184 | |
| 182 | 185 | return .{ |
| ... | ... | @@ -825,10 +828,10 @@ fn analyzeOperands( |
| 825 | 828 | |
| 826 | 829 | // This logic must synchronize with `will_die_immediately` in `AnalyzeBigOperands.init`. |
| 827 | 830 | const immediate_death = if (data.live_set.remove(inst)) blk: { |
| 828 | | log.debug("[{}] %{d}: removed from live set", .{ pass, @intFromEnum(inst) }); |
| 831 | log.debug("[{t}] {f}: removed from live set", .{ pass, inst }); |
| 829 | 832 | break :blk false; |
| 830 | 833 | } else blk: { |
| 831 | | log.debug("[{}] %{d}: immediate death", .{ pass, @intFromEnum(inst) }); |
| 834 | log.debug("[{t}] {f}: immediate death", .{ pass, inst }); |
| 832 | 835 | break :blk true; |
| 833 | 836 | }; |
| 834 | 837 | |
| ... | ... | @@ -849,7 +852,7 @@ fn analyzeOperands( |
| 849 | 852 | const mask = @as(Bpi, 1) << @as(OperandInt, @intCast(i)); |
| 850 | 853 | |
| 851 | 854 | if ((try data.live_set.fetchPut(gpa, operand, {})) == null) { |
| 852 | | log.debug("[{}] %{d}: added %{d} to live set (operand dies here)", .{ pass, @intFromEnum(inst), operand }); |
| 855 | log.debug("[{t}] {f}: added {f} to live set (operand dies here)", .{ pass, inst, operand }); |
| 853 | 856 | tomb_bits |= mask; |
| 854 | 857 | } |
| 855 | 858 | } |
| ... | ... | @@ -988,19 +991,19 @@ fn analyzeInstBlock( |
| 988 | 991 | }, |
| 989 | 992 | |
| 990 | 993 | .main_analysis => { |
| 991 | | log.debug("[{}] %{f}: block live set is {f}", .{ pass, inst, fmtInstSet(&data.live_set) }); |
| 994 | log.debug("[{t}] {f}: block live set is {f}", .{ pass, inst, fmtInstSet(&data.live_set) }); |
| 992 | 995 | // We can move the live set because the body should have a noreturn |
| 993 | 996 | // instruction which overrides the set. |
| 994 | 997 | try data.block_scopes.put(gpa, inst, .{ |
| 995 | 998 | .live_set = data.live_set.move(), |
| 996 | 999 | }); |
| 997 | 1000 | defer { |
| 998 | | log.debug("[{}] %{f}: popped block scope", .{ pass, inst }); |
| 1001 | log.debug("[{t}] {f}: popped block scope", .{ pass, inst }); |
| 999 | 1002 | var scope = data.block_scopes.fetchRemove(inst).?.value; |
| 1000 | 1003 | scope.live_set.deinit(gpa); |
| 1001 | 1004 | } |
| 1002 | 1005 | |
| 1003 | | log.debug("[{}] %{f}: pushed new block scope", .{ pass, inst }); |
| 1006 | log.debug("[{t}] {f}: pushed new block scope", .{ pass, inst }); |
| 1004 | 1007 | try analyzeBody(a, pass, data, body); |
| 1005 | 1008 | |
| 1006 | 1009 | // If the block is noreturn, block deaths not only aren't useful, they're impossible to |
| ... | ... | @@ -1027,7 +1030,7 @@ fn analyzeInstBlock( |
| 1027 | 1030 | } |
| 1028 | 1031 | assert(measured_num == num_deaths); // post-live-set should be a subset of pre-live-set |
| 1029 | 1032 | try a.special.put(gpa, inst, extra_index); |
| 1030 | | log.debug("[{}] %{f}: block deaths are {f}", .{ |
| 1033 | log.debug("[{t}] {f}: block deaths are {f}", .{ |
| 1031 | 1034 | pass, |
| 1032 | 1035 | inst, |
| 1033 | 1036 | fmtInstList(@ptrCast(a.extra.items[extra_index + 1 ..][0..num_deaths])), |
| ... | ... | @@ -1064,7 +1067,7 @@ fn writeLoopInfo( |
| 1064 | 1067 | const block_inst = key.*; |
| 1065 | 1068 | a.extra.appendAssumeCapacity(@intFromEnum(block_inst)); |
| 1066 | 1069 | } |
| 1067 | | log.debug("[{}] %{f}: includes breaks to {f}", .{ LivenessPass.loop_analysis, inst, fmtInstSet(&data.breaks) }); |
| 1070 | log.debug("[{t}] {f}: includes breaks to {f}", .{ LivenessPass.loop_analysis, inst, fmtInstSet(&data.breaks) }); |
| 1068 | 1071 | |
| 1069 | 1072 | // Now we put the live operands from the loop body in too |
| 1070 | 1073 | const num_live = data.live_set.count(); |
| ... | ... | @@ -1076,7 +1079,7 @@ fn writeLoopInfo( |
| 1076 | 1079 | const alive = key.*; |
| 1077 | 1080 | a.extra.appendAssumeCapacity(@intFromEnum(alive)); |
| 1078 | 1081 | } |
| 1079 | | log.debug("[{}] %{f}: maintain liveness of {f}", .{ LivenessPass.loop_analysis, inst, fmtInstSet(&data.live_set) }); |
| 1082 | log.debug("[{t}] {f}: maintain liveness of {f}", .{ LivenessPass.loop_analysis, inst, fmtInstSet(&data.live_set) }); |
| 1080 | 1083 | |
| 1081 | 1084 | try a.special.put(gpa, inst, extra_index); |
| 1082 | 1085 | |
| ... | ... | @@ -1117,7 +1120,7 @@ fn resolveLoopLiveSet( |
| 1117 | 1120 | try data.live_set.ensureUnusedCapacity(gpa, @intCast(loop_live.len)); |
| 1118 | 1121 | for (loop_live) |alive| data.live_set.putAssumeCapacity(alive, {}); |
| 1119 | 1122 | |
| 1120 | | log.debug("[{}] %{f}: block live set is {f}", .{ LivenessPass.main_analysis, inst, fmtInstSet(&data.live_set) }); |
| 1123 | log.debug("[{t}] {f}: block live set is {f}", .{ LivenessPass.main_analysis, inst, fmtInstSet(&data.live_set) }); |
| 1121 | 1124 | |
| 1122 | 1125 | for (breaks) |block_inst| { |
| 1123 | 1126 | // We might break to this block, so include every operand that the block needs alive |
| ... | ... | @@ -1130,7 +1133,7 @@ fn resolveLoopLiveSet( |
| 1130 | 1133 | } |
| 1131 | 1134 | } |
| 1132 | 1135 | |
| 1133 | | log.debug("[{}] %{f}: loop live set is {f}", .{ LivenessPass.main_analysis, inst, fmtInstSet(&data.live_set) }); |
| 1136 | log.debug("[{t}] {f}: loop live set is {f}", .{ LivenessPass.main_analysis, inst, fmtInstSet(&data.live_set) }); |
| 1134 | 1137 | } |
| 1135 | 1138 | |
| 1136 | 1139 | fn analyzeInstLoop( |
| ... | ... | @@ -1168,7 +1171,7 @@ fn analyzeInstLoop( |
| 1168 | 1171 | .live_set = data.live_set.move(), |
| 1169 | 1172 | }); |
| 1170 | 1173 | defer { |
| 1171 | | log.debug("[{}] %{f}: popped loop block scop", .{ pass, inst }); |
| 1174 | log.debug("[{t}] {f}: popped loop block scop", .{ pass, inst }); |
| 1172 | 1175 | var scope = data.block_scopes.fetchRemove(inst).?.value; |
| 1173 | 1176 | scope.live_set.deinit(gpa); |
| 1174 | 1177 | } |
| ... | ... | @@ -1269,13 +1272,13 @@ fn analyzeInstCondBr( |
| 1269 | 1272 | } |
| 1270 | 1273 | } |
| 1271 | 1274 | |
| 1272 | | log.debug("[{}] %{f}: 'then' branch mirrored deaths are {f}", .{ pass, inst, fmtInstList(then_mirrored_deaths.items) }); |
| 1273 | | log.debug("[{}] %{f}: 'else' branch mirrored deaths are {f}", .{ pass, inst, fmtInstList(else_mirrored_deaths.items) }); |
| 1275 | log.debug("[{t}] {f}: 'then' branch mirrored deaths are {f}", .{ pass, inst, fmtInstList(then_mirrored_deaths.items) }); |
| 1276 | log.debug("[{t}] {f}: 'else' branch mirrored deaths are {f}", .{ pass, inst, fmtInstList(else_mirrored_deaths.items) }); |
| 1274 | 1277 | |
| 1275 | 1278 | data.live_set.deinit(gpa); |
| 1276 | 1279 | data.live_set = then_live.move(); // Really the union of both live sets |
| 1277 | 1280 | |
| 1278 | | log.debug("[{}] %{f}: new live set is {f}", .{ pass, inst, fmtInstSet(&data.live_set) }); |
| 1281 | log.debug("[{t}] {f}: new live set is {f}", .{ pass, inst, fmtInstSet(&data.live_set) }); |
| 1279 | 1282 | |
| 1280 | 1283 | // Write the mirrored deaths to `extra` |
| 1281 | 1284 | const then_death_count = @as(u32, @intCast(then_mirrored_deaths.items.len)); |
| ... | ... | @@ -1343,7 +1346,7 @@ fn analyzeInstSwitchBr( |
| 1343 | 1346 | }); |
| 1344 | 1347 | } |
| 1345 | 1348 | defer if (is_dispatch_loop) { |
| 1346 | | log.debug("[{}] %{f}: popped loop block scop", .{ pass, inst }); |
| 1349 | log.debug("[{t}] {f}: popped loop block scope", .{ pass, inst }); |
| 1347 | 1350 | var scope = data.block_scopes.fetchRemove(inst).?.value; |
| 1348 | 1351 | scope.live_set.deinit(gpa); |
| 1349 | 1352 | }; |
| ... | ... | @@ -1401,13 +1404,13 @@ fn analyzeInstSwitchBr( |
| 1401 | 1404 | } |
| 1402 | 1405 | |
| 1403 | 1406 | for (mirrored_deaths, 0..) |mirrored, i| { |
| 1404 | | log.debug("[{}] %{f}: case {} mirrored deaths are {f}", .{ pass, inst, i, fmtInstList(mirrored.items) }); |
| 1407 | log.debug("[{t}] {f}: case {} mirrored deaths are {f}", .{ pass, inst, i, fmtInstList(mirrored.items) }); |
| 1405 | 1408 | } |
| 1406 | 1409 | |
| 1407 | 1410 | data.live_set.deinit(gpa); |
| 1408 | 1411 | data.live_set = all_alive.move(); |
| 1409 | 1412 | |
| 1410 | | log.debug("[{}] %{f}: new live set is {f}", .{ pass, inst, fmtInstSet(&data.live_set) }); |
| 1413 | log.debug("[{t}] {f}: new live set is {f}", .{ pass, inst, fmtInstSet(&data.live_set) }); |
| 1411 | 1414 | } |
| 1412 | 1415 | |
| 1413 | 1416 | const else_death_count = @as(u32, @intCast(mirrored_deaths[ncases].items.len)); |
| ... | ... | @@ -1506,7 +1509,7 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type { |
| 1506 | 1509 | |
| 1507 | 1510 | .main_analysis => { |
| 1508 | 1511 | if ((try big.data.live_set.fetchPut(gpa, operand, {})) == null) { |
| 1509 | | log.debug("[{}] %{f}: added %{f} to live set (operand dies here)", .{ pass, big.inst, operand }); |
| 1512 | log.debug("[{t}] {f}: added {f} to live set (operand dies here)", .{ pass, big.inst, operand }); |
| 1510 | 1513 | big.extra_tombs[extra_byte] |= @as(u32, 1) << extra_bit; |
| 1511 | 1514 | } |
| 1512 | 1515 | }, |
| ... | ... | @@ -1568,9 +1571,9 @@ const FmtInstSet = struct { |
| 1568 | 1571 | return; |
| 1569 | 1572 | } |
| 1570 | 1573 | var it = val.set.keyIterator(); |
| 1571 | | try w.print("%{f}", .{it.next().?.*}); |
| 1574 | try w.print("{f}", .{it.next().?.*}); |
| 1572 | 1575 | while (it.next()) |key| { |
| 1573 | | try w.print(" %{f}", .{key.*}); |
| 1576 | try w.print(" {f}", .{key.*}); |
| 1574 | 1577 | } |
| 1575 | 1578 | } |
| 1576 | 1579 | }; |
| ... | ... | @@ -1587,9 +1590,9 @@ const FmtInstList = struct { |
| 1587 | 1590 | try w.writeAll("[no instructions]"); |
| 1588 | 1591 | return; |
| 1589 | 1592 | } |
| 1590 | | try w.print("%{f}", .{val.list[0]}); |
| 1593 | try w.print("{f}", .{val.list[0]}); |
| 1591 | 1594 | for (val.list[1..]) |inst| { |
| 1592 | | try w.print(" %{f}", .{inst}); |
| 1595 | try w.print(" {f}", .{inst}); |
| 1593 | 1596 | } |
| 1594 | 1597 | } |
| 1595 | 1598 | }; |