authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-04-14 21:38:32+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-04-20 20:28:48+01:00
log407dc6eee4660bb0744c55f4565be77501ec7d37
tree8e58be56dea4c1f318b0cb57ea7d4ab9d85076a7
parent4486f271266b330f683ccc266ce19ddbd55e7f59
signature Commit is signed but in an unrecognized format.

Liveness: avoid emitting unused instructions or marking their operands as used

Backends want to avoid emitting unused instructions which do not have side effects: to that end, they all have `Liveness.isUnused` checks for many instructions. However, checking this in the backends avoids a lot of potential optimizations. For instance, if a nested field is loaded, then the first field access would still be emitted, since its result is used by the next access (which is then unreferenced). To elide more instructions, Liveness can track this data instead. For operands which do not have to be lowered (i.e. are not side effecting and are not something special like `arg), Liveness can ignore their operand usages, and push the unused information further up, potentially marking many more instructions as unreferenced. In doing this, I also uncovered a bug in the LLVM backend relating to discarding the result of `@cVaArg`, which this change fixes. A behaviour test has been added to cover it.

5 files changed, 756 insertions(+), 679 deletions(-)

src/Air.zig+214
...@@ -1375,3 +1375,217 @@ pub fn nullTerminatedString(air: Air, index: usize) [:0]const u8 {...@@ -1375,3 +1375,217 @@ pub fn nullTerminatedString(air: Air, index: usize) [:0]const u8 {
1375 }1375 }
1376 return bytes[0..end :0];1376 return bytes[0..end :0];
1377}1377}
1378
1379/// Returns whether the given instruction must always be lowered, for instance because it can cause
1380/// side effects. If an instruction does not need to be lowered, and Liveness determines its result
1381/// is unused, backends should avoid lowering it.
1382pub fn mustLower(air: Air, inst: Air.Inst.Index) bool {
1383 const data = air.instructions.items(.data)[inst];
1384 return switch (air.instructions.items(.tag)[inst]) {
1385 .arg,
1386 .block,
1387 .loop,
1388 .br,
1389 .trap,
1390 .breakpoint,
1391 .call,
1392 .call_always_tail,
1393 .call_never_tail,
1394 .call_never_inline,
1395 .cond_br,
1396 .switch_br,
1397 .@"try",
1398 .try_ptr,
1399 .dbg_stmt,
1400 .dbg_block_begin,
1401 .dbg_block_end,
1402 .dbg_inline_begin,
1403 .dbg_inline_end,
1404 .dbg_var_ptr,
1405 .dbg_var_val,
1406 .ret,
1407 .ret_load,
1408 .store,
1409 .unreach,
1410 .optional_payload_ptr_set,
1411 .errunion_payload_ptr_set,
1412 .set_union_tag,
1413 .memset,
1414 .memcpy,
1415 .cmpxchg_weak,
1416 .cmpxchg_strong,
1417 .fence,
1418 .atomic_store_unordered,
1419 .atomic_store_monotonic,
1420 .atomic_store_release,
1421 .atomic_store_seq_cst,
1422 .atomic_rmw,
1423 .prefetch,
1424 .wasm_memory_grow,
1425 .set_err_return_trace,
1426 .vector_store_elem,
1427 .c_va_arg,
1428 .c_va_copy,
1429 .c_va_end,
1430 .c_va_start,
1431 => true,
1432
1433 .add,
1434 .add_optimized,
1435 .addwrap,
1436 .addwrap_optimized,
1437 .add_sat,
1438 .sub,
1439 .sub_optimized,
1440 .subwrap,
1441 .subwrap_optimized,
1442 .sub_sat,
1443 .mul,
1444 .mul_optimized,
1445 .mulwrap,
1446 .mulwrap_optimized,
1447 .mul_sat,
1448 .div_float,
1449 .div_float_optimized,
1450 .div_trunc,
1451 .div_trunc_optimized,
1452 .div_floor,
1453 .div_floor_optimized,
1454 .div_exact,
1455 .div_exact_optimized,
1456 .rem,
1457 .rem_optimized,
1458 .mod,
1459 .mod_optimized,
1460 .ptr_add,
1461 .ptr_sub,
1462 .max,
1463 .min,
1464 .add_with_overflow,
1465 .sub_with_overflow,
1466 .mul_with_overflow,
1467 .shl_with_overflow,
1468 .alloc,
1469 .ret_ptr,
1470 .bit_and,
1471 .bit_or,
1472 .shr,
1473 .shr_exact,
1474 .shl,
1475 .shl_exact,
1476 .shl_sat,
1477 .xor,
1478 .not,
1479 .bitcast,
1480 .ret_addr,
1481 .frame_addr,
1482 .clz,
1483 .ctz,
1484 .popcount,
1485 .byte_swap,
1486 .bit_reverse,
1487 .sqrt,
1488 .sin,
1489 .cos,
1490 .tan,
1491 .exp,
1492 .exp2,
1493 .log,
1494 .log2,
1495 .log10,
1496 .fabs,
1497 .floor,
1498 .ceil,
1499 .round,
1500 .trunc_float,
1501 .neg,
1502 .neg_optimized,
1503 .cmp_lt,
1504 .cmp_lt_optimized,
1505 .cmp_lte,
1506 .cmp_lte_optimized,
1507 .cmp_eq,
1508 .cmp_eq_optimized,
1509 .cmp_gte,
1510 .cmp_gte_optimized,
1511 .cmp_gt,
1512 .cmp_gt_optimized,
1513 .cmp_neq,
1514 .cmp_neq_optimized,
1515 .cmp_vector,
1516 .cmp_vector_optimized,
1517 .constant,
1518 .const_ty,
1519 .is_null,
1520 .is_non_null,
1521 .is_null_ptr,
1522 .is_non_null_ptr,
1523 .is_err,
1524 .is_non_err,
1525 .is_err_ptr,
1526 .is_non_err_ptr,
1527 .bool_and,
1528 .bool_or,
1529 .ptrtoint,
1530 .bool_to_int,
1531 .fptrunc,
1532 .fpext,
1533 .intcast,
1534 .trunc,
1535 .optional_payload,
1536 .optional_payload_ptr,
1537 .wrap_optional,
1538 .unwrap_errunion_payload,
1539 .unwrap_errunion_err,
1540 .unwrap_errunion_payload_ptr,
1541 .unwrap_errunion_err_ptr,
1542 .wrap_errunion_payload,
1543 .wrap_errunion_err,
1544 .struct_field_ptr,
1545 .struct_field_ptr_index_0,
1546 .struct_field_ptr_index_1,
1547 .struct_field_ptr_index_2,
1548 .struct_field_ptr_index_3,
1549 .struct_field_val,
1550 .get_union_tag,
1551 .slice,
1552 .slice_len,
1553 .slice_ptr,
1554 .ptr_slice_len_ptr,
1555 .ptr_slice_ptr_ptr,
1556 .array_elem_val,
1557 .slice_elem_ptr,
1558 .ptr_elem_ptr,
1559 .array_to_slice,
1560 .float_to_int,
1561 .float_to_int_optimized,
1562 .int_to_float,
1563 .reduce,
1564 .reduce_optimized,
1565 .splat,
1566 .shuffle,
1567 .select,
1568 .is_named_enum_value,
1569 .tag_name,
1570 .error_name,
1571 .error_set_has_value,
1572 .aggregate_init,
1573 .union_init,
1574 .mul_add,
1575 .field_parent_ptr,
1576 .wasm_memory_size,
1577 .cmp_lt_errors_len,
1578 .err_return_trace,
1579 .addrspace_cast,
1580 .save_err_return_trace_index,
1581 .work_item_id,
1582 .work_group_size,
1583 .work_group_id,
1584 => false,
1585
1586 .assembly => @truncate(u1, air.extraData(Air.Asm, data.ty_pl.payload).data.flags >> 31) != 0,
1587 .load => air.typeOf(data.ty_op.operand).isVolatilePtr(),
1588 .slice_elem_val, .ptr_elem_val => air.typeOf(data.bin_op.lhs).isVolatilePtr(),
1589 .atomic_load => air.typeOf(data.atomic_load.ptr).isVolatilePtr(),
1590 };
1591}
src/Liveness.zig+44-23
...@@ -1333,40 +1333,47 @@ fn analyzeOperands(...@@ -1333,40 +1333,47 @@ fn analyzeOperands(
1333 .main_analysis => {1333 .main_analysis => {
1334 const usize_index = (inst * bpi) / @bitSizeOf(usize);1334 const usize_index = (inst * bpi) / @bitSizeOf(usize);
13351335
1336 var tomb_bits: Bpi = 0;1336 // This logic must synchronize with `will_die_immediately` in `AnalyzeBigOperands.init`.
13371337 var immediate_death = false;
1338 if (data.branch_deaths.remove(inst)) {1338 if (data.branch_deaths.remove(inst)) {
1339 log.debug("[{}] %{}: resolved branch death to birth (immediate death)", .{ pass, inst });1339 log.debug("[{}] %{}: resolved branch death to birth (immediate death)", .{ pass, inst });
1340 tomb_bits |= @as(Bpi, 1) << (bpi - 1);1340 immediate_death = true;
1341 assert(!data.live_set.contains(inst));1341 assert(!data.live_set.contains(inst));
1342 } else if (data.live_set.remove(inst)) {1342 } else if (data.live_set.remove(inst)) {
1343 log.debug("[{}] %{}: removed from live set", .{ pass, inst });1343 log.debug("[{}] %{}: removed from live set", .{ pass, inst });
1344 } else {1344 } else {
1345 log.debug("[{}] %{}: immediate death", .{ pass, inst });1345 log.debug("[{}] %{}: immediate death", .{ pass, inst });
1346 tomb_bits |= @as(Bpi, 1) << (bpi - 1);1346 immediate_death = true;
1347 }1347 }
13481348
1349 // Note that it's important we iterate over the operands backwards, so that if a dying1349 var tomb_bits: Bpi = @as(Bpi, @boolToInt(immediate_death)) << (bpi - 1);
1350 // operand is used multiple times we mark its last use as its death.1350
1351 var i = operands.len;1351 // If our result is unused and the instruction doesn't need to be lowered, backends will
1352 while (i > 0) {1352 // skip the lowering of this instruction, so we don't want to record uses of operands.
1353 i -= 1;1353 // That way, we can mark as many instructions as possible unused.
1354 const op_ref = operands[i];1354 if (!immediate_death or a.air.mustLower(inst)) {
1355 const operand = Air.refToIndex(op_ref) orelse continue;1355 // Note that it's important we iterate over the operands backwards, so that if a dying
13561356 // operand is used multiple times we mark its last use as its death.
1357 // Don't compute any liveness for constants1357 var i = operands.len;
1358 switch (inst_tags[operand]) {1358 while (i > 0) {
1359 .constant, .const_ty => continue,1359 i -= 1;
1360 else => {},1360 const op_ref = operands[i];
1361 }1361 const operand = Air.refToIndex(op_ref) orelse continue;
1362
1363 // Don't compute any liveness for constants
1364 switch (inst_tags[operand]) {
1365 .constant, .const_ty => continue,
1366 else => {},
1367 }
13621368
1363 const mask = @as(Bpi, 1) << @intCast(OperandInt, i);1369 const mask = @as(Bpi, 1) << @intCast(OperandInt, i);
13641370
1365 if ((try data.live_set.fetchPut(gpa, operand, {})) == null) {1371 if ((try data.live_set.fetchPut(gpa, operand, {})) == null) {
1366 log.debug("[{}] %{}: added %{} to live set (operand dies here)", .{ pass, inst, operand });1372 log.debug("[{}] %{}: added %{} to live set (operand dies here)", .{ pass, inst, operand });
1367 tomb_bits |= mask;1373 tomb_bits |= mask;
1368 if (data.branch_deaths.remove(operand)) {1374 if (data.branch_deaths.remove(operand)) {
1369 log.debug("[{}] %{}: resolved branch death of %{} to this usage", .{ pass, inst, operand });1375 log.debug("[{}] %{}: resolved branch death of %{} to this usage", .{ pass, inst, operand });
1376 }
1370 }1377 }
1371 }1378 }
1372 }1379 }
...@@ -1975,6 +1982,9 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type {...@@ -1975,6 +1982,9 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type {
1975 small: [bpi - 1]Air.Inst.Ref = .{.none} ** (bpi - 1),1982 small: [bpi - 1]Air.Inst.Ref = .{.none} ** (bpi - 1),
1976 extra_tombs: []u32,1983 extra_tombs: []u32,
19771984
1985 // Only used in `LivenessPass.main_analysis`
1986 will_die_immediately: bool,
1987
1978 const Self = @This();1988 const Self = @This();
19791989
1980 fn init(1990 fn init(
...@@ -1994,12 +2004,18 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type {...@@ -1994,12 +2004,18 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type {
19942004
1995 std.mem.set(u32, extra_tombs, 0);2005 std.mem.set(u32, extra_tombs, 0);
19962006
2007 const will_die_immediately: bool = switch (pass) {
2008 .loop_analysis => false, // track everything, since we don't have full liveness information yet
2009 .main_analysis => data.branch_deaths.contains(inst) and !data.live_set.contains(inst),
2010 };
2011
1997 return .{2012 return .{
1998 .a = a,2013 .a = a,
1999 .data = data,2014 .data = data,
2000 .inst = inst,2015 .inst = inst,
2001 .operands_remaining = @intCast(u32, total_operands),2016 .operands_remaining = @intCast(u32, total_operands),
2002 .extra_tombs = extra_tombs,2017 .extra_tombs = extra_tombs,
2018 .will_die_immediately = will_die_immediately,
2003 };2019 };
2004 }2020 }
20052021
...@@ -2022,6 +2038,11 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type {...@@ -2022,6 +2038,11 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type {
2022 else => {},2038 else => {},
2023 }2039 }
20242040
2041 // If our result is unused and the instruction doesn't need to be lowered, backends will
2042 // skip the lowering of this instruction, so we don't want to record uses of operands.
2043 // That way, we can mark as many instructions as possible unused.
2044 if (big.will_die_immediately and !big.a.air.mustLower(big.inst)) return;
2045
2025 const extra_byte = (big.operands_remaining - (bpi - 1)) / 31;2046 const extra_byte = (big.operands_remaining - (bpi - 1)) / 31;
2026 const extra_bit = @intCast(u5, big.operands_remaining - (bpi - 1) - extra_byte * 31);2047 const extra_bit = @intCast(u5, big.operands_remaining - (bpi - 1) - extra_byte * 31);
20272048
src/Liveness/Verify.zig+476-469
...@@ -29,518 +29,525 @@ const LiveMap = std.AutoHashMapUnmanaged(Air.Inst.Index, void);...@@ -29,518 +29,525 @@ const LiveMap = std.AutoHashMapUnmanaged(Air.Inst.Index, void);
29fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {29fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
30 const tag = self.air.instructions.items(.tag);30 const tag = self.air.instructions.items(.tag);
31 const data = self.air.instructions.items(.data);31 const data = self.air.instructions.items(.data);
32 for (body) |inst| switch (tag[inst]) {32 for (body) |inst| {
33 // no operands33 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst)) {
34 .arg,34 // This instruction will not be lowered and should be ignored.
35 .alloc,35 continue;
36 .ret_ptr,36 }
37 .constant,37
38 .const_ty,38 switch (tag[inst]) {
39 .breakpoint,39 // no operands
40 .dbg_stmt,40 .arg,
41 .dbg_inline_begin,41 .alloc,
42 .dbg_inline_end,42 .ret_ptr,
43 .dbg_block_begin,43 .constant,
44 .dbg_block_end,44 .const_ty,
45 .fence,45 .breakpoint,
46 .ret_addr,46 .dbg_stmt,
47 .frame_addr,47 .dbg_inline_begin,
48 .wasm_memory_size,48 .dbg_inline_end,
49 .err_return_trace,49 .dbg_block_begin,
50 .save_err_return_trace_index,50 .dbg_block_end,
51 .c_va_start,51 .fence,
52 .work_item_id,52 .ret_addr,
53 .work_group_size,53 .frame_addr,
54 .work_group_id,54 .wasm_memory_size,
55 => try self.verifyInst(inst, .{ .none, .none, .none }),55 .err_return_trace,
5656 .save_err_return_trace_index,
57 .trap, .unreach => {57 .c_va_start,
58 try self.verifyInst(inst, .{ .none, .none, .none });58 .work_item_id,
59 // This instruction terminates the function, so everything should be dead59 .work_group_size,
60 if (self.live.count() > 0) return invalid("%{}: instructions still alive", .{inst});60 .work_group_id,
61 },61 => try self.verifyInst(inst, .{ .none, .none, .none }),
62
63 .trap, .unreach => {
64 try self.verifyInst(inst, .{ .none, .none, .none });
65 // This instruction terminates the function, so everything should be dead
66 if (self.live.count() > 0) return invalid("%{}: instructions still alive", .{inst});
67 },
68
69 // unary
70 .not,
71 .bitcast,
72 .load,
73 .fpext,
74 .fptrunc,
75 .intcast,
76 .trunc,
77 .optional_payload,
78 .optional_payload_ptr,
79 .optional_payload_ptr_set,
80 .errunion_payload_ptr_set,
81 .wrap_optional,
82 .unwrap_errunion_payload,
83 .unwrap_errunion_err,
84 .unwrap_errunion_payload_ptr,
85 .unwrap_errunion_err_ptr,
86 .wrap_errunion_payload,
87 .wrap_errunion_err,
88 .slice_ptr,
89 .slice_len,
90 .ptr_slice_len_ptr,
91 .ptr_slice_ptr_ptr,
92 .struct_field_ptr_index_0,
93 .struct_field_ptr_index_1,
94 .struct_field_ptr_index_2,
95 .struct_field_ptr_index_3,
96 .array_to_slice,
97 .float_to_int,
98 .float_to_int_optimized,
99 .int_to_float,
100 .get_union_tag,
101 .clz,
102 .ctz,
103 .popcount,
104 .byte_swap,
105 .bit_reverse,
106 .splat,
107 .error_set_has_value,
108 .addrspace_cast,
109 .c_va_arg,
110 .c_va_copy,
111 => {
112 const ty_op = data[inst].ty_op;
113 try self.verifyInst(inst, .{ ty_op.operand, .none, .none });
114 },
115 .is_null,
116 .is_non_null,
117 .is_null_ptr,
118 .is_non_null_ptr,
119 .is_err,
120 .is_non_err,
121 .is_err_ptr,
122 .is_non_err_ptr,
123 .ptrtoint,
124 .bool_to_int,
125 .is_named_enum_value,
126 .tag_name,
127 .error_name,
128 .sqrt,
129 .sin,
130 .cos,
131 .tan,
132 .exp,
133 .exp2,
134 .log,
135 .log2,
136 .log10,
137 .fabs,
138 .floor,
139 .ceil,
140 .round,
141 .trunc_float,
142 .neg,
143 .neg_optimized,
144 .cmp_lt_errors_len,
145 .set_err_return_trace,
146 .c_va_end,
147 => {
148 const un_op = data[inst].un_op;
149 try self.verifyInst(inst, .{ un_op, .none, .none });
150 },
151 .ret,
152 .ret_load,
153 => {
154 const un_op = data[inst].un_op;
155 try self.verifyInst(inst, .{ un_op, .none, .none });
156 // This instruction terminates the function, so everything should be dead
157 if (self.live.count() > 0) return invalid("%{}: instructions still alive", .{inst});
158 },
159 .dbg_var_ptr,
160 .dbg_var_val,
161 .wasm_memory_grow,
162 => {
163 const pl_op = data[inst].pl_op;
164 try self.verifyInst(inst, .{ pl_op.operand, .none, .none });
165 },
166 .prefetch => {
167 const prefetch = data[inst].prefetch;
168 try self.verifyInst(inst, .{ prefetch.ptr, .none, .none });
169 },
170 .reduce,
171 .reduce_optimized,
172 => {
173 const reduce = data[inst].reduce;
174 try self.verifyInst(inst, .{ reduce.operand, .none, .none });
175 },
176 .union_init => {
177 const ty_pl = data[inst].ty_pl;
178 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
179 try self.verifyInst(inst, .{ extra.init, .none, .none });
180 },
181 .struct_field_ptr, .struct_field_val => {
182 const ty_pl = data[inst].ty_pl;
183 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
184 try self.verifyInst(inst, .{ extra.struct_operand, .none, .none });
185 },
186 .field_parent_ptr => {
187 const ty_pl = data[inst].ty_pl;
188 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
189 try self.verifyInst(inst, .{ extra.field_ptr, .none, .none });
190 },
191 .atomic_load => {
192 const atomic_load = data[inst].atomic_load;
193 try self.verifyInst(inst, .{ atomic_load.ptr, .none, .none });
194 },
195
196 // binary
197 .add,
198 .add_optimized,
199 .addwrap,
200 .addwrap_optimized,
201 .add_sat,
202 .sub,
203 .sub_optimized,
204 .subwrap,
205 .subwrap_optimized,
206 .sub_sat,
207 .mul,
208 .mul_optimized,
209 .mulwrap,
210 .mulwrap_optimized,
211 .mul_sat,
212 .div_float,
213 .div_float_optimized,
214 .div_trunc,
215 .div_trunc_optimized,
216 .div_floor,
217 .div_floor_optimized,
218 .div_exact,
219 .div_exact_optimized,
220 .rem,
221 .rem_optimized,
222 .mod,
223 .mod_optimized,
224 .bit_and,
225 .bit_or,
226 .xor,
227 .cmp_lt,
228 .cmp_lt_optimized,
229 .cmp_lte,
230 .cmp_lte_optimized,
231 .cmp_eq,
232 .cmp_eq_optimized,
233 .cmp_gte,
234 .cmp_gte_optimized,
235 .cmp_gt,
236 .cmp_gt_optimized,
237 .cmp_neq,
238 .cmp_neq_optimized,
239 .bool_and,
240 .bool_or,
241 .store,
242 .array_elem_val,
243 .slice_elem_val,
244 .ptr_elem_val,
245 .shl,
246 .shl_exact,
247 .shl_sat,
248 .shr,
249 .shr_exact,
250 .atomic_store_unordered,
251 .atomic_store_monotonic,
252 .atomic_store_release,
253 .atomic_store_seq_cst,
254 .set_union_tag,
255 .min,
256 .max,
257 => {
258 const bin_op = data[inst].bin_op;
259 try self.verifyInst(inst, .{ bin_op.lhs, bin_op.rhs, .none });
260 },
261 .add_with_overflow,
262 .sub_with_overflow,
263 .mul_with_overflow,
264 .shl_with_overflow,
265 .ptr_add,
266 .ptr_sub,
267 .ptr_elem_ptr,
268 .slice_elem_ptr,
269 .slice,
270 => {
271 const ty_pl = data[inst].ty_pl;
272 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
273 try self.verifyInst(inst, .{ extra.lhs, extra.rhs, .none });
274 },
275 .shuffle => {
276 const ty_pl = data[inst].ty_pl;
277 const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data;
278 try self.verifyInst(inst, .{ extra.a, extra.b, .none });
279 },
280 .cmp_vector,
281 .cmp_vector_optimized,
282 => {
283 const ty_pl = data[inst].ty_pl;
284 const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data;
285 try self.verifyInst(inst, .{ extra.lhs, extra.rhs, .none });
286 },
287 .atomic_rmw => {
288 const pl_op = data[inst].pl_op;
289 const extra = self.air.extraData(Air.AtomicRmw, pl_op.payload).data;
290 try self.verifyInst(inst, .{ pl_op.operand, extra.operand, .none });
291 },
292
293 // ternary
294 .select => {
295 const pl_op = data[inst].pl_op;
296 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;
297 try self.verifyInst(inst, .{ pl_op.operand, extra.lhs, extra.rhs });
298 },
299 .mul_add => {
300 const pl_op = data[inst].pl_op;
301 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;
302 try self.verifyInst(inst, .{ extra.lhs, extra.rhs, pl_op.operand });
303 },
304 .vector_store_elem => {
305 const vector_store_elem = data[inst].vector_store_elem;
306 const extra = self.air.extraData(Air.Bin, vector_store_elem.payload).data;
307 try self.verifyInst(inst, .{ vector_store_elem.vector_ptr, extra.lhs, extra.rhs });
308 },
309 .memset,
310 .memcpy,
311 => {
312 const pl_op = data[inst].pl_op;
313 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;
314 try self.verifyInst(inst, .{ pl_op.operand, extra.lhs, extra.rhs });
315 },
316 .cmpxchg_strong,
317 .cmpxchg_weak,
318 => {
319 const ty_pl = data[inst].ty_pl;
320 const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
321 try self.verifyInst(inst, .{ extra.ptr, extra.expected_value, extra.new_value });
322 },
323
324 // big tombs
325 .aggregate_init => {
326 const ty_pl = data[inst].ty_pl;
327 const aggregate_ty = self.air.getRefType(ty_pl.ty);
328 const len = @intCast(usize, aggregate_ty.arrayLen());
329 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
330
331 var bt = self.liveness.iterateBigTomb(inst);
332 for (elements) |element| {
333 try self.verifyOperand(inst, element, bt.feed());
334 }
335 try self.verifyInst(inst, .{ .none, .none, .none });
336 },
337 .call, .call_always_tail, .call_never_tail, .call_never_inline => {
338 const pl_op = data[inst].pl_op;
339 const extra = self.air.extraData(Air.Call, pl_op.payload);
340 const args = @ptrCast(
341 []const Air.Inst.Ref,
342 self.air.extra[extra.end..][0..extra.data.args_len],
343 );
62344
63 // unary345 var bt = self.liveness.iterateBigTomb(inst);
64 .not,346 try self.verifyOperand(inst, pl_op.operand, bt.feed());
65 .bitcast,347 for (args) |arg| {
66 .load,348 try self.verifyOperand(inst, arg, bt.feed());
67 .fpext,349 }
68 .fptrunc,350 try self.verifyInst(inst, .{ .none, .none, .none });
69 .intcast,351 },
70 .trunc,352 .assembly => {
71 .optional_payload,353 const ty_pl = data[inst].ty_pl;
72 .optional_payload_ptr,354 const extra = self.air.extraData(Air.Asm, ty_pl.payload);
73 .optional_payload_ptr_set,355 var extra_i = extra.end;
74 .errunion_payload_ptr_set,356 const outputs = @ptrCast(
75 .wrap_optional,357 []const Air.Inst.Ref,
76 .unwrap_errunion_payload,358 self.air.extra[extra_i..][0..extra.data.outputs_len],
77 .unwrap_errunion_err,359 );
78 .unwrap_errunion_payload_ptr,360 extra_i += outputs.len;
79 .unwrap_errunion_err_ptr,361 const inputs = @ptrCast(
80 .wrap_errunion_payload,362 []const Air.Inst.Ref,
81 .wrap_errunion_err,363 self.air.extra[extra_i..][0..extra.data.inputs_len],
82 .slice_ptr,364 );
83 .slice_len,365 extra_i += inputs.len;
84 .ptr_slice_len_ptr,
85 .ptr_slice_ptr_ptr,
86 .struct_field_ptr_index_0,
87 .struct_field_ptr_index_1,
88 .struct_field_ptr_index_2,
89 .struct_field_ptr_index_3,
90 .array_to_slice,
91 .float_to_int,
92 .float_to_int_optimized,
93 .int_to_float,
94 .get_union_tag,
95 .clz,
96 .ctz,
97 .popcount,
98 .byte_swap,
99 .bit_reverse,
100 .splat,
101 .error_set_has_value,
102 .addrspace_cast,
103 .c_va_arg,
104 .c_va_copy,
105 => {
106 const ty_op = data[inst].ty_op;
107 try self.verifyInst(inst, .{ ty_op.operand, .none, .none });
108 },
109 .is_null,
110 .is_non_null,
111 .is_null_ptr,
112 .is_non_null_ptr,
113 .is_err,
114 .is_non_err,
115 .is_err_ptr,
116 .is_non_err_ptr,
117 .ptrtoint,
118 .bool_to_int,
119 .is_named_enum_value,
120 .tag_name,
121 .error_name,
122 .sqrt,
123 .sin,
124 .cos,
125 .tan,
126 .exp,
127 .exp2,
128 .log,
129 .log2,
130 .log10,
131 .fabs,
132 .floor,
133 .ceil,
134 .round,
135 .trunc_float,
136 .neg,
137 .neg_optimized,
138 .cmp_lt_errors_len,
139 .set_err_return_trace,
140 .c_va_end,
141 => {
142 const un_op = data[inst].un_op;
143 try self.verifyInst(inst, .{ un_op, .none, .none });
144 },
145 .ret,
146 .ret_load,
147 => {
148 const un_op = data[inst].un_op;
149 try self.verifyInst(inst, .{ un_op, .none, .none });
150 // This instruction terminates the function, so everything should be dead
151 if (self.live.count() > 0) return invalid("%{}: instructions still alive", .{inst});
152 },
153 .dbg_var_ptr,
154 .dbg_var_val,
155 .wasm_memory_grow,
156 => {
157 const pl_op = data[inst].pl_op;
158 try self.verifyInst(inst, .{ pl_op.operand, .none, .none });
159 },
160 .prefetch => {
161 const prefetch = data[inst].prefetch;
162 try self.verifyInst(inst, .{ prefetch.ptr, .none, .none });
163 },
164 .reduce,
165 .reduce_optimized,
166 => {
167 const reduce = data[inst].reduce;
168 try self.verifyInst(inst, .{ reduce.operand, .none, .none });
169 },
170 .union_init => {
171 const ty_pl = data[inst].ty_pl;
172 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
173 try self.verifyInst(inst, .{ extra.init, .none, .none });
174 },
175 .struct_field_ptr, .struct_field_val => {
176 const ty_pl = data[inst].ty_pl;
177 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
178 try self.verifyInst(inst, .{ extra.struct_operand, .none, .none });
179 },
180 .field_parent_ptr => {
181 const ty_pl = data[inst].ty_pl;
182 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
183 try self.verifyInst(inst, .{ extra.field_ptr, .none, .none });
184 },
185 .atomic_load => {
186 const atomic_load = data[inst].atomic_load;
187 try self.verifyInst(inst, .{ atomic_load.ptr, .none, .none });
188 },
189366
190 // binary367 var bt = self.liveness.iterateBigTomb(inst);
191 .add,368 for (outputs) |output| {
192 .add_optimized,369 if (output != .none) {
193 .addwrap,370 try self.verifyOperand(inst, output, bt.feed());
194 .addwrap_optimized,371 }
195 .add_sat,372 }
196 .sub,373 for (inputs) |input| {
197 .sub_optimized,374 try self.verifyOperand(inst, input, bt.feed());
198 .subwrap,375 }
199 .subwrap_optimized,376 try self.verifyInst(inst, .{ .none, .none, .none });
200 .sub_sat,377 },
201 .mul,
202 .mul_optimized,
203 .mulwrap,
204 .mulwrap_optimized,
205 .mul_sat,
206 .div_float,
207 .div_float_optimized,
208 .div_trunc,
209 .div_trunc_optimized,
210 .div_floor,
211 .div_floor_optimized,
212 .div_exact,
213 .div_exact_optimized,
214 .rem,
215 .rem_optimized,
216 .mod,
217 .mod_optimized,
218 .bit_and,
219 .bit_or,
220 .xor,
221 .cmp_lt,
222 .cmp_lt_optimized,
223 .cmp_lte,
224 .cmp_lte_optimized,
225 .cmp_eq,
226 .cmp_eq_optimized,
227 .cmp_gte,
228 .cmp_gte_optimized,
229 .cmp_gt,
230 .cmp_gt_optimized,
231 .cmp_neq,
232 .cmp_neq_optimized,
233 .bool_and,
234 .bool_or,
235 .store,
236 .array_elem_val,
237 .slice_elem_val,
238 .ptr_elem_val,
239 .shl,
240 .shl_exact,
241 .shl_sat,
242 .shr,
243 .shr_exact,
244 .atomic_store_unordered,
245 .atomic_store_monotonic,
246 .atomic_store_release,
247 .atomic_store_seq_cst,
248 .set_union_tag,
249 .min,
250 .max,
251 => {
252 const bin_op = data[inst].bin_op;
253 try self.verifyInst(inst, .{ bin_op.lhs, bin_op.rhs, .none });
254 },
255 .add_with_overflow,
256 .sub_with_overflow,
257 .mul_with_overflow,
258 .shl_with_overflow,
259 .ptr_add,
260 .ptr_sub,
261 .ptr_elem_ptr,
262 .slice_elem_ptr,
263 .slice,
264 => {
265 const ty_pl = data[inst].ty_pl;
266 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
267 try self.verifyInst(inst, .{ extra.lhs, extra.rhs, .none });
268 },
269 .shuffle => {
270 const ty_pl = data[inst].ty_pl;
271 const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data;
272 try self.verifyInst(inst, .{ extra.a, extra.b, .none });
273 },
274 .cmp_vector,
275 .cmp_vector_optimized,
276 => {
277 const ty_pl = data[inst].ty_pl;
278 const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data;
279 try self.verifyInst(inst, .{ extra.lhs, extra.rhs, .none });
280 },
281 .atomic_rmw => {
282 const pl_op = data[inst].pl_op;
283 const extra = self.air.extraData(Air.AtomicRmw, pl_op.payload).data;
284 try self.verifyInst(inst, .{ pl_op.operand, extra.operand, .none });
285 },
286378
287 // ternary379 // control flow
288 .select => {380 .@"try" => {
289 const pl_op = data[inst].pl_op;381 const pl_op = data[inst].pl_op;
290 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;382 const extra = self.air.extraData(Air.Try, pl_op.payload);
291 try self.verifyInst(inst, .{ pl_op.operand, extra.lhs, extra.rhs });383 const try_body = self.air.extra[extra.end..][0..extra.data.body_len];
292 },
293 .mul_add => {
294 const pl_op = data[inst].pl_op;
295 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;
296 try self.verifyInst(inst, .{ extra.lhs, extra.rhs, pl_op.operand });
297 },
298 .vector_store_elem => {
299 const vector_store_elem = data[inst].vector_store_elem;
300 const extra = self.air.extraData(Air.Bin, vector_store_elem.payload).data;
301 try self.verifyInst(inst, .{ vector_store_elem.vector_ptr, extra.lhs, extra.rhs });
302 },
303 .memset,
304 .memcpy,
305 => {
306 const pl_op = data[inst].pl_op;
307 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;
308 try self.verifyInst(inst, .{ pl_op.operand, extra.lhs, extra.rhs });
309 },
310 .cmpxchg_strong,
311 .cmpxchg_weak,
312 => {
313 const ty_pl = data[inst].ty_pl;
314 const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
315 try self.verifyInst(inst, .{ extra.ptr, extra.expected_value, extra.new_value });
316 },
317384
318 // big tombs385 const cond_br_liveness = self.liveness.getCondBr(inst);
319 .aggregate_init => {
320 const ty_pl = data[inst].ty_pl;
321 const aggregate_ty = self.air.getRefType(ty_pl.ty);
322 const len = @intCast(usize, aggregate_ty.arrayLen());
323 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
324386
325 var bt = self.liveness.iterateBigTomb(inst);387 try self.verifyOperand(inst, pl_op.operand, self.liveness.operandDies(inst, 0));
326 for (elements) |element| {
327 try self.verifyOperand(inst, element, bt.feed());
328 }
329 try self.verifyInst(inst, .{ .none, .none, .none });
330 },
331 .call, .call_always_tail, .call_never_tail, .call_never_inline => {
332 const pl_op = data[inst].pl_op;
333 const extra = self.air.extraData(Air.Call, pl_op.payload);
334 const args = @ptrCast(
335 []const Air.Inst.Ref,
336 self.air.extra[extra.end..][0..extra.data.args_len],
337 );
338
339 var bt = self.liveness.iterateBigTomb(inst);
340 try self.verifyOperand(inst, pl_op.operand, bt.feed());
341 for (args) |arg| {
342 try self.verifyOperand(inst, arg, bt.feed());
343 }
344 try self.verifyInst(inst, .{ .none, .none, .none });
345 },
346 .assembly => {
347 const ty_pl = data[inst].ty_pl;
348 const extra = self.air.extraData(Air.Asm, ty_pl.payload);
349 var extra_i = extra.end;
350 const outputs = @ptrCast(
351 []const Air.Inst.Ref,
352 self.air.extra[extra_i..][0..extra.data.outputs_len],
353 );
354 extra_i += outputs.len;
355 const inputs = @ptrCast(
356 []const Air.Inst.Ref,
357 self.air.extra[extra_i..][0..extra.data.inputs_len],
358 );
359 extra_i += inputs.len;
360
361 var bt = self.liveness.iterateBigTomb(inst);
362 for (outputs) |output| {
363 if (output != .none) {
364 try self.verifyOperand(inst, output, bt.feed());
365 }
366 }
367 for (inputs) |input| {
368 try self.verifyOperand(inst, input, bt.feed());
369 }
370 try self.verifyInst(inst, .{ .none, .none, .none });
371 },
372388
373 // control flow389 var live = try self.live.clone(self.gpa);
374 .@"try" => {390 defer live.deinit(self.gpa);
375 const pl_op = data[inst].pl_op;
376 const extra = self.air.extraData(Air.Try, pl_op.payload);
377 const try_body = self.air.extra[extra.end..][0..extra.data.body_len];
378391
379 const cond_br_liveness = self.liveness.getCondBr(inst);392 for (cond_br_liveness.else_deaths) |death| try self.verifyDeath(inst, death);
393 try self.verifyBody(try_body);
380394
381 try self.verifyOperand(inst, pl_op.operand, self.liveness.operandDies(inst, 0));395 self.live.deinit(self.gpa);
396 self.live = live.move();
382397
383 var live = try self.live.clone(self.gpa);398 for (cond_br_liveness.then_deaths) |death| try self.verifyDeath(inst, death);
384 defer live.deinit(self.gpa);
385399
386 for (cond_br_liveness.else_deaths) |death| try self.verifyDeath(inst, death);400 try self.verifyInst(inst, .{ .none, .none, .none });
387 try self.verifyBody(try_body);401 },
402 .try_ptr => {
403 const ty_pl = data[inst].ty_pl;
404 const extra = self.air.extraData(Air.TryPtr, ty_pl.payload);
405 const try_body = self.air.extra[extra.end..][0..extra.data.body_len];
388406
389 self.live.deinit(self.gpa);407 const cond_br_liveness = self.liveness.getCondBr(inst);
390 self.live = live.move();
391408
392 for (cond_br_liveness.then_deaths) |death| try self.verifyDeath(inst, death);409 try self.verifyOperand(inst, extra.data.ptr, self.liveness.operandDies(inst, 0));
393410
394 try self.verifyInst(inst, .{ .none, .none, .none });411 var live = try self.live.clone(self.gpa);
395 },412 defer live.deinit(self.gpa);
396 .try_ptr => {
397 const ty_pl = data[inst].ty_pl;
398 const extra = self.air.extraData(Air.TryPtr, ty_pl.payload);
399 const try_body = self.air.extra[extra.end..][0..extra.data.body_len];
400
401 const cond_br_liveness = self.liveness.getCondBr(inst);
402413
403 try self.verifyOperand(inst, extra.data.ptr, self.liveness.operandDies(inst, 0));414 for (cond_br_liveness.else_deaths) |death| try self.verifyDeath(inst, death);
415 try self.verifyBody(try_body);
404416
405 var live = try self.live.clone(self.gpa);417 self.live.deinit(self.gpa);
406 defer live.deinit(self.gpa);418 self.live = live.move();
407419
408 for (cond_br_liveness.else_deaths) |death| try self.verifyDeath(inst, death);420 for (cond_br_liveness.then_deaths) |death| try self.verifyDeath(inst, death);
409 try self.verifyBody(try_body);
410421
411 self.live.deinit(self.gpa);422 try self.verifyInst(inst, .{ .none, .none, .none });
412 self.live = live.move();423 },
424 .br => {
425 const br = data[inst].br;
426 const gop = try self.blocks.getOrPut(self.gpa, br.block_inst);
413427
414 for (cond_br_liveness.then_deaths) |death| try self.verifyDeath(inst, death);428 try self.verifyOperand(inst, br.operand, self.liveness.operandDies(inst, 0));
429 if (gop.found_existing) {
430 try self.verifyMatchingLiveness(br.block_inst, gop.value_ptr.*);
431 } else {
432 gop.value_ptr.* = try self.live.clone(self.gpa);
433 }
434 try self.verifyInst(inst, .{ .none, .none, .none });
435 },
436 .block => {
437 const ty_pl = data[inst].ty_pl;
438 const block_ty = self.air.getRefType(ty_pl.ty);
439 const extra = self.air.extraData(Air.Block, ty_pl.payload);
440 const block_body = self.air.extra[extra.end..][0..extra.data.body_len];
441 const block_liveness = self.liveness.getBlock(inst);
442
443 var orig_live = try self.live.clone(self.gpa);
444 defer orig_live.deinit(self.gpa);
415445
416 try self.verifyInst(inst, .{ .none, .none, .none });446 assert(!self.blocks.contains(inst));
417 },447 try self.verifyBody(block_body);
418 .br => {
419 const br = data[inst].br;
420 const gop = try self.blocks.getOrPut(self.gpa, br.block_inst);
421448
422 try self.verifyOperand(inst, br.operand, self.liveness.operandDies(inst, 0));449 // Liveness data after the block body is garbage, but we want to
423 if (gop.found_existing) {450 // restore it to verify deaths
424 try self.verifyMatchingLiveness(br.block_inst, gop.value_ptr.*);451 self.live.deinit(self.gpa);
425 } else {452 self.live = orig_live.move();
426 gop.value_ptr.* = try self.live.clone(self.gpa);
427 }
428 try self.verifyInst(inst, .{ .none, .none, .none });
429 },
430 .block => {
431 const ty_pl = data[inst].ty_pl;
432 const block_ty = self.air.getRefType(ty_pl.ty);
433 const extra = self.air.extraData(Air.Block, ty_pl.payload);
434 const block_body = self.air.extra[extra.end..][0..extra.data.body_len];
435 const block_liveness = self.liveness.getBlock(inst);
436453
437 var orig_live = try self.live.clone(self.gpa);454 for (block_liveness.deaths) |death| try self.verifyDeath(inst, death);
438 defer orig_live.deinit(self.gpa);
439455
440 assert(!self.blocks.contains(inst));456 if (block_ty.isNoReturn()) {
441 try self.verifyBody(block_body);457 assert(!self.blocks.contains(inst));
458 } else {
459 var live = self.blocks.fetchRemove(inst).?.value;
460 defer live.deinit(self.gpa);
442461
443 // Liveness data after the block body is garbage, but we want to462 try self.verifyMatchingLiveness(inst, live);
444 // restore it to verify deaths463 }
445 self.live.deinit(self.gpa);
446 self.live = orig_live.move();
447464
448 for (block_liveness.deaths) |death| try self.verifyDeath(inst, death);465 try self.verifyInst(inst, .{ .none, .none, .none });
466 },
467 .loop => {
468 const ty_pl = data[inst].ty_pl;
469 const extra = self.air.extraData(Air.Block, ty_pl.payload);
470 const loop_body = self.air.extra[extra.end..][0..extra.data.body_len];
449471
450 if (block_ty.isNoReturn()) {472 var live = try self.live.clone(self.gpa);
451 assert(!self.blocks.contains(inst));
452 } else {
453 var live = self.blocks.fetchRemove(inst).?.value;
454 defer live.deinit(self.gpa);473 defer live.deinit(self.gpa);
455474
456 try self.verifyMatchingLiveness(inst, live);475 try self.verifyBody(loop_body);
457 }
458476
459 try self.verifyInst(inst, .{ .none, .none, .none });477 // The same stuff should be alive after the loop as before it
460 },478 try self.verifyMatchingLiveness(inst, live);
461 .loop => {
462 const ty_pl = data[inst].ty_pl;
463 const extra = self.air.extraData(Air.Block, ty_pl.payload);
464 const loop_body = self.air.extra[extra.end..][0..extra.data.body_len];
465479
466 var live = try self.live.clone(self.gpa);480 try self.verifyInst(inst, .{ .none, .none, .none });
467 defer live.deinit(self.gpa);481 },
482 .cond_br => {
483 const pl_op = data[inst].pl_op;
484 const extra = self.air.extraData(Air.CondBr, pl_op.payload);
485 const then_body = self.air.extra[extra.end..][0..extra.data.then_body_len];
486 const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];
487 const cond_br_liveness = self.liveness.getCondBr(inst);
468488
469 try self.verifyBody(loop_body);489 try self.verifyOperand(inst, pl_op.operand, self.liveness.operandDies(inst, 0));
470490
471 // The same stuff should be alive after the loop as before it491 var live = try self.live.clone(self.gpa);
472 try self.verifyMatchingLiveness(inst, live);492 defer live.deinit(self.gpa);
473493
474 try self.verifyInst(inst, .{ .none, .none, .none });494 for (cond_br_liveness.then_deaths) |death| try self.verifyDeath(inst, death);
475 },495 try self.verifyBody(then_body);
476 .cond_br => {
477 const pl_op = data[inst].pl_op;
478 const extra = self.air.extraData(Air.CondBr, pl_op.payload);
479 const then_body = self.air.extra[extra.end..][0..extra.data.then_body_len];
480 const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];
481 const cond_br_liveness = self.liveness.getCondBr(inst);
482496
483 try self.verifyOperand(inst, pl_op.operand, self.liveness.operandDies(inst, 0));497 self.live.deinit(self.gpa);
498 self.live = live.move();
484499
485 var live = try self.live.clone(self.gpa);500 for (cond_br_liveness.else_deaths) |death| try self.verifyDeath(inst, death);
486 defer live.deinit(self.gpa);501 try self.verifyBody(else_body);
487502
488 for (cond_br_liveness.then_deaths) |death| try self.verifyDeath(inst, death);503 try self.verifyInst(inst, .{ .none, .none, .none });
489 try self.verifyBody(then_body);504 },
505 .switch_br => {
506 const pl_op = data[inst].pl_op;
507 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);
508 var extra_index = switch_br.end;
509 var case_i: u32 = 0;
510 const switch_br_liveness = try self.liveness.getSwitchBr(
511 self.gpa,
512 inst,
513 switch_br.data.cases_len + 1,
514 );
515 defer self.gpa.free(switch_br_liveness.deaths);
490516
491 self.live.deinit(self.gpa);517 try self.verifyOperand(inst, pl_op.operand, self.liveness.operandDies(inst, 0));
492 self.live = live.move();
493518
494 for (cond_br_liveness.else_deaths) |death| try self.verifyDeath(inst, death);519 var live = self.live.move();
495 try self.verifyBody(else_body);520 defer live.deinit(self.gpa);
496521
497 try self.verifyInst(inst, .{ .none, .none, .none });522 while (case_i < switch_br.data.cases_len) : (case_i += 1) {
498 },523 const case = self.air.extraData(Air.SwitchBr.Case, extra_index);
499 .switch_br => {524 const items = @ptrCast(
500 const pl_op = data[inst].pl_op;525 []const Air.Inst.Ref,
501 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);526 self.air.extra[case.end..][0..case.data.items_len],
502 var extra_index = switch_br.end;527 );
503 var case_i: u32 = 0;528 const case_body = self.air.extra[case.end + items.len ..][0..case.data.body_len];
504 const switch_br_liveness = try self.liveness.getSwitchBr(529 extra_index = case.end + items.len + case_body.len;
505 self.gpa,
506 inst,
507 switch_br.data.cases_len + 1,
508 );
509 defer self.gpa.free(switch_br_liveness.deaths);
510
511 try self.verifyOperand(inst, pl_op.operand, self.liveness.operandDies(inst, 0));
512
513 var live = self.live.move();
514 defer live.deinit(self.gpa);
515
516 while (case_i < switch_br.data.cases_len) : (case_i += 1) {
517 const case = self.air.extraData(Air.SwitchBr.Case, extra_index);
518 const items = @ptrCast(
519 []const Air.Inst.Ref,
520 self.air.extra[case.end..][0..case.data.items_len],
521 );
522 const case_body = self.air.extra[case.end + items.len ..][0..case.data.body_len];
523 extra_index = case.end + items.len + case_body.len;
524530
525 self.live.deinit(self.gpa);531 self.live.deinit(self.gpa);
526 self.live = try live.clone(self.gpa);532 self.live = try live.clone(self.gpa);
527533
528 for (switch_br_liveness.deaths[case_i]) |death| try self.verifyDeath(inst, death);534 for (switch_br_liveness.deaths[case_i]) |death| try self.verifyDeath(inst, death);
529 try self.verifyBody(case_body);535 try self.verifyBody(case_body);
530 }536 }
531537
532 const else_body = self.air.extra[extra_index..][0..switch_br.data.else_body_len];538 const else_body = self.air.extra[extra_index..][0..switch_br.data.else_body_len];
533 if (else_body.len > 0) {539 if (else_body.len > 0) {
534 self.live.deinit(self.gpa);540 self.live.deinit(self.gpa);
535 self.live = try live.clone(self.gpa);541 self.live = try live.clone(self.gpa);
536542
537 for (switch_br_liveness.deaths[case_i]) |death| try self.verifyDeath(inst, death);543 for (switch_br_liveness.deaths[case_i]) |death| try self.verifyDeath(inst, death);
538 try self.verifyBody(else_body);544 try self.verifyBody(else_body);
539 }545 }
540546
541 try self.verifyInst(inst, .{ .none, .none, .none });547 try self.verifyInst(inst, .{ .none, .none, .none });
542 },548 },
543 };549 }
550 }
544}551}
545552
546fn verifyDeath(self: *Verify, inst: Air.Inst.Index, operand: Air.Inst.Index) Error!void {553fn verifyDeath(self: *Verify, inst: Air.Inst.Index, operand: Air.Inst.Index) Error!void {
src/codegen/llvm.zig+6-187
...@@ -4523,6 +4523,10 @@ pub const FuncGen = struct {...@@ -4523,6 +4523,10 @@ pub const FuncGen = struct {
4523 fn genBody(self: *FuncGen, body: []const Air.Inst.Index) Error!void {4523 fn genBody(self: *FuncGen, body: []const Air.Inst.Index) Error!void {
4524 const air_tags = self.air.instructions.items(.tag);4524 const air_tags = self.air.instructions.items(.tag);
4525 for (body, 0..) |inst, i| {4525 for (body, 0..) |inst, i| {
4526 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst)) {
4527 continue;
4528 }
4529
4526 const opt_value: ?*llvm.Value = switch (air_tags[inst]) {4530 const opt_value: ?*llvm.Value = switch (air_tags[inst]) {
4527 // zig fmt: off4531 // zig fmt: off
4528 .add => try self.airAdd(inst, false),4532 .add => try self.airAdd(inst, false),
...@@ -5166,8 +5170,6 @@ pub const FuncGen = struct {...@@ -5166,8 +5170,6 @@ pub const FuncGen = struct {
5166 }5170 }
51675171
5168 fn airCVaArg(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5172 fn airCVaArg(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5169 if (self.liveness.isUnused(inst)) return null;
5170
5171 const ty_op = self.air.instructions.items(.data)[inst].ty_op;5173 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
5172 const list = try self.resolveInst(ty_op.operand);5174 const list = try self.resolveInst(ty_op.operand);
5173 const arg_ty = self.air.getRefType(ty_op.ty);5175 const arg_ty = self.air.getRefType(ty_op.ty);
...@@ -5177,8 +5179,6 @@ pub const FuncGen = struct {...@@ -5177,8 +5179,6 @@ pub const FuncGen = struct {
5177 }5179 }
51785180
5179 fn airCVaCopy(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5181 fn airCVaCopy(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5180 if (self.liveness.isUnused(inst)) return null;
5181
5182 const ty_op = self.air.instructions.items(.data)[inst].ty_op;5182 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
5183 const src_list = try self.resolveInst(ty_op.operand);5183 const src_list = try self.resolveInst(ty_op.operand);
5184 const va_list_ty = self.air.getRefType(ty_op.ty);5184 const va_list_ty = self.air.getRefType(ty_op.ty);
...@@ -5226,8 +5226,6 @@ pub const FuncGen = struct {...@@ -5226,8 +5226,6 @@ pub const FuncGen = struct {
5226 }5226 }
52275227
5228 fn airCVaStart(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5228 fn airCVaStart(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5229 if (self.liveness.isUnused(inst)) return null;
5230
5231 const va_list_ty = self.air.typeOfIndex(inst);5229 const va_list_ty = self.air.typeOfIndex(inst);
5232 const llvm_va_list_ty = try self.dg.lowerType(va_list_ty);5230 const llvm_va_list_ty = try self.dg.lowerType(va_list_ty);
52335231
...@@ -5254,7 +5252,6 @@ pub const FuncGen = struct {...@@ -5254,7 +5252,6 @@ pub const FuncGen = struct {
5254 }5252 }
52555253
5256 fn airCmp(self: *FuncGen, inst: Air.Inst.Index, op: math.CompareOperator, want_fast_math: bool) !?*llvm.Value {5254 fn airCmp(self: *FuncGen, inst: Air.Inst.Index, op: math.CompareOperator, want_fast_math: bool) !?*llvm.Value {
5257 if (self.liveness.isUnused(inst)) return null;
5258 self.builder.setFastMath(want_fast_math);5255 self.builder.setFastMath(want_fast_math);
52595256
5260 const bin_op = self.air.instructions.items(.data)[inst].bin_op;5257 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -5266,7 +5263,6 @@ pub const FuncGen = struct {...@@ -5266,7 +5263,6 @@ pub const FuncGen = struct {
5266 }5263 }
52675264
5268 fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {5265 fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
5269 if (self.liveness.isUnused(inst)) return null;
5270 self.builder.setFastMath(want_fast_math);5266 self.builder.setFastMath(want_fast_math);
52715267
5272 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;5268 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
...@@ -5281,8 +5277,6 @@ pub const FuncGen = struct {...@@ -5281,8 +5277,6 @@ pub const FuncGen = struct {
5281 }5277 }
52825278
5283 fn airCmpLtErrorsLen(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5279 fn airCmpLtErrorsLen(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5284 if (self.liveness.isUnused(inst)) return null;
5285
5286 const un_op = self.air.instructions.items(.data)[inst].un_op;5280 const un_op = self.air.instructions.items(.data)[inst].un_op;
5287 const operand = try self.resolveInst(un_op);5281 const operand = try self.resolveInst(un_op);
5288 const llvm_fn = try self.getCmpLtErrorsLenFunction();5282 const llvm_fn = try self.getCmpLtErrorsLenFunction();
...@@ -5650,9 +5644,6 @@ pub const FuncGen = struct {...@@ -5650,9 +5644,6 @@ pub const FuncGen = struct {
5650 }5644 }
56515645
5652 fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5646 fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5653 if (self.liveness.isUnused(inst))
5654 return null;
5655
5656 const ty_op = self.air.instructions.items(.data)[inst].ty_op;5647 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
5657 const operand_ty = self.air.typeOf(ty_op.operand);5648 const operand_ty = self.air.typeOf(ty_op.operand);
5658 const array_ty = operand_ty.childType();5649 const array_ty = operand_ty.childType();
...@@ -5674,9 +5665,6 @@ pub const FuncGen = struct {...@@ -5674,9 +5665,6 @@ pub const FuncGen = struct {
5674 }5665 }
56755666
5676 fn airIntToFloat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5667 fn airIntToFloat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5677 if (self.liveness.isUnused(inst))
5678 return null;
5679
5680 const ty_op = self.air.instructions.items(.data)[inst].ty_op;5668 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
56815669
5682 const operand = try self.resolveInst(ty_op.operand);5670 const operand = try self.resolveInst(ty_op.operand);
...@@ -5733,9 +5721,6 @@ pub const FuncGen = struct {...@@ -5733,9 +5721,6 @@ pub const FuncGen = struct {
5733 }5721 }
57345722
5735 fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {5723 fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
5736 if (self.liveness.isUnused(inst))
5737 return null;
5738
5739 self.builder.setFastMath(want_fast_math);5724 self.builder.setFastMath(want_fast_math);
57405725
5741 const target = self.dg.module.getTarget();5726 const target = self.dg.module.getTarget();
...@@ -5792,16 +5777,12 @@ pub const FuncGen = struct {...@@ -5792,16 +5777,12 @@ pub const FuncGen = struct {
5792 }5777 }
57935778
5794 fn airSliceField(self: *FuncGen, inst: Air.Inst.Index, index: c_uint) !?*llvm.Value {5779 fn airSliceField(self: *FuncGen, inst: Air.Inst.Index, index: c_uint) !?*llvm.Value {
5795 if (self.liveness.isUnused(inst)) return null;
5796
5797 const ty_op = self.air.instructions.items(.data)[inst].ty_op;5780 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
5798 const operand = try self.resolveInst(ty_op.operand);5781 const operand = try self.resolveInst(ty_op.operand);
5799 return self.builder.buildExtractValue(operand, index, "");5782 return self.builder.buildExtractValue(operand, index, "");
5800 }5783 }
58015784
5802 fn airPtrSliceFieldPtr(self: *FuncGen, inst: Air.Inst.Index, index: c_uint) !?*llvm.Value {5785 fn airPtrSliceFieldPtr(self: *FuncGen, inst: Air.Inst.Index, index: c_uint) !?*llvm.Value {
5803 if (self.liveness.isUnused(inst)) return null;
5804
5805 const ty_op = self.air.instructions.items(.data)[inst].ty_op;5786 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
5806 const slice_ptr = try self.resolveInst(ty_op.operand);5787 const slice_ptr = try self.resolveInst(ty_op.operand);
5807 const slice_ptr_ty = self.air.typeOf(ty_op.operand);5788 const slice_ptr_ty = self.air.typeOf(ty_op.operand);
...@@ -5814,8 +5795,6 @@ pub const FuncGen = struct {...@@ -5814,8 +5795,6 @@ pub const FuncGen = struct {
5814 const inst = body_tail[0];5795 const inst = body_tail[0];
5815 const bin_op = self.air.instructions.items(.data)[inst].bin_op;5796 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
5816 const slice_ty = self.air.typeOf(bin_op.lhs);5797 const slice_ty = self.air.typeOf(bin_op.lhs);
5817 if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null;
5818
5819 const slice = try self.resolveInst(bin_op.lhs);5798 const slice = try self.resolveInst(bin_op.lhs);
5820 const index = try self.resolveInst(bin_op.rhs);5799 const index = try self.resolveInst(bin_op.rhs);
5821 const elem_ty = slice_ty.childType();5800 const elem_ty = slice_ty.childType();
...@@ -5835,7 +5814,6 @@ pub const FuncGen = struct {...@@ -5835,7 +5814,6 @@ pub const FuncGen = struct {
5835 }5814 }
58365815
5837 fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5816 fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5838 if (self.liveness.isUnused(inst)) return null;
5839 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;5817 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5840 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;5818 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
5841 const slice_ty = self.air.typeOf(bin_op.lhs);5819 const slice_ty = self.air.typeOf(bin_op.lhs);
...@@ -5850,7 +5828,6 @@ pub const FuncGen = struct {...@@ -5850,7 +5828,6 @@ pub const FuncGen = struct {
58505828
5851 fn airArrayElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {5829 fn airArrayElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {
5852 const inst = body_tail[0];5830 const inst = body_tail[0];
5853 if (self.liveness.isUnused(inst)) return null;
58545831
5855 const bin_op = self.air.instructions.items(.data)[inst].bin_op;5832 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
5856 const array_ty = self.air.typeOf(bin_op.lhs);5833 const array_ty = self.air.typeOf(bin_op.lhs);
...@@ -5881,8 +5858,6 @@ pub const FuncGen = struct {...@@ -5881,8 +5858,6 @@ pub const FuncGen = struct {
5881 const inst = body_tail[0];5858 const inst = body_tail[0];
5882 const bin_op = self.air.instructions.items(.data)[inst].bin_op;5859 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
5883 const ptr_ty = self.air.typeOf(bin_op.lhs);5860 const ptr_ty = self.air.typeOf(bin_op.lhs);
5884 if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null;
5885
5886 const elem_ty = ptr_ty.childType();5861 const elem_ty = ptr_ty.childType();
5887 const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty);5862 const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty);
5888 const base_ptr = try self.resolveInst(bin_op.lhs);5863 const base_ptr = try self.resolveInst(bin_op.lhs);
...@@ -5908,8 +5883,6 @@ pub const FuncGen = struct {...@@ -5908,8 +5883,6 @@ pub const FuncGen = struct {
5908 }5883 }
59095884
5910 fn airPtrElemPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5885 fn airPtrElemPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5911 if (self.liveness.isUnused(inst)) return null;
5912
5913 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;5886 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5914 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;5887 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
5915 const ptr_ty = self.air.typeOf(bin_op.lhs);5888 const ptr_ty = self.air.typeOf(bin_op.lhs);
...@@ -5934,9 +5907,6 @@ pub const FuncGen = struct {...@@ -5934,9 +5907,6 @@ pub const FuncGen = struct {
5934 }5907 }
59355908
5936 fn airStructFieldPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5909 fn airStructFieldPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5937 if (self.liveness.isUnused(inst))
5938 return null;
5939
5940 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;5910 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5941 const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data;5911 const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data;
5942 const struct_ptr = try self.resolveInst(struct_field.struct_operand);5912 const struct_ptr = try self.resolveInst(struct_field.struct_operand);
...@@ -5949,8 +5919,6 @@ pub const FuncGen = struct {...@@ -5949,8 +5919,6 @@ pub const FuncGen = struct {
5949 inst: Air.Inst.Index,5919 inst: Air.Inst.Index,
5950 field_index: u32,5920 field_index: u32,
5951 ) !?*llvm.Value {5921 ) !?*llvm.Value {
5952 if (self.liveness.isUnused(inst)) return null;
5953
5954 const ty_op = self.air.instructions.items(.data)[inst].ty_op;5922 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
5955 const struct_ptr = try self.resolveInst(ty_op.operand);5923 const struct_ptr = try self.resolveInst(ty_op.operand);
5956 const struct_ptr_ty = self.air.typeOf(ty_op.operand);5924 const struct_ptr_ty = self.air.typeOf(ty_op.operand);
...@@ -5959,8 +5927,6 @@ pub const FuncGen = struct {...@@ -5959,8 +5927,6 @@ pub const FuncGen = struct {
59595927
5960 fn airStructFieldVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {5928 fn airStructFieldVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {
5961 const inst = body_tail[0];5929 const inst = body_tail[0];
5962 if (self.liveness.isUnused(inst)) return null;
5963
5964 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;5930 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5965 const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data;5931 const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data;
5966 const struct_ty = self.air.typeOf(struct_field.struct_operand);5932 const struct_ty = self.air.typeOf(struct_field.struct_operand);
...@@ -6060,8 +6026,6 @@ pub const FuncGen = struct {...@@ -6060,8 +6026,6 @@ pub const FuncGen = struct {
6060 }6026 }
60616027
6062 fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6028 fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6063 if (self.liveness.isUnused(inst)) return null;
6064
6065 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;6029 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
6066 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;6030 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
60676031
...@@ -6083,9 +6047,6 @@ pub const FuncGen = struct {...@@ -6083,9 +6047,6 @@ pub const FuncGen = struct {
6083 }6047 }
60846048
6085 fn airNot(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6049 fn airNot(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6086 if (self.liveness.isUnused(inst))
6087 return null;
6088
6089 const ty_op = self.air.instructions.items(.data)[inst].ty_op;6050 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
6090 const operand = try self.resolveInst(ty_op.operand);6051 const operand = try self.resolveInst(ty_op.operand);
60916052
...@@ -6263,8 +6224,6 @@ pub const FuncGen = struct {...@@ -6263,8 +6224,6 @@ pub const FuncGen = struct {
6263 const clobbers_len = @truncate(u31, extra.data.flags);6224 const clobbers_len = @truncate(u31, extra.data.flags);
6264 var extra_i: usize = extra.end;6225 var extra_i: usize = extra.end;
62656226
6266 if (!is_volatile and self.liveness.isUnused(inst)) return null;
6267
6268 const outputs = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra_i..][0..extra.data.outputs_len]);6227 const outputs = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra_i..][0..extra.data.outputs_len]);
6269 extra_i += outputs.len;6228 extra_i += outputs.len;
6270 const inputs = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra_i..][0..extra.data.inputs_len]);6229 const inputs = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra_i..][0..extra.data.inputs_len]);
...@@ -6610,8 +6569,6 @@ pub const FuncGen = struct {...@@ -6610,8 +6569,6 @@ pub const FuncGen = struct {
6610 operand_is_ptr: bool,6569 operand_is_ptr: bool,
6611 pred: llvm.IntPredicate,6570 pred: llvm.IntPredicate,
6612 ) !?*llvm.Value {6571 ) !?*llvm.Value {
6613 if (self.liveness.isUnused(inst)) return null;
6614
6615 const un_op = self.air.instructions.items(.data)[inst].un_op;6572 const un_op = self.air.instructions.items(.data)[inst].un_op;
6616 const operand = try self.resolveInst(un_op);6573 const operand = try self.resolveInst(un_op);
6617 const operand_ty = self.air.typeOf(un_op);6574 const operand_ty = self.air.typeOf(un_op);
...@@ -6659,8 +6616,6 @@ pub const FuncGen = struct {...@@ -6659,8 +6616,6 @@ pub const FuncGen = struct {
6659 op: llvm.IntPredicate,6616 op: llvm.IntPredicate,
6660 operand_is_ptr: bool,6617 operand_is_ptr: bool,
6661 ) !?*llvm.Value {6618 ) !?*llvm.Value {
6662 if (self.liveness.isUnused(inst)) return null;
6663
6664 const un_op = self.air.instructions.items(.data)[inst].un_op;6619 const un_op = self.air.instructions.items(.data)[inst].un_op;
6665 const operand = try self.resolveInst(un_op);6620 const operand = try self.resolveInst(un_op);
6666 const operand_ty = self.air.typeOf(un_op);6621 const operand_ty = self.air.typeOf(un_op);
...@@ -6701,8 +6656,6 @@ pub const FuncGen = struct {...@@ -6701,8 +6656,6 @@ pub const FuncGen = struct {
6701 }6656 }
67026657
6703 fn airOptionalPayloadPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6658 fn airOptionalPayloadPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6704 if (self.liveness.isUnused(inst)) return null;
6705
6706 const ty_op = self.air.instructions.items(.data)[inst].ty_op;6659 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
6707 const operand = try self.resolveInst(ty_op.operand);6660 const operand = try self.resolveInst(ty_op.operand);
6708 const optional_ty = self.air.typeOf(ty_op.operand).childType();6661 const optional_ty = self.air.typeOf(ty_op.operand).childType();
...@@ -6756,8 +6709,6 @@ pub const FuncGen = struct {...@@ -6756,8 +6709,6 @@ pub const FuncGen = struct {
67566709
6757 fn airOptionalPayload(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {6710 fn airOptionalPayload(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {
6758 const inst = body_tail[0];6711 const inst = body_tail[0];
6759 if (self.liveness.isUnused(inst)) return null;
6760
6761 const ty_op = self.air.instructions.items(.data)[inst].ty_op;6712 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
6762 const operand = try self.resolveInst(ty_op.operand);6713 const operand = try self.resolveInst(ty_op.operand);
6763 const optional_ty = self.air.typeOf(ty_op.operand);6714 const optional_ty = self.air.typeOf(ty_op.operand);
...@@ -6780,8 +6731,6 @@ pub const FuncGen = struct {...@@ -6780,8 +6731,6 @@ pub const FuncGen = struct {
6780 operand_is_ptr: bool,6731 operand_is_ptr: bool,
6781 ) !?*llvm.Value {6732 ) !?*llvm.Value {
6782 const inst = body_tail[0];6733 const inst = body_tail[0];
6783 if (self.liveness.isUnused(inst)) return null;
6784
6785 const ty_op = self.air.instructions.items(.data)[inst].ty_op;6734 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
6786 const operand = try self.resolveInst(ty_op.operand);6735 const operand = try self.resolveInst(ty_op.operand);
6787 const operand_ty = self.air.typeOf(ty_op.operand);6736 const operand_ty = self.air.typeOf(ty_op.operand);
...@@ -6817,9 +6766,6 @@ pub const FuncGen = struct {...@@ -6817,9 +6766,6 @@ pub const FuncGen = struct {
6817 inst: Air.Inst.Index,6766 inst: Air.Inst.Index,
6818 operand_is_ptr: bool,6767 operand_is_ptr: bool,
6819 ) !?*llvm.Value {6768 ) !?*llvm.Value {
6820 if (self.liveness.isUnused(inst))
6821 return null;
6822
6823 const ty_op = self.air.instructions.items(.data)[inst].ty_op;6769 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
6824 const operand = try self.resolveInst(ty_op.operand);6770 const operand = try self.resolveInst(ty_op.operand);
6825 const operand_ty = self.air.typeOf(ty_op.operand);6771 const operand_ty = self.air.typeOf(ty_op.operand);
...@@ -6893,8 +6839,6 @@ pub const FuncGen = struct {...@@ -6893,8 +6839,6 @@ pub const FuncGen = struct {
6893 }6839 }
68946840
6895 fn airSaveErrReturnTraceIndex(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6841 fn airSaveErrReturnTraceIndex(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6896 if (self.liveness.isUnused(inst)) return null;
6897
6898 const target = self.dg.module.getTarget();6842 const target = self.dg.module.getTarget();
68996843
6900 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;6844 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
...@@ -6911,8 +6855,6 @@ pub const FuncGen = struct {...@@ -6911,8 +6855,6 @@ pub const FuncGen = struct {
6911 }6855 }
69126856
6913 fn airWrapOptional(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6857 fn airWrapOptional(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6914 if (self.liveness.isUnused(inst)) return null;
6915
6916 const ty_op = self.air.instructions.items(.data)[inst].ty_op;6858 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
6917 const payload_ty = self.air.typeOf(ty_op.operand);6859 const payload_ty = self.air.typeOf(ty_op.operand);
6918 const non_null_bit = self.context.intType(8).constInt(1, .False);6860 const non_null_bit = self.context.intType(8).constInt(1, .False);
...@@ -6943,8 +6885,6 @@ pub const FuncGen = struct {...@@ -6943,8 +6885,6 @@ pub const FuncGen = struct {
6943 }6885 }
69446886
6945 fn airWrapErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6887 fn airWrapErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6946 if (self.liveness.isUnused(inst)) return null;
6947
6948 const ty_op = self.air.instructions.items(.data)[inst].ty_op;6888 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
6949 const err_un_ty = self.air.typeOfIndex(inst);6889 const err_un_ty = self.air.typeOfIndex(inst);
6950 const operand = try self.resolveInst(ty_op.operand);6890 const operand = try self.resolveInst(ty_op.operand);
...@@ -6978,8 +6918,6 @@ pub const FuncGen = struct {...@@ -6978,8 +6918,6 @@ pub const FuncGen = struct {
6978 }6918 }
69796919
6980 fn airWrapErrUnionErr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6920 fn airWrapErrUnionErr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6981 if (self.liveness.isUnused(inst)) return null;
6982
6983 const ty_op = self.air.instructions.items(.data)[inst].ty_op;6921 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
6984 const err_un_ty = self.air.typeOfIndex(inst);6922 const err_un_ty = self.air.typeOfIndex(inst);
6985 const payload_ty = err_un_ty.errorUnionPayload();6923 const payload_ty = err_un_ty.errorUnionPayload();
...@@ -7015,8 +6953,6 @@ pub const FuncGen = struct {...@@ -7015,8 +6953,6 @@ pub const FuncGen = struct {
7015 }6953 }
70166954
7017 fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6955 fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7018 if (self.liveness.isUnused(inst)) return null;
7019
7020 const pl_op = self.air.instructions.items(.data)[inst].pl_op;6956 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
7021 const index = pl_op.payload;6957 const index = pl_op.payload;
7022 const llvm_u32 = self.context.intType(32);6958 const llvm_u32 = self.context.intType(32);
...@@ -7061,8 +6997,6 @@ pub const FuncGen = struct {...@@ -7061,8 +6997,6 @@ pub const FuncGen = struct {
7061 }6997 }
70626998
7063 fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {6999 fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7064 if (self.liveness.isUnused(inst)) return null;
7065
7066 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7000 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7067 const lhs = try self.resolveInst(bin_op.lhs);7001 const lhs = try self.resolveInst(bin_op.lhs);
7068 const rhs = try self.resolveInst(bin_op.rhs);7002 const rhs = try self.resolveInst(bin_op.rhs);
...@@ -7074,8 +7008,6 @@ pub const FuncGen = struct {...@@ -7074,8 +7008,6 @@ pub const FuncGen = struct {
7074 }7008 }
70757009
7076 fn airMax(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7010 fn airMax(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7077 if (self.liveness.isUnused(inst)) return null;
7078
7079 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7011 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7080 const lhs = try self.resolveInst(bin_op.lhs);7012 const lhs = try self.resolveInst(bin_op.lhs);
7081 const rhs = try self.resolveInst(bin_op.rhs);7013 const rhs = try self.resolveInst(bin_op.rhs);
...@@ -7087,8 +7019,6 @@ pub const FuncGen = struct {...@@ -7087,8 +7019,6 @@ pub const FuncGen = struct {
7087 }7019 }
70887020
7089 fn airSlice(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7021 fn airSlice(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7090 if (self.liveness.isUnused(inst)) return null;
7091
7092 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;7022 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
7093 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;7023 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
7094 const ptr = try self.resolveInst(bin_op.lhs);7024 const ptr = try self.resolveInst(bin_op.lhs);
...@@ -7103,7 +7033,6 @@ pub const FuncGen = struct {...@@ -7103,7 +7033,6 @@ pub const FuncGen = struct {
7103 }7033 }
71047034
7105 fn airAdd(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {7035 fn airAdd(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7106 if (self.liveness.isUnused(inst)) return null;
7107 self.builder.setFastMath(want_fast_math);7036 self.builder.setFastMath(want_fast_math);
71087037
7109 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7038 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7118,7 +7047,6 @@ pub const FuncGen = struct {...@@ -7118,7 +7047,6 @@ pub const FuncGen = struct {
7118 }7047 }
71197048
7120 fn airAddWrap(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {7049 fn airAddWrap(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7121 if (self.liveness.isUnused(inst)) return null;
7122 self.builder.setFastMath(want_fast_math);7050 self.builder.setFastMath(want_fast_math);
71237051
7124 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7052 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7129,8 +7057,6 @@ pub const FuncGen = struct {...@@ -7129,8 +7057,6 @@ pub const FuncGen = struct {
7129 }7057 }
71307058
7131 fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7059 fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7132 if (self.liveness.isUnused(inst)) return null;
7133
7134 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7060 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7135 const lhs = try self.resolveInst(bin_op.lhs);7061 const lhs = try self.resolveInst(bin_op.lhs);
7136 const rhs = try self.resolveInst(bin_op.rhs);7062 const rhs = try self.resolveInst(bin_op.rhs);
...@@ -7144,7 +7070,6 @@ pub const FuncGen = struct {...@@ -7144,7 +7070,6 @@ pub const FuncGen = struct {
7144 }7070 }
71457071
7146 fn airSub(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {7072 fn airSub(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7147 if (self.liveness.isUnused(inst)) return null;
7148 self.builder.setFastMath(want_fast_math);7073 self.builder.setFastMath(want_fast_math);
71497074
7150 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7075 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7159,7 +7084,6 @@ pub const FuncGen = struct {...@@ -7159,7 +7084,6 @@ pub const FuncGen = struct {
7159 }7084 }
71607085
7161 fn airSubWrap(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {7086 fn airSubWrap(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7162 if (self.liveness.isUnused(inst)) return null;
7163 self.builder.setFastMath(want_fast_math);7087 self.builder.setFastMath(want_fast_math);
71647088
7165 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7089 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7170,8 +7094,6 @@ pub const FuncGen = struct {...@@ -7170,8 +7094,6 @@ pub const FuncGen = struct {
7170 }7094 }
71717095
7172 fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7096 fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7173 if (self.liveness.isUnused(inst)) return null;
7174
7175 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7097 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7176 const lhs = try self.resolveInst(bin_op.lhs);7098 const lhs = try self.resolveInst(bin_op.lhs);
7177 const rhs = try self.resolveInst(bin_op.rhs);7099 const rhs = try self.resolveInst(bin_op.rhs);
...@@ -7184,7 +7106,6 @@ pub const FuncGen = struct {...@@ -7184,7 +7106,6 @@ pub const FuncGen = struct {
7184 }7106 }
71857107
7186 fn airMul(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {7108 fn airMul(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7187 if (self.liveness.isUnused(inst)) return null;
7188 self.builder.setFastMath(want_fast_math);7109 self.builder.setFastMath(want_fast_math);
71897110
7190 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7111 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7199,7 +7120,6 @@ pub const FuncGen = struct {...@@ -7199,7 +7120,6 @@ pub const FuncGen = struct {
7199 }7120 }
72007121
7201 fn airMulWrap(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {7122 fn airMulWrap(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7202 if (self.liveness.isUnused(inst)) return null;
7203 self.builder.setFastMath(want_fast_math);7123 self.builder.setFastMath(want_fast_math);
72047124
7205 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7125 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7210,8 +7130,6 @@ pub const FuncGen = struct {...@@ -7210,8 +7130,6 @@ pub const FuncGen = struct {
7210 }7130 }
72117131
7212 fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7132 fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7213 if (self.liveness.isUnused(inst)) return null;
7214
7215 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7133 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7216 const lhs = try self.resolveInst(bin_op.lhs);7134 const lhs = try self.resolveInst(bin_op.lhs);
7217 const rhs = try self.resolveInst(bin_op.rhs);7135 const rhs = try self.resolveInst(bin_op.rhs);
...@@ -7224,7 +7142,6 @@ pub const FuncGen = struct {...@@ -7224,7 +7142,6 @@ pub const FuncGen = struct {
7224 }7142 }
72257143
7226 fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {7144 fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7227 if (self.liveness.isUnused(inst)) return null;
7228 self.builder.setFastMath(want_fast_math);7145 self.builder.setFastMath(want_fast_math);
72297146
7230 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7147 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7236,7 +7153,6 @@ pub const FuncGen = struct {...@@ -7236,7 +7153,6 @@ pub const FuncGen = struct {
7236 }7153 }
72377154
7238 fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {7155 fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7239 if (self.liveness.isUnused(inst)) return null;
7240 self.builder.setFastMath(want_fast_math);7156 self.builder.setFastMath(want_fast_math);
72417157
7242 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7158 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7254,7 +7170,6 @@ pub const FuncGen = struct {...@@ -7254,7 +7170,6 @@ pub const FuncGen = struct {
7254 }7170 }
72557171
7256 fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {7172 fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7257 if (self.liveness.isUnused(inst)) return null;
7258 self.builder.setFastMath(want_fast_math);7173 self.builder.setFastMath(want_fast_math);
72597174
7260 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7175 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7287,7 +7202,6 @@ pub const FuncGen = struct {...@@ -7287,7 +7202,6 @@ pub const FuncGen = struct {
7287 }7202 }
72887203
7289 fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {7204 fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7290 if (self.liveness.isUnused(inst)) return null;
7291 self.builder.setFastMath(want_fast_math);7205 self.builder.setFastMath(want_fast_math);
72927206
7293 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7207 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7302,7 +7216,6 @@ pub const FuncGen = struct {...@@ -7302,7 +7216,6 @@ pub const FuncGen = struct {
7302 }7216 }
73037217
7304 fn airRem(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {7218 fn airRem(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7305 if (self.liveness.isUnused(inst)) return null;
7306 self.builder.setFastMath(want_fast_math);7219 self.builder.setFastMath(want_fast_math);
73077220
7308 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7221 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7317,7 +7230,6 @@ pub const FuncGen = struct {...@@ -7317,7 +7230,6 @@ pub const FuncGen = struct {
7317 }7230 }
73187231
7319 fn airMod(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {7232 fn airMod(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
7320 if (self.liveness.isUnused(inst)) return null;
7321 self.builder.setFastMath(want_fast_math);7233 self.builder.setFastMath(want_fast_math);
73227234
7323 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7235 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -7347,8 +7259,6 @@ pub const FuncGen = struct {...@@ -7347,8 +7259,6 @@ pub const FuncGen = struct {
7347 }7259 }
73487260
7349 fn airPtrAdd(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7261 fn airPtrAdd(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7350 if (self.liveness.isUnused(inst)) return null;
7351
7352 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;7262 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
7353 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;7263 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
7354 const base_ptr = try self.resolveInst(bin_op.lhs);7264 const base_ptr = try self.resolveInst(bin_op.lhs);
...@@ -7368,8 +7278,6 @@ pub const FuncGen = struct {...@@ -7368,8 +7278,6 @@ pub const FuncGen = struct {
7368 }7278 }
73697279
7370 fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7280 fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7371 if (self.liveness.isUnused(inst)) return null;
7372
7373 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;7281 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
7374 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;7282 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
7375 const base_ptr = try self.resolveInst(bin_op.lhs);7283 const base_ptr = try self.resolveInst(bin_op.lhs);
...@@ -7395,9 +7303,6 @@ pub const FuncGen = struct {...@@ -7395,9 +7303,6 @@ pub const FuncGen = struct {
7395 signed_intrinsic: []const u8,7303 signed_intrinsic: []const u8,
7396 unsigned_intrinsic: []const u8,7304 unsigned_intrinsic: []const u8,
7397 ) !?*llvm.Value {7305 ) !?*llvm.Value {
7398 if (self.liveness.isUnused(inst))
7399 return null;
7400
7401 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;7306 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
7402 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;7307 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
74037308
...@@ -7686,8 +7591,6 @@ pub const FuncGen = struct {...@@ -7686,8 +7591,6 @@ pub const FuncGen = struct {
7686 }7591 }
76877592
7688 fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7593 fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7689 if (self.liveness.isUnused(inst)) return null;
7690
7691 const pl_op = self.air.instructions.items(.data)[inst].pl_op;7594 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
7692 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;7595 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;
76937596
...@@ -7700,9 +7603,6 @@ pub const FuncGen = struct {...@@ -7700,9 +7603,6 @@ pub const FuncGen = struct {
7700 }7603 }
77017604
7702 fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7605 fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7703 if (self.liveness.isUnused(inst))
7704 return null;
7705
7706 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;7606 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
7707 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;7607 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
77087608
...@@ -7759,8 +7659,6 @@ pub const FuncGen = struct {...@@ -7759,8 +7659,6 @@ pub const FuncGen = struct {
7759 }7659 }
77607660
7761 fn airAnd(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7661 fn airAnd(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7762 if (self.liveness.isUnused(inst))
7763 return null;
7764 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7662 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7765 const lhs = try self.resolveInst(bin_op.lhs);7663 const lhs = try self.resolveInst(bin_op.lhs);
7766 const rhs = try self.resolveInst(bin_op.rhs);7664 const rhs = try self.resolveInst(bin_op.rhs);
...@@ -7768,8 +7666,6 @@ pub const FuncGen = struct {...@@ -7768,8 +7666,6 @@ pub const FuncGen = struct {
7768 }7666 }
77697667
7770 fn airOr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7668 fn airOr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7771 if (self.liveness.isUnused(inst))
7772 return null;
7773 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7669 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7774 const lhs = try self.resolveInst(bin_op.lhs);7670 const lhs = try self.resolveInst(bin_op.lhs);
7775 const rhs = try self.resolveInst(bin_op.rhs);7671 const rhs = try self.resolveInst(bin_op.rhs);
...@@ -7777,8 +7673,6 @@ pub const FuncGen = struct {...@@ -7777,8 +7673,6 @@ pub const FuncGen = struct {
7777 }7673 }
77787674
7779 fn airXor(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7675 fn airXor(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7780 if (self.liveness.isUnused(inst))
7781 return null;
7782 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7676 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
7783 const lhs = try self.resolveInst(bin_op.lhs);7677 const lhs = try self.resolveInst(bin_op.lhs);
7784 const rhs = try self.resolveInst(bin_op.rhs);7678 const rhs = try self.resolveInst(bin_op.rhs);
...@@ -7786,8 +7680,6 @@ pub const FuncGen = struct {...@@ -7786,8 +7680,6 @@ pub const FuncGen = struct {
7786 }7680 }
77877681
7788 fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7682 fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7789 if (self.liveness.isUnused(inst)) return null;
7790
7791 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7683 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
77927684
7793 const lhs = try self.resolveInst(bin_op.lhs);7685 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -7809,8 +7701,6 @@ pub const FuncGen = struct {...@@ -7809,8 +7701,6 @@ pub const FuncGen = struct {
7809 }7701 }
78107702
7811 fn airShl(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7703 fn airShl(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7812 if (self.liveness.isUnused(inst)) return null;
7813
7814 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7704 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
78157705
7816 const lhs = try self.resolveInst(bin_op.lhs);7706 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -7831,8 +7721,6 @@ pub const FuncGen = struct {...@@ -7831,8 +7721,6 @@ pub const FuncGen = struct {
7831 }7721 }
78327722
7833 fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7723 fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7834 if (self.liveness.isUnused(inst)) return null;
7835
7836 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7724 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
78377725
7838 const lhs = try self.resolveInst(bin_op.lhs);7726 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -7876,8 +7764,6 @@ pub const FuncGen = struct {...@@ -7876,8 +7764,6 @@ pub const FuncGen = struct {
7876 }7764 }
78777765
7878 fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !?*llvm.Value {7766 fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !?*llvm.Value {
7879 if (self.liveness.isUnused(inst)) return null;
7880
7881 const bin_op = self.air.instructions.items(.data)[inst].bin_op;7767 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
78827768
7883 const lhs = try self.resolveInst(bin_op.lhs);7769 const lhs = try self.resolveInst(bin_op.lhs);
...@@ -7912,9 +7798,6 @@ pub const FuncGen = struct {...@@ -7912,9 +7798,6 @@ pub const FuncGen = struct {
7912 }7798 }
79137799
7914 fn airIntCast(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7800 fn airIntCast(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7915 if (self.liveness.isUnused(inst))
7916 return null;
7917
7918 const target = self.dg.module.getTarget();7801 const target = self.dg.module.getTarget();
7919 const ty_op = self.air.instructions.items(.data)[inst].ty_op;7802 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
7920 const dest_ty = self.air.typeOfIndex(inst);7803 const dest_ty = self.air.typeOfIndex(inst);
...@@ -7937,8 +7820,6 @@ pub const FuncGen = struct {...@@ -7937,8 +7820,6 @@ pub const FuncGen = struct {
7937 }7820 }
79387821
7939 fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7822 fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7940 if (self.liveness.isUnused(inst)) return null;
7941
7942 const ty_op = self.air.instructions.items(.data)[inst].ty_op;7823 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
7943 const operand = try self.resolveInst(ty_op.operand);7824 const operand = try self.resolveInst(ty_op.operand);
7944 const dest_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst));7825 const dest_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst));
...@@ -7946,9 +7827,6 @@ pub const FuncGen = struct {...@@ -7946,9 +7827,6 @@ pub const FuncGen = struct {
7946 }7827 }
79477828
7948 fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7829 fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7949 if (self.liveness.isUnused(inst))
7950 return null;
7951
7952 const ty_op = self.air.instructions.items(.data)[inst].ty_op;7830 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
7953 const operand = try self.resolveInst(ty_op.operand);7831 const operand = try self.resolveInst(ty_op.operand);
7954 const operand_ty = self.air.typeOf(ty_op.operand);7832 const operand_ty = self.air.typeOf(ty_op.operand);
...@@ -7978,9 +7856,6 @@ pub const FuncGen = struct {...@@ -7978,9 +7856,6 @@ pub const FuncGen = struct {
7978 }7856 }
79797857
7980 fn airFpext(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7858 fn airFpext(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7981 if (self.liveness.isUnused(inst))
7982 return null;
7983
7984 const ty_op = self.air.instructions.items(.data)[inst].ty_op;7859 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
7985 const operand = try self.resolveInst(ty_op.operand);7860 const operand = try self.resolveInst(ty_op.operand);
7986 const operand_ty = self.air.typeOf(ty_op.operand);7861 const operand_ty = self.air.typeOf(ty_op.operand);
...@@ -8010,9 +7885,6 @@ pub const FuncGen = struct {...@@ -8010,9 +7885,6 @@ pub const FuncGen = struct {
8010 }7885 }
80117886
8012 fn airPtrToInt(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7887 fn airPtrToInt(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8013 if (self.liveness.isUnused(inst))
8014 return null;
8015
8016 const un_op = self.air.instructions.items(.data)[inst].un_op;7888 const un_op = self.air.instructions.items(.data)[inst].un_op;
8017 const operand = try self.resolveInst(un_op);7889 const operand = try self.resolveInst(un_op);
8018 const dest_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst));7890 const dest_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst));
...@@ -8020,8 +7892,6 @@ pub const FuncGen = struct {...@@ -8020,8 +7892,6 @@ pub const FuncGen = struct {
8020 }7892 }
80217893
8022 fn airBitCast(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {7894 fn airBitCast(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8023 if (self.liveness.isUnused(inst)) return null;
8024
8025 const ty_op = self.air.instructions.items(.data)[inst].ty_op;7895 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
8026 const operand_ty = self.air.typeOf(ty_op.operand);7896 const operand_ty = self.air.typeOf(ty_op.operand);
8027 const inst_ty = self.air.typeOfIndex(inst);7897 const inst_ty = self.air.typeOfIndex(inst);
...@@ -8137,9 +8007,6 @@ pub const FuncGen = struct {...@@ -8137,9 +8007,6 @@ pub const FuncGen = struct {
8137 }8007 }
81388008
8139 fn airBoolToInt(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8009 fn airBoolToInt(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8140 if (self.liveness.isUnused(inst))
8141 return null;
8142
8143 const un_op = self.air.instructions.items(.data)[inst].un_op;8010 const un_op = self.air.instructions.items(.data)[inst].un_op;
8144 const operand = try self.resolveInst(un_op);8011 const operand = try self.resolveInst(un_op);
8145 return operand;8012 return operand;
...@@ -8189,7 +8056,6 @@ pub const FuncGen = struct {...@@ -8189,7 +8056,6 @@ pub const FuncGen = struct {
8189 }8056 }
81908057
8191 fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8058 fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8192 if (self.liveness.isUnused(inst)) return null;
8193 const ptr_ty = self.air.typeOfIndex(inst);8059 const ptr_ty = self.air.typeOfIndex(inst);
8194 const pointee_type = ptr_ty.childType();8060 const pointee_type = ptr_ty.childType();
8195 if (!pointee_type.isFnOrHasRuntimeBitsIgnoreComptime()) return self.dg.lowerPtrToVoid(ptr_ty);8061 if (!pointee_type.isFnOrHasRuntimeBitsIgnoreComptime()) return self.dg.lowerPtrToVoid(ptr_ty);
...@@ -8201,7 +8067,6 @@ pub const FuncGen = struct {...@@ -8201,7 +8067,6 @@ pub const FuncGen = struct {
8201 }8067 }
82028068
8203 fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8069 fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8204 if (self.liveness.isUnused(inst)) return null;
8205 const ptr_ty = self.air.typeOfIndex(inst);8070 const ptr_ty = self.air.typeOfIndex(inst);
8206 const ret_ty = ptr_ty.childType();8071 const ret_ty = ptr_ty.childType();
8207 if (!ret_ty.isFnOrHasRuntimeBitsIgnoreComptime()) return self.dg.lowerPtrToVoid(ptr_ty);8072 if (!ret_ty.isFnOrHasRuntimeBitsIgnoreComptime()) return self.dg.lowerPtrToVoid(ptr_ty);
...@@ -8289,8 +8154,6 @@ pub const FuncGen = struct {...@@ -8289,8 +8154,6 @@ pub const FuncGen = struct {
8289 const ptr = try fg.resolveInst(ty_op.operand);8154 const ptr = try fg.resolveInst(ty_op.operand);
82908155
8291 elide: {8156 elide: {
8292 if (ptr_info.@"volatile") break :elide;
8293 if (fg.liveness.isUnused(inst)) return null;
8294 if (!isByRef(ptr_info.pointee_type)) break :elide;8157 if (!isByRef(ptr_info.pointee_type)) break :elide;
8295 if (!canElideLoad(fg, body_tail)) break :elide;8158 if (!canElideLoad(fg, body_tail)) break :elide;
8296 return ptr;8159 return ptr;
...@@ -8314,8 +8177,7 @@ pub const FuncGen = struct {...@@ -8314,8 +8177,7 @@ pub const FuncGen = struct {
8314 }8177 }
83158178
8316 fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8179 fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8317 if (self.liveness.isUnused(inst)) return null;8180 _ = inst;
8318
8319 const llvm_usize = try self.dg.lowerType(Type.usize);8181 const llvm_usize = try self.dg.lowerType(Type.usize);
8320 const target = self.dg.module.getTarget();8182 const target = self.dg.module.getTarget();
8321 if (!target_util.supportsReturnAddress(target)) {8183 if (!target_util.supportsReturnAddress(target)) {
...@@ -8331,8 +8193,7 @@ pub const FuncGen = struct {...@@ -8331,8 +8193,7 @@ pub const FuncGen = struct {
8331 }8193 }
83328194
8333 fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8195 fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8334 if (self.liveness.isUnused(inst)) return null;8196 _ = inst;
8335
8336 const llvm_i32 = self.context.intType(32);8197 const llvm_i32 = self.context.intType(32);
8337 const llvm_fn_name = "llvm.frameaddress.p0";8198 const llvm_fn_name = "llvm.frameaddress.p0";
8338 const llvm_fn = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: {8199 const llvm_fn = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: {
...@@ -8462,8 +8323,6 @@ pub const FuncGen = struct {...@@ -8462,8 +8323,6 @@ pub const FuncGen = struct {
8462 const ptr = try self.resolveInst(atomic_load.ptr);8323 const ptr = try self.resolveInst(atomic_load.ptr);
8463 const ptr_ty = self.air.typeOf(atomic_load.ptr);8324 const ptr_ty = self.air.typeOf(atomic_load.ptr);
8464 const ptr_info = ptr_ty.ptrInfo().data;8325 const ptr_info = ptr_ty.ptrInfo().data;
8465 if (!ptr_info.@"volatile" and self.liveness.isUnused(inst))
8466 return null;
8467 const elem_ty = ptr_info.pointee_type;8326 const elem_ty = ptr_info.pointee_type;
8468 if (!elem_ty.hasRuntimeBitsIgnoreComptime())8327 if (!elem_ty.hasRuntimeBitsIgnoreComptime())
8469 return null;8328 return null;
...@@ -8577,8 +8436,6 @@ pub const FuncGen = struct {...@@ -8577,8 +8436,6 @@ pub const FuncGen = struct {
8577 }8436 }
85788437
8579 fn airGetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8438 fn airGetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8580 if (self.liveness.isUnused(inst)) return null;
8581
8582 const ty_op = self.air.instructions.items(.data)[inst].ty_op;8439 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
8583 const un_ty = self.air.typeOf(ty_op.operand);8440 const un_ty = self.air.typeOf(ty_op.operand);
8584 const target = self.dg.module.getTarget();8441 const target = self.dg.module.getTarget();
...@@ -8603,8 +8460,6 @@ pub const FuncGen = struct {...@@ -8603,8 +8460,6 @@ pub const FuncGen = struct {
8603 }8460 }
86048461
8605 fn airUnaryOp(self: *FuncGen, inst: Air.Inst.Index, comptime op: FloatOp) !?*llvm.Value {8462 fn airUnaryOp(self: *FuncGen, inst: Air.Inst.Index, comptime op: FloatOp) !?*llvm.Value {
8606 if (self.liveness.isUnused(inst)) return null;
8607
8608 const un_op = self.air.instructions.items(.data)[inst].un_op;8463 const un_op = self.air.instructions.items(.data)[inst].un_op;
8609 const operand = try self.resolveInst(un_op);8464 const operand = try self.resolveInst(un_op);
8610 const operand_ty = self.air.typeOf(un_op);8465 const operand_ty = self.air.typeOf(un_op);
...@@ -8613,7 +8468,6 @@ pub const FuncGen = struct {...@@ -8613,7 +8468,6 @@ pub const FuncGen = struct {
8613 }8468 }
86148469
8615 fn airNeg(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {8470 fn airNeg(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
8616 if (self.liveness.isUnused(inst)) return null;
8617 self.builder.setFastMath(want_fast_math);8471 self.builder.setFastMath(want_fast_math);
86188472
8619 const un_op = self.air.instructions.items(.data)[inst].un_op;8473 const un_op = self.air.instructions.items(.data)[inst].un_op;
...@@ -8624,8 +8478,6 @@ pub const FuncGen = struct {...@@ -8624,8 +8478,6 @@ pub const FuncGen = struct {
8624 }8478 }
86258479
8626 fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value {8480 fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value {
8627 if (self.liveness.isUnused(inst)) return null;
8628
8629 const ty_op = self.air.instructions.items(.data)[inst].ty_op;8481 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
8630 const operand_ty = self.air.typeOf(ty_op.operand);8482 const operand_ty = self.air.typeOf(ty_op.operand);
8631 const operand = try self.resolveInst(ty_op.operand);8483 const operand = try self.resolveInst(ty_op.operand);
...@@ -8652,8 +8504,6 @@ pub const FuncGen = struct {...@@ -8652,8 +8504,6 @@ pub const FuncGen = struct {
8652 }8504 }
86538505
8654 fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value {8506 fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value {
8655 if (self.liveness.isUnused(inst)) return null;
8656
8657 const ty_op = self.air.instructions.items(.data)[inst].ty_op;8507 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
8658 const operand_ty = self.air.typeOf(ty_op.operand);8508 const operand_ty = self.air.typeOf(ty_op.operand);
8659 const operand = try self.resolveInst(ty_op.operand);8509 const operand = try self.resolveInst(ty_op.operand);
...@@ -8679,8 +8529,6 @@ pub const FuncGen = struct {...@@ -8679,8 +8529,6 @@ pub const FuncGen = struct {
8679 }8529 }
86808530
8681 fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value {8531 fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value {
8682 if (self.liveness.isUnused(inst)) return null;
8683
8684 const target = self.dg.module.getTarget();8532 const target = self.dg.module.getTarget();
8685 const ty_op = self.air.instructions.items(.data)[inst].ty_op;8533 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
8686 const operand_ty = self.air.typeOf(ty_op.operand);8534 const operand_ty = self.air.typeOf(ty_op.operand);
...@@ -8734,8 +8582,6 @@ pub const FuncGen = struct {...@@ -8734,8 +8582,6 @@ pub const FuncGen = struct {
8734 }8582 }
87358583
8736 fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8584 fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8737 if (self.liveness.isUnused(inst)) return null;
8738
8739 const ty_op = self.air.instructions.items(.data)[inst].ty_op;8585 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
8740 const operand = try self.resolveInst(ty_op.operand);8586 const operand = try self.resolveInst(ty_op.operand);
8741 const error_set_ty = self.air.getRefType(ty_op.ty);8587 const error_set_ty = self.air.getRefType(ty_op.ty);
...@@ -8781,8 +8627,6 @@ pub const FuncGen = struct {...@@ -8781,8 +8627,6 @@ pub const FuncGen = struct {
8781 }8627 }
87828628
8783 fn airIsNamedEnumValue(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8629 fn airIsNamedEnumValue(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8784 if (self.liveness.isUnused(inst)) return null;
8785
8786 const un_op = self.air.instructions.items(.data)[inst].un_op;8630 const un_op = self.air.instructions.items(.data)[inst].un_op;
8787 const operand = try self.resolveInst(un_op);8631 const operand = try self.resolveInst(un_op);
8788 const enum_ty = self.air.typeOf(un_op);8632 const enum_ty = self.air.typeOf(un_op);
...@@ -8862,8 +8706,6 @@ pub const FuncGen = struct {...@@ -8862,8 +8706,6 @@ pub const FuncGen = struct {
8862 }8706 }
88638707
8864 fn airTagName(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8708 fn airTagName(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8865 if (self.liveness.isUnused(inst)) return null;
8866
8867 const un_op = self.air.instructions.items(.data)[inst].un_op;8709 const un_op = self.air.instructions.items(.data)[inst].un_op;
8868 const operand = try self.resolveInst(un_op);8710 const operand = try self.resolveInst(un_op);
8869 const enum_ty = self.air.typeOf(un_op);8711 const enum_ty = self.air.typeOf(un_op);
...@@ -8995,8 +8837,6 @@ pub const FuncGen = struct {...@@ -8995,8 +8837,6 @@ pub const FuncGen = struct {
8995 }8837 }
89968838
8997 fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8839 fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8998 if (self.liveness.isUnused(inst)) return null;
8999
9000 const un_op = self.air.instructions.items(.data)[inst].un_op;8840 const un_op = self.air.instructions.items(.data)[inst].un_op;
9001 const operand = try self.resolveInst(un_op);8841 const operand = try self.resolveInst(un_op);
9002 const slice_ty = self.air.typeOfIndex(inst);8842 const slice_ty = self.air.typeOfIndex(inst);
...@@ -9011,8 +8851,6 @@ pub const FuncGen = struct {...@@ -9011,8 +8851,6 @@ pub const FuncGen = struct {
9011 }8851 }
90128852
9013 fn airSplat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8853 fn airSplat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
9014 if (self.liveness.isUnused(inst)) return null;
9015
9016 const ty_op = self.air.instructions.items(.data)[inst].ty_op;8854 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
9017 const scalar = try self.resolveInst(ty_op.operand);8855 const scalar = try self.resolveInst(ty_op.operand);
9018 const vector_ty = self.air.typeOfIndex(inst);8856 const vector_ty = self.air.typeOfIndex(inst);
...@@ -9021,8 +8859,6 @@ pub const FuncGen = struct {...@@ -9021,8 +8859,6 @@ pub const FuncGen = struct {
9021 }8859 }
90228860
9023 fn airSelect(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8861 fn airSelect(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
9024 if (self.liveness.isUnused(inst)) return null;
9025
9026 const pl_op = self.air.instructions.items(.data)[inst].pl_op;8862 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
9027 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;8863 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;
9028 const pred = try self.resolveInst(pl_op.operand);8864 const pred = try self.resolveInst(pl_op.operand);
...@@ -9033,8 +8869,6 @@ pub const FuncGen = struct {...@@ -9033,8 +8869,6 @@ pub const FuncGen = struct {
9033 }8869 }
90348870
9035 fn airShuffle(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {8871 fn airShuffle(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
9036 if (self.liveness.isUnused(inst)) return null;
9037
9038 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;8872 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
9039 const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data;8873 const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data;
9040 const a = try self.resolveInst(extra.a);8874 const a = try self.resolveInst(extra.a);
...@@ -9134,7 +8968,6 @@ pub const FuncGen = struct {...@@ -9134,7 +8968,6 @@ pub const FuncGen = struct {
9134 }8968 }
91358969
9136 fn airReduce(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {8970 fn airReduce(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
9137 if (self.liveness.isUnused(inst)) return null;
9138 self.builder.setFastMath(want_fast_math);8971 self.builder.setFastMath(want_fast_math);
9139 const target = self.dg.module.getTarget();8972 const target = self.dg.module.getTarget();
91408973
...@@ -9221,8 +9054,6 @@ pub const FuncGen = struct {...@@ -9221,8 +9054,6 @@ pub const FuncGen = struct {
9221 }9054 }
92229055
9223 fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {9056 fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
9224 if (self.liveness.isUnused(inst)) return null;
9225
9226 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;9057 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
9227 const result_ty = self.air.typeOfIndex(inst);9058 const result_ty = self.air.typeOfIndex(inst);
9228 const len = @intCast(usize, result_ty.arrayLen());9059 const len = @intCast(usize, result_ty.arrayLen());
...@@ -9360,8 +9191,6 @@ pub const FuncGen = struct {...@@ -9360,8 +9191,6 @@ pub const FuncGen = struct {
9360 }9191 }
93619192
9362 fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {9193 fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
9363 if (self.liveness.isUnused(inst)) return null;
9364
9365 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;9194 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
9366 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;9195 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
9367 const union_ty = self.air.typeOfIndex(inst);9196 const union_ty = self.air.typeOfIndex(inst);
...@@ -9566,8 +9395,6 @@ pub const FuncGen = struct {...@@ -9566,8 +9395,6 @@ pub const FuncGen = struct {
9566 }9395 }
95679396
9568 fn airAddrSpaceCast(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {9397 fn airAddrSpaceCast(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
9569 if (self.liveness.isUnused(inst)) return null;
9570
9571 const ty_op = self.air.instructions.items(.data)[inst].ty_op;9398 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
9572 const inst_ty = self.air.typeOfIndex(inst);9399 const inst_ty = self.air.typeOfIndex(inst);
9573 const operand = try self.resolveInst(ty_op.operand);9400 const operand = try self.resolveInst(ty_op.operand);
...@@ -9592,8 +9419,6 @@ pub const FuncGen = struct {...@@ -9592,8 +9419,6 @@ pub const FuncGen = struct {
9592 }9419 }
95939420
9594 fn airWorkItemId(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {9421 fn airWorkItemId(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
9595 if (self.liveness.isUnused(inst)) return null;
9596
9597 const target = self.dg.module.getTarget();9422 const target = self.dg.module.getTarget();
9598 assert(target.cpu.arch == .amdgcn); // TODO is to port this function to other GPU architectures9423 assert(target.cpu.arch == .amdgcn); // TODO is to port this function to other GPU architectures
95999424
...@@ -9603,8 +9428,6 @@ pub const FuncGen = struct {...@@ -9603,8 +9428,6 @@ pub const FuncGen = struct {
9603 }9428 }
96049429
9605 fn airWorkGroupSize(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {9430 fn airWorkGroupSize(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
9606 if (self.liveness.isUnused(inst)) return null;
9607
9608 const target = self.dg.module.getTarget();9431 const target = self.dg.module.getTarget();
9609 assert(target.cpu.arch == .amdgcn); // TODO is to port this function to other GPU architectures9432 assert(target.cpu.arch == .amdgcn); // TODO is to port this function to other GPU architectures
96109433
...@@ -9634,8 +9457,6 @@ pub const FuncGen = struct {...@@ -9634,8 +9457,6 @@ pub const FuncGen = struct {
9634 }9457 }
96359458
9636 fn airWorkGroupId(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {9459 fn airWorkGroupId(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
9637 if (self.liveness.isUnused(inst)) return null;
9638
9639 const target = self.dg.module.getTarget();9460 const target = self.dg.module.getTarget();
9640 assert(target.cpu.arch == .amdgcn); // TODO is to port this function to other GPU architectures9461 assert(target.cpu.arch == .amdgcn); // TODO is to port this function to other GPU architectures
96419462
...@@ -9756,8 +9577,6 @@ pub const FuncGen = struct {...@@ -9756,8 +9577,6 @@ pub const FuncGen = struct {
9756 struct_ptr_ty: Type,9577 struct_ptr_ty: Type,
9757 field_index: u32,9578 field_index: u32,
9758 ) !?*llvm.Value {9579 ) !?*llvm.Value {
9759 if (self.liveness.isUnused(inst)) return null;
9760
9761 const target = self.dg.object.target;9580 const target = self.dg.object.target;
9762 const struct_ty = struct_ptr_ty.childType();9581 const struct_ty = struct_ptr_ty.childType();
9763 switch (struct_ty.zigTypeTag()) {9582 switch (struct_ty.zigTypeTag()) {
test/behavior/var_args.zig+16
...@@ -215,3 +215,19 @@ test "copy VaList" {...@@ -215,3 +215,19 @@ test "copy VaList" {
215 try std.testing.expectEqual(@as(c_int, 3), S.add(1, @as(c_int, 1)));215 try std.testing.expectEqual(@as(c_int, 3), S.add(1, @as(c_int, 1)));
216 try std.testing.expectEqual(@as(c_int, 9), S.add(2, @as(c_int, 1), @as(c_int, 2)));216 try std.testing.expectEqual(@as(c_int, 9), S.add(2, @as(c_int, 1), @as(c_int, 2)));
217}217}
218
219test "unused VaList arg" {
220 const S = struct {
221 fn thirdArg(dummy: c_int, ...) callconv(.C) c_int {
222 _ = dummy;
223
224 var ap = @cVaStart();
225 defer @cVaEnd(&ap);
226
227 _ = @cVaArg(&ap, c_int);
228 return @cVaArg(&ap, c_int);
229 }
230 };
231 const x = S.thirdArg(0, @as(c_int, 1), @as(c_int, 2));
232 try std.testing.expectEqual(@as(c_int, 2), x);
233}