authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-01-30 11:58:32-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-01-31 23:00:34-05:00
logafa74c6b213efb1ff85b86ce4a9edd5cc03e5a9b
tree6a4d326e31eda55c359ec1e2aef05681bbef0298
parent8195b64f575acaed9dbc59e745a98acebb71dc60

Sema: introduce all_vector_instructions backend feature

Sema is arbitrarily scalarizing some operations, which means that when I try to implement vectorized versions of those operations in a backend, they are impossible to test due to Sema not producing them. Now, I can implement them and then temporarily enable the new feature for that backend in order to test them. Once the backend supports all of them, the feature can be permanently enabled. This also deletes the Air instructions `int_from_bool` and `int_from_ptr`, which are just bitcasts with a fixed result type, since changing `un_op` to `ty_op` takes up the same amount of memory.

17 files changed, 102 insertions(+), 269 deletions(-)

src/Air.zig+2-14
...@@ -266,7 +266,8 @@ pub const Inst = struct {...@@ -266,7 +266,8 @@ pub const Inst = struct {
266 /// Boolean or binary NOT.266 /// Boolean or binary NOT.
267 /// Uses the `ty_op` field.267 /// Uses the `ty_op` field.
268 not,268 not,
269 /// Reinterpret the memory representation of a value as a different type.269 /// Reinterpret the bits of a value as a different type. This is like `@bitCast` but
270 /// also supports enums and pointers.
270 /// Uses the `ty_op` field.271 /// Uses the `ty_op` field.
271 bitcast,272 bitcast,
272 /// Uses the `ty_pl` field with payload `Block`. A block runs its body which always ends273 /// Uses the `ty_pl` field with payload `Block`. A block runs its body which always ends
...@@ -517,14 +518,6 @@ pub const Inst = struct {...@@ -517,14 +518,6 @@ pub const Inst = struct {
517 /// Read a value from a pointer.518 /// Read a value from a pointer.
518 /// Uses the `ty_op` field.519 /// Uses the `ty_op` field.
519 load,520 load,
520 /// Converts a pointer to its address. Result type is always `usize`.
521 /// Pointer type size may be any, including slice.
522 /// Uses the `un_op` field.
523 int_from_ptr,
524 /// Given a boolean, returns 0 or 1.
525 /// Result type is always `u1`.
526 /// Uses the `un_op` field.
527 int_from_bool,
528 /// Return a value from a function.521 /// Return a value from a function.
529 /// Result type is always noreturn; no instructions in a block follow this one.522 /// Result type is always noreturn; no instructions in a block follow this one.
530 /// Uses the `un_op` field.523 /// Uses the `un_op` field.
...@@ -1542,7 +1535,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)...@@ -1542,7 +1535,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
1542 .c_va_end,1535 .c_va_end,
1543 => return Type.void,1536 => return Type.void,
15441537
1545 .int_from_ptr,
1546 .slice_len,1538 .slice_len,
1547 .ret_addr,1539 .ret_addr,
1548 .frame_addr,1540 .frame_addr,
...@@ -1552,8 +1544,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)...@@ -1552,8 +1544,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
1552 .wasm_memory_grow => return Type.isize,1544 .wasm_memory_grow => return Type.isize,
1553 .wasm_memory_size => return Type.usize,1545 .wasm_memory_size => return Type.usize,
15541546
1555 .int_from_bool => return Type.u1,
1556
1557 .tag_name, .error_name => return Type.slice_const_u8_sentinel_0,1547 .tag_name, .error_name => return Type.slice_const_u8_sentinel_0,
15581548
1559 .call, .call_always_tail, .call_never_tail, .call_never_inline => {1549 .call, .call_always_tail, .call_never_tail, .call_never_inline => {
...@@ -1815,8 +1805,6 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {...@@ -1815,8 +1805,6 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
1815 .is_non_err_ptr,1805 .is_non_err_ptr,
1816 .bool_and,1806 .bool_and,
1817 .bool_or,1807 .bool_or,
1818 .int_from_ptr,
1819 .int_from_bool,
1820 .fptrunc,1808 .fptrunc,
1821 .fpext,1809 .fpext,
1822 .intcast,1810 .intcast,
src/Air/types_resolved.zig-2
...@@ -208,8 +208,6 @@ fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool {...@@ -208,8 +208,6 @@ fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool {
208 .is_non_err,208 .is_non_err,
209 .is_err_ptr,209 .is_err_ptr,
210 .is_non_err_ptr,210 .is_non_err_ptr,
211 .int_from_ptr,
212 .int_from_bool,
213 .ret,211 .ret,
214 .ret_safe,212 .ret_safe,
215 .ret_load,213 .ret_load,
src/Liveness.zig-4
...@@ -402,8 +402,6 @@ pub fn categorizeOperand(...@@ -402,8 +402,6 @@ pub fn categorizeOperand(
402 .is_non_err,402 .is_non_err,
403 .is_err_ptr,403 .is_err_ptr,
404 .is_non_err_ptr,404 .is_non_err_ptr,
405 .int_from_ptr,
406 .int_from_bool,
407 .is_named_enum_value,405 .is_named_enum_value,
408 .tag_name,406 .tag_name,
409 .error_name,407 .error_name,
...@@ -1028,8 +1026,6 @@ fn analyzeInst(...@@ -1028,8 +1026,6 @@ fn analyzeInst(
1028 .is_non_err,1026 .is_non_err,
1029 .is_err_ptr,1027 .is_err_ptr,
1030 .is_non_err_ptr,1028 .is_non_err_ptr,
1031 .int_from_ptr,
1032 .int_from_bool,
1033 .is_named_enum_value,1029 .is_named_enum_value,
1034 .tag_name,1030 .tag_name,
1035 .error_name,1031 .error_name,
src/Liveness/Verify.zig-2
...@@ -130,8 +130,6 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -130,8 +130,6 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
130 .is_non_err,130 .is_non_err,
131 .is_err_ptr,131 .is_err_ptr,
132 .is_non_err_ptr,132 .is_non_err_ptr,
133 .int_from_ptr,
134 .int_from_bool,
135 .is_named_enum_value,133 .is_named_enum_value,
136 .tag_name,134 .tag_name,
137 .error_name,135 .error_name,
src/Sema.zig+70-33
...@@ -10054,6 +10054,8 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -10054,6 +10054,8 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
10054 };10054 };
10055 return sema.failWithOwnedErrorMsg(block, msg);10055 return sema.failWithOwnedErrorMsg(block, msg);
10056 }10056 }
10057 const len = if (is_vector) operand_ty.vectorLen(zcu) else undefined;
10058 const dest_ty: Type = if (is_vector) try pt.vectorType(.{ .child = .usize_type, .len = len }) else .usize;
10057 if (try sema.resolveValueIntable(operand)) |operand_val| ct: {10059 if (try sema.resolveValueIntable(operand)) |operand_val| ct: {
10058 if (!is_vector) {10060 if (!is_vector) {
10059 if (operand_val.isUndef(zcu)) {10061 if (operand_val.isUndef(zcu)) {
...@@ -10064,8 +10066,6 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -10064,8 +10066,6 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
10064 (try operand_val.toUnsignedIntSema(pt)),10066 (try operand_val.toUnsignedIntSema(pt)),
10065 )).toIntern());10067 )).toIntern());
10066 }10068 }
10067 const len = operand_ty.vectorLen(zcu);
10068 const dest_ty = try pt.vectorType(.{ .child = .usize_type, .len = len });
10069 const new_elems = try sema.arena.alloc(InternPool.Index, len);10069 const new_elems = try sema.arena.alloc(InternPool.Index, len);
10070 for (new_elems, 0..) |*new_elem, i| {10070 for (new_elems, 0..) |*new_elem, i| {
10071 const ptr_val = try operand_val.elemValue(pt, i);10071 const ptr_val = try operand_val.elemValue(pt, i);
...@@ -10089,16 +10089,14 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -10089,16 +10089,14 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
10089 }10089 }
10090 try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), ptr_src);10090 try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), ptr_src);
10091 try sema.validateRuntimeValue(block, ptr_src, operand);10091 try sema.validateRuntimeValue(block, ptr_src, operand);
10092 if (!is_vector) {10092 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {
10093 return block.addUnOp(.int_from_ptr, operand);10093 return block.addBitCast(dest_ty, operand);
10094 }10094 }
10095 const len = operand_ty.vectorLen(zcu);
10096 const dest_ty = try pt.vectorType(.{ .child = .usize_type, .len = len });
10097 const new_elems = try sema.arena.alloc(Air.Inst.Ref, len);10095 const new_elems = try sema.arena.alloc(Air.Inst.Ref, len);
10098 for (new_elems, 0..) |*new_elem, i| {10096 for (new_elems, 0..) |*new_elem, i| {
10099 const idx_ref = try pt.intRef(Type.usize, i);10097 const idx_ref = try pt.intRef(Type.usize, i);
10100 const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref);10098 const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref);
10101 new_elem.* = try block.addUnOp(.int_from_ptr, old_elem);10099 new_elem.* = try block.addBitCast(.usize, old_elem);
10102 }10100 }
10103 return block.addAggregateInit(dest_ty, new_elems);10101 return block.addAggregateInit(dest_ty, new_elems);
10104}10102}
...@@ -10585,7 +10583,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -10585,7 +10583,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
10585 if (dst_bits >= src_bits) {10583 if (dst_bits >= src_bits) {
10586 return sema.coerce(block, dest_ty, operand, operand_src);10584 return sema.coerce(block, dest_ty, operand, operand_src);
10587 }10585 }
10588 if (!is_vector) {10586 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {
10589 return block.addTyOp(.fptrunc, dest_ty, operand);10587 return block.addTyOp(.fptrunc, dest_ty, operand);
10590 }10588 }
10591 const vec_len = operand_ty.vectorLen(zcu);10589 const vec_len = operand_ty.vectorLen(zcu);
...@@ -14762,7 +14760,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -14762,7 +14760,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
14762 });14760 });
1476314761
14764 const many_ty = slice_ty.slicePtrFieldType(zcu);14762 const many_ty = slice_ty.slicePtrFieldType(zcu);
14765 const many_alloc = try block.addTyOp(.bitcast, many_ty, mutable_alloc);14763 const many_alloc = try block.addBitCast(many_ty, mutable_alloc);
1476614764
14767 // lhs_dest_slice = dest[0..lhs.len]14765 // lhs_dest_slice = dest[0..lhs.len]
14768 const slice_ty_ref = Air.internedToRef(slice_ty.toIntern());14766 const slice_ty_ref = Air.internedToRef(slice_ty.toIntern());
...@@ -14812,7 +14810,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -14812,7 +14810,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
14812 try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store);14810 try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store);
14813 }14811 }
1481414812
14815 return block.addTyOp(.bitcast, constant_alloc_ty, mutable_alloc);14813 return block.addBitCast(constant_alloc_ty, mutable_alloc);
14816 }14814 }
1481714815
14818 var elem_i: u32 = 0;14816 var elem_i: u32 = 0;
...@@ -14845,7 +14843,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -14845,7 +14843,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
14845 try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store);14843 try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store);
14846 }14844 }
1484714845
14848 return block.addTyOp(.bitcast, constant_alloc_ty, mutable_alloc);14846 return block.addBitCast(constant_alloc_ty, mutable_alloc);
14849 }14847 }
1485014848
14851 const element_refs = try sema.arena.alloc(Air.Inst.Ref, result_len);14849 const element_refs = try sema.arena.alloc(Air.Inst.Ref, result_len);
...@@ -16612,8 +16610,8 @@ fn analyzeArithmetic(...@@ -16612,8 +16610,8 @@ fn analyzeArithmetic(
16612 };16610 };
1661316611
16614 try sema.requireRuntimeBlock(block, src, runtime_src);16612 try sema.requireRuntimeBlock(block, src, runtime_src);
16615 const lhs_int = try block.addUnOp(.int_from_ptr, lhs);16613 const lhs_int = try block.addBitCast(.usize, lhs);
16616 const rhs_int = try block.addUnOp(.int_from_ptr, rhs);16614 const rhs_int = try block.addBitCast(.usize, rhs);
16617 const address = try block.addBinOp(.sub_wrap, lhs_int, rhs_int);16615 const address = try block.addBinOp(.sub_wrap, lhs_int, rhs_int);
16618 return try block.addBinOp(.div_exact, address, try pt.intRef(Type.usize, elem_size));16616 return try block.addBinOp(.div_exact, address, try pt.intRef(Type.usize, elem_size));
16619 }16617 }
...@@ -21231,14 +21229,14 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -21231,14 +21229,14 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
21231 if (operand_scalar_ty.toIntern() != .bool_type) {21229 if (operand_scalar_ty.toIntern() != .bool_type) {
21232 return sema.fail(block, src, "expected 'bool', found '{}'", .{operand_scalar_ty.zigTypeTag(zcu)});21230 return sema.fail(block, src, "expected 'bool', found '{}'", .{operand_scalar_ty.zigTypeTag(zcu)});
21233 }21231 }
21232 const len = if (is_vector) operand_ty.vectorLen(zcu) else undefined;
21233 const dest_ty: Type = if (is_vector) try pt.vectorType(.{ .child = .u1_type, .len = len }) else .u1;
21234 if (try sema.resolveValue(operand)) |val| {21234 if (try sema.resolveValue(operand)) |val| {
21235 if (!is_vector) {21235 if (!is_vector) {
21236 if (val.isUndef(zcu)) return pt.undefRef(Type.u1);21236 if (val.isUndef(zcu)) return pt.undefRef(Type.u1);
21237 if (val.toBool()) return Air.internedToRef((try pt.intValue(Type.u1, 1)).toIntern());21237 if (val.toBool()) return Air.internedToRef((try pt.intValue(Type.u1, 1)).toIntern());
21238 return Air.internedToRef((try pt.intValue(Type.u1, 0)).toIntern());21238 return Air.internedToRef((try pt.intValue(Type.u1, 0)).toIntern());
21239 }21239 }
21240 const len = operand_ty.vectorLen(zcu);
21241 const dest_ty = try pt.vectorType(.{ .child = .u1_type, .len = len });
21242 if (val.isUndef(zcu)) return pt.undefRef(dest_ty);21240 if (val.isUndef(zcu)) return pt.undefRef(dest_ty);
21243 const new_elems = try sema.arena.alloc(InternPool.Index, len);21241 const new_elems = try sema.arena.alloc(InternPool.Index, len);
21244 for (new_elems, 0..) |*new_elem, i| {21242 for (new_elems, 0..) |*new_elem, i| {
...@@ -21256,16 +21254,14 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -21256,16 +21254,14 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
21256 .storage = .{ .elems = new_elems },21254 .storage = .{ .elems = new_elems },
21257 } }));21255 } }));
21258 }21256 }
21259 if (!is_vector) {21257 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {
21260 return block.addUnOp(.int_from_bool, operand);21258 return block.addBitCast(dest_ty, operand);
21261 }21259 }
21262 const len = operand_ty.vectorLen(zcu);
21263 const dest_ty = try pt.vectorType(.{ .child = .u1_type, .len = len });
21264 const new_elems = try sema.arena.alloc(Air.Inst.Ref, len);21260 const new_elems = try sema.arena.alloc(Air.Inst.Ref, len);
21265 for (new_elems, 0..) |*new_elem, i| {21261 for (new_elems, 0..) |*new_elem, i| {
21266 const idx_ref = try pt.intRef(Type.usize, i);21262 const idx_ref = try pt.intRef(Type.usize, i);
21267 const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref);21263 const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref);
21268 new_elem.* = try block.addUnOp(.int_from_bool, old_elem);21264 new_elem.* = try block.addBitCast(.u1, old_elem);
21269 }21265 }
21270 return block.addAggregateInit(dest_ty, new_elems);21266 return block.addAggregateInit(dest_ty, new_elems);
21271}21267}
...@@ -22858,14 +22854,27 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -22858,14 +22854,27 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
22858 .storage = .{ .repeated_elem = (try pt.intValue(dest_scalar_ty, 0)).toIntern() },22854 .storage = .{ .repeated_elem = (try pt.intValue(dest_scalar_ty, 0)).toIntern() },
22859 } }));22855 } }));
22860 }22856 }
22861 if (!is_vector) {22857 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {
22862 const result = try block.addTyOp(if (block.float_mode == .optimized) .int_from_float_optimized else .int_from_float, dest_ty, operand);22858 const result = try block.addTyOp(if (block.float_mode == .optimized) .int_from_float_optimized else .int_from_float, dest_ty, operand);
22863 if (block.wantSafety()) {22859 if (block.wantSafety()) {
22864 const back = try block.addTyOp(.float_from_int, operand_ty, result);22860 const back = try block.addTyOp(.float_from_int, operand_ty, result);
22865 const diff = try block.addBinOp(.sub, operand, back);22861 const diff = try block.addBinOp(if (block.float_mode == .optimized) .sub_optimized else .sub, operand, back);
22866 const ok_pos = try block.addBinOp(if (block.float_mode == .optimized) .cmp_lt_optimized else .cmp_lt, diff, Air.internedToRef((try pt.floatValue(operand_ty, 1.0)).toIntern()));22862 const ok = if (is_vector) ok: {
22867 const ok_neg = try block.addBinOp(if (block.float_mode == .optimized) .cmp_gt_optimized else .cmp_gt, diff, Air.internedToRef((try pt.floatValue(operand_ty, -1.0)).toIntern()));22863 const ok_pos = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, 1.0))).toIntern()), .lt);
22868 const ok = try block.addBinOp(.bool_and, ok_pos, ok_neg);22864 const ok_neg = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, -1.0))).toIntern()), .gt);
22865 const ok = try block.addBinOp(.bit_and, ok_pos, ok_neg);
22866 break :ok try block.addInst(.{
22867 .tag = .reduce,
22868 .data = .{ .reduce = .{
22869 .operand = ok,
22870 .operation = .And,
22871 } },
22872 });
22873 } else ok: {
22874 const ok_pos = try block.addBinOp(if (block.float_mode == .optimized) .cmp_lt_optimized else .cmp_lt, diff, Air.internedToRef((try pt.floatValue(operand_ty, 1.0)).toIntern()));
22875 const ok_neg = try block.addBinOp(if (block.float_mode == .optimized) .cmp_gt_optimized else .cmp_gt, diff, Air.internedToRef((try pt.floatValue(operand_ty, -1.0)).toIntern()));
22876 break :ok try block.addBinOp(.bool_and, ok_pos, ok_neg);
22877 };
22869 try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds);22878 try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds);
22870 }22879 }
22871 return result;22880 return result;
...@@ -22917,7 +22926,7 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -22917,7 +22926,7 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
22917 }22926 }
2291822927
22919 try sema.requireRuntimeBlock(block, src, operand_src);22928 try sema.requireRuntimeBlock(block, src, operand_src);
22920 if (!is_vector) {22929 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {
22921 return block.addTyOp(.float_from_int, dest_ty, operand);22930 return block.addTyOp(.float_from_int, dest_ty, operand);
22922 }22931 }
22923 const len = operand_ty.vectorLen(zcu);22932 const len = operand_ty.vectorLen(zcu);
...@@ -22996,17 +23005,37 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -22996,17 +23005,37 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
22996 });23005 });
22997 }23006 }
22998 try sema.requireRuntimeBlock(block, src, operand_src);23007 try sema.requireRuntimeBlock(block, src, operand_src);
22999 if (!is_vector) {23008 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {
23000 if (block.wantSafety() and (try elem_ty.hasRuntimeBitsSema(pt) or elem_ty.zigTypeTag(zcu) == .@"fn")) {23009 if (block.wantSafety() and (try elem_ty.hasRuntimeBitsSema(pt) or elem_ty.zigTypeTag(zcu) == .@"fn")) {
23001 if (!ptr_ty.isAllowzeroPtr(zcu)) {23010 if (!ptr_ty.isAllowzeroPtr(zcu)) {
23002 const is_non_zero = try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize);23011 const is_non_zero = if (is_vector) all_non_zero: {
23012 const zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern());
23013 const is_non_zero = try block.addCmpVector(operand_coerced, zero_usize, .neq);
23014 break :all_non_zero try block.addInst(.{
23015 .tag = .reduce,
23016 .data = .{ .reduce = .{
23017 .operand = is_non_zero,
23018 .operation = .And,
23019 } },
23020 });
23021 } else try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize);
23003 try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null);23022 try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null);
23004 }23023 }
23005 if (ptr_align.compare(.gt, .@"1")) {23024 if (ptr_align.compare(.gt, .@"1")) {
23006 const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1;23025 const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1;
23007 const align_minus_1 = Air.internedToRef((try pt.intValue(Type.usize, align_bytes_minus_1)).toIntern());23026 const align_minus_1 = Air.internedToRef((try sema.splat(operand_ty, try pt.intValue(Type.usize, align_bytes_minus_1))).toIntern());
23008 const remainder = try block.addBinOp(.bit_and, operand_coerced, align_minus_1);23027 const remainder = try block.addBinOp(.bit_and, operand_coerced, align_minus_1);
23009 const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize);23028 const is_aligned = if (is_vector) all_aligned: {
23029 const splat_zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern());
23030 const is_aligned = try block.addCmpVector(remainder, splat_zero_usize, .eq);
23031 break :all_aligned try block.addInst(.{
23032 .tag = .reduce,
23033 .data = .{ .reduce = .{
23034 .operand = is_aligned,
23035 .operation = .And,
23036 } },
23037 });
23038 } else try block.addBinOp(.cmp_eq, remainder, .zero_usize);
23010 try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment);23039 try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment);
23011 }23040 }
23012 }23041 }
...@@ -23559,7 +23588,11 @@ fn ptrCastFull(...@@ -23559,7 +23588,11 @@ fn ptrCastFull(
23559 if (block.wantSafety() and operand_ty.ptrAllowsZero(zcu) and !dest_ty.ptrAllowsZero(zcu) and23588 if (block.wantSafety() and operand_ty.ptrAllowsZero(zcu) and !dest_ty.ptrAllowsZero(zcu) and
23560 (try Type.fromInterned(dest_info.child).hasRuntimeBitsSema(pt) or Type.fromInterned(dest_info.child).zigTypeTag(zcu) == .@"fn"))23589 (try Type.fromInterned(dest_info.child).hasRuntimeBitsSema(pt) or Type.fromInterned(dest_info.child).zigTypeTag(zcu) == .@"fn"))
23561 {23590 {
23562 const ptr_int = try block.addUnOp(.int_from_ptr, ptr);23591 const actual_ptr = if (src_info.flags.size == .slice)
23592 try sema.analyzeSlicePtr(block, src, ptr, operand_ty)
23593 else
23594 ptr;
23595 const ptr_int = try block.addBitCast(.usize, actual_ptr);
23563 const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize);23596 const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize);
23564 const ok = if (src_info.flags.size == .slice and dest_info.flags.size == .slice) ok: {23597 const ok = if (src_info.flags.size == .slice and dest_info.flags.size == .slice) ok: {
23565 const len = try sema.analyzeSliceLen(block, operand_src, ptr);23598 const len = try sema.analyzeSliceLen(block, operand_src, ptr);
...@@ -23575,7 +23608,11 @@ fn ptrCastFull(...@@ -23575,7 +23608,11 @@ fn ptrCastFull(
23575 {23608 {
23576 const align_bytes_minus_1 = dest_align.toByteUnits().? - 1;23609 const align_bytes_minus_1 = dest_align.toByteUnits().? - 1;
23577 const align_minus_1 = Air.internedToRef((try pt.intValue(Type.usize, align_bytes_minus_1)).toIntern());23610 const align_minus_1 = Air.internedToRef((try pt.intValue(Type.usize, align_bytes_minus_1)).toIntern());
23578 const ptr_int = try block.addUnOp(.int_from_ptr, ptr);23611 const actual_ptr = if (src_info.flags.size == .slice)
23612 try sema.analyzeSlicePtr(block, src, ptr, operand_ty)
23613 else
23614 ptr;
23615 const ptr_int = try block.addBitCast(.usize, actual_ptr);
23579 const remainder = try block.addBinOp(.bit_and, ptr_int, align_minus_1);23616 const remainder = try block.addBinOp(.bit_and, ptr_int, align_minus_1);
23580 const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize);23617 const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize);
23581 const ok = if (src_info.flags.size == .slice and dest_info.flags.size == .slice) ok: {23618 const ok = if (src_info.flags.size == .slice and dest_info.flags.size == .slice) ok: {
...@@ -31403,7 +31440,7 @@ fn coerceCompatiblePtrs(...@@ -31403,7 +31440,7 @@ fn coerceCompatiblePtrs(
31403 try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty)31440 try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty)
31404 else31441 else
31405 inst;31442 inst;
31406 const ptr_int = try block.addUnOp(.int_from_ptr, actual_ptr);31443 const ptr_int = try block.addBitCast(.usize, actual_ptr);
31407 const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize);31444 const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize);
31408 const ok = if (inst_ty.isSlice(zcu)) ok: {31445 const ok = if (inst_ty.isSlice(zcu)) ok: {
31409 const len = try sema.analyzeSliceLen(block, inst_src, inst);31446 const len = try sema.analyzeSliceLen(block, inst_src, inst);
src/Zcu.zig+9
...@@ -3336,6 +3336,15 @@ pub const Feature = enum {...@@ -3336,6 +3336,15 @@ pub const Feature = enum {
3336 safety_checked_instructions,3336 safety_checked_instructions,
3337 /// If the backend supports running from another thread.3337 /// If the backend supports running from another thread.
3338 separate_thread,3338 separate_thread,
3339 /// If the backend supports the following AIR instructions with vector types:
3340 /// * `Air.Inst.Tag.bit_and`
3341 /// * `Air.Inst.Tag.bit_or`
3342 /// * `Air.Inst.Tag.bitcast`
3343 /// * `Air.Inst.Tag.float_from_int`
3344 /// * `Air.Inst.Tag.fptrunc`
3345 /// * `Air.Inst.Tag.int_from_float`
3346 /// If not supported, Sema will scalarize the operation.
3347 all_vector_instructions,
3339};3348};
33403349
3341pub fn backendSupportsFeature(zcu: *const Zcu, comptime feature: Feature) bool {3350pub fn backendSupportsFeature(zcu: *const Zcu, comptime feature: Feature) bool {
src/arch/aarch64/CodeGen.zig-15
...@@ -734,7 +734,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -734,7 +734,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
734 .fpext => try self.airFpext(inst),734 .fpext => try self.airFpext(inst),
735 .intcast => try self.airIntCast(inst),735 .intcast => try self.airIntCast(inst),
736 .trunc => try self.airTrunc(inst),736 .trunc => try self.airTrunc(inst),
737 .int_from_bool => try self.airIntFromBool(inst),
738 .is_non_null => try self.airIsNonNull(inst),737 .is_non_null => try self.airIsNonNull(inst),
739 .is_non_null_ptr => try self.airIsNonNullPtr(inst),738 .is_non_null_ptr => try self.airIsNonNullPtr(inst),
740 .is_null => try self.airIsNull(inst),739 .is_null => try self.airIsNull(inst),
...@@ -746,7 +745,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -746,7 +745,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
746 .load => try self.airLoad(inst),745 .load => try self.airLoad(inst),
747 .loop => try self.airLoop(inst),746 .loop => try self.airLoop(inst),
748 .not => try self.airNot(inst),747 .not => try self.airNot(inst),
749 .int_from_ptr => try self.airIntFromPtr(inst),
750 .ret => try self.airRet(inst),748 .ret => try self.airRet(inst),
751 .ret_safe => try self.airRet(inst), // TODO749 .ret_safe => try self.airRet(inst), // TODO
752 .ret_load => try self.airRetLoad(inst),750 .ret_load => try self.airRetLoad(inst),
...@@ -1294,13 +1292,6 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) InnerError!void {...@@ -1294,13 +1292,6 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) InnerError!void {
1294 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1292 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1295}1293}
12961294
1297fn airIntFromBool(self: *Self, inst: Air.Inst.Index) InnerError!void {
1298 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
1299 const operand = try self.resolveInst(un_op);
1300 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else operand;
1301 return self.finishAir(inst, result, .{ un_op, .none, .none });
1302}
1303
1304fn airNot(self: *Self, inst: Air.Inst.Index) InnerError!void {1295fn airNot(self: *Self, inst: Air.Inst.Index) InnerError!void {
1305 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;1296 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
1306 const pt = self.pt;1297 const pt = self.pt;
...@@ -5906,12 +5897,6 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -5906,12 +5897,6 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
5906 }5897 }
5907}5898}
59085899
5909fn airIntFromPtr(self: *Self, inst: Air.Inst.Index) InnerError!void {
5910 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
5911 const result = try self.resolveInst(un_op);
5912 return self.finishAir(inst, result, .{ un_op, .none, .none });
5913}
5914
5915fn airBitCast(self: *Self, inst: Air.Inst.Index) InnerError!void {5900fn airBitCast(self: *Self, inst: Air.Inst.Index) InnerError!void {
5916 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;5901 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
5917 const result = if (self.liveness.isUnused(inst)) .dead else result: {5902 const result = if (self.liveness.isUnused(inst)) .dead else result: {
src/arch/arm/CodeGen.zig-15
...@@ -723,7 +723,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -723,7 +723,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
723 .fpext => try self.airFpext(inst),723 .fpext => try self.airFpext(inst),
724 .intcast => try self.airIntCast(inst),724 .intcast => try self.airIntCast(inst),
725 .trunc => try self.airTrunc(inst),725 .trunc => try self.airTrunc(inst),
726 .int_from_bool => try self.airIntFromBool(inst),
727 .is_non_null => try self.airIsNonNull(inst),726 .is_non_null => try self.airIsNonNull(inst),
728 .is_non_null_ptr => try self.airIsNonNullPtr(inst),727 .is_non_null_ptr => try self.airIsNonNullPtr(inst),
729 .is_null => try self.airIsNull(inst),728 .is_null => try self.airIsNull(inst),
...@@ -735,7 +734,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -735,7 +734,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
735 .load => try self.airLoad(inst),734 .load => try self.airLoad(inst),
736 .loop => try self.airLoop(inst),735 .loop => try self.airLoop(inst),
737 .not => try self.airNot(inst),736 .not => try self.airNot(inst),
738 .int_from_ptr => try self.airIntFromPtr(inst),
739 .ret => try self.airRet(inst),737 .ret => try self.airRet(inst),
740 .ret_safe => try self.airRet(inst), // TODO738 .ret_safe => try self.airRet(inst), // TODO
741 .ret_load => try self.airRetLoad(inst),739 .ret_load => try self.airRetLoad(inst),
...@@ -1258,13 +1256,6 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {...@@ -1258,13 +1256,6 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
1258 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1256 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1259}1257}
12601258
1261fn airIntFromBool(self: *Self, inst: Air.Inst.Index) !void {
1262 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
1263 const operand = try self.resolveInst(un_op);
1264 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else operand;
1265 return self.finishAir(inst, result, .{ un_op, .none, .none });
1266}
1267
1268fn airNot(self: *Self, inst: Air.Inst.Index) !void {1259fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1269 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;1260 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
1270 const pt = self.pt;1261 const pt = self.pt;
...@@ -5874,12 +5865,6 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -5874,12 +5865,6 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
5874 }5865 }
5875}5866}
58765867
5877fn airIntFromPtr(self: *Self, inst: Air.Inst.Index) !void {
5878 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
5879 const result = try self.resolveInst(un_op);
5880 return self.finishAir(inst, result, .{ un_op, .none, .none });
5881}
5882
5883fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {5868fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
5884 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;5869 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
5885 const result = if (self.liveness.isUnused(inst)) .dead else result: {5870 const result = if (self.liveness.isUnused(inst)) .dead else result: {
src/arch/riscv64/CodeGen.zig+2-25
...@@ -1557,7 +1557,6 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1557,7 +1557,6 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1557 .fpext => try func.airFpext(inst),1557 .fpext => try func.airFpext(inst),
1558 .intcast => try func.airIntCast(inst),1558 .intcast => try func.airIntCast(inst),
1559 .trunc => try func.airTrunc(inst),1559 .trunc => try func.airTrunc(inst),
1560 .int_from_bool => try func.airIntFromBool(inst),
1561 .is_non_null => try func.airIsNonNull(inst),1560 .is_non_null => try func.airIsNonNull(inst),
1562 .is_non_null_ptr => try func.airIsNonNullPtr(inst),1561 .is_non_null_ptr => try func.airIsNonNullPtr(inst),
1563 .is_null => try func.airIsNull(inst),1562 .is_null => try func.airIsNull(inst),
...@@ -1569,7 +1568,6 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1569,7 +1568,6 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1569 .load => try func.airLoad(inst),1568 .load => try func.airLoad(inst),
1570 .loop => try func.airLoop(inst),1569 .loop => try func.airLoop(inst),
1571 .not => try func.airNot(inst),1570 .not => try func.airNot(inst),
1572 .int_from_ptr => try func.airIntFromPtr(inst),
1573 .ret => try func.airRet(inst, false),1571 .ret => try func.airRet(inst, false),
1574 .ret_safe => try func.airRet(inst, true),1572 .ret_safe => try func.airRet(inst, true),
1575 .ret_load => try func.airRetLoad(inst),1573 .ret_load => try func.airRetLoad(inst),
...@@ -2299,13 +2297,6 @@ fn airTrunc(func: *Func, inst: Air.Inst.Index) !void {...@@ -2299,13 +2297,6 @@ fn airTrunc(func: *Func, inst: Air.Inst.Index) !void {
2299 return func.finishAir(inst, operand, .{ ty_op.operand, .none, .none });2297 return func.finishAir(inst, operand, .{ ty_op.operand, .none, .none });
2300}2298}
23012299
2302fn airIntFromBool(func: *Func, inst: Air.Inst.Index) !void {
2303 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
2304 const operand = try func.resolveInst(un_op);
2305 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else operand;
2306 return func.finishAir(inst, result, .{ un_op, .none, .none });
2307}
2308
2309fn airNot(func: *Func, inst: Air.Inst.Index) !void {2300fn airNot(func: *Func, inst: Air.Inst.Index) !void {
2310 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;2301 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
2311 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {2302 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
...@@ -7262,21 +7253,6 @@ fn genSetMem(...@@ -7262,21 +7253,6 @@ fn genSetMem(
7262 }7253 }
7263}7254}
72647255
7265fn airIntFromPtr(func: *Func, inst: Air.Inst.Index) !void {
7266 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
7267 const result = result: {
7268 const src_mcv = try func.resolveInst(un_op);
7269 const src_ty = func.typeOfIndex(inst);
7270 if (func.reuseOperand(inst, un_op, 0, src_mcv)) break :result src_mcv;
7271
7272 const dst_mcv = try func.allocRegOrMem(src_ty, inst, true);
7273 const dst_ty = func.typeOfIndex(inst);
7274 try func.genCopy(dst_ty, dst_mcv, src_mcv);
7275 break :result dst_mcv;
7276 };
7277 return func.finishAir(inst, result, .{ un_op, .none, .none });
7278}
7279
7280fn airBitCast(func: *Func, inst: Air.Inst.Index) !void {7256fn airBitCast(func: *Func, inst: Air.Inst.Index) !void {
7281 const pt = func.pt;7257 const pt = func.pt;
7282 const zcu = pt.zcu;7258 const zcu = pt.zcu;
...@@ -7285,8 +7261,9 @@ fn airBitCast(func: *Func, inst: Air.Inst.Index) !void {...@@ -7285,8 +7261,9 @@ fn airBitCast(func: *Func, inst: Air.Inst.Index) !void {
7285 const result = if (func.liveness.isUnused(inst)) .unreach else result: {7261 const result = if (func.liveness.isUnused(inst)) .unreach else result: {
7286 const src_mcv = try func.resolveInst(ty_op.operand);7262 const src_mcv = try func.resolveInst(ty_op.operand);
72877263
7288 const dst_ty = func.typeOfIndex(inst);
7289 const src_ty = func.typeOf(ty_op.operand);7264 const src_ty = func.typeOf(ty_op.operand);
7265 if (src_ty.toIntern() == .bool_type) break :result src_mcv;
7266 const dst_ty = func.typeOfIndex(inst);
72907267
7291 const src_lock = if (src_mcv.getReg()) |reg| func.register_manager.lockReg(reg) else null;7268 const src_lock = if (src_mcv.getReg()) |reg| func.register_manager.lockReg(reg) else null;
7292 defer if (src_lock) |lock| func.register_manager.unlockReg(lock);7269 defer if (src_lock) |lock| func.register_manager.unlockReg(lock);
src/arch/sparc64/CodeGen.zig-15
...@@ -577,7 +577,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -577,7 +577,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
577 .fpext => @panic("TODO try self.airFpext(inst)"),577 .fpext => @panic("TODO try self.airFpext(inst)"),
578 .intcast => try self.airIntCast(inst),578 .intcast => try self.airIntCast(inst),
579 .trunc => try self.airTrunc(inst),579 .trunc => try self.airTrunc(inst),
580 .int_from_bool => try self.airIntFromBool(inst),
581 .is_non_null => try self.airIsNonNull(inst),580 .is_non_null => try self.airIsNonNull(inst),
582 .is_non_null_ptr => @panic("TODO try self.airIsNonNullPtr(inst)"),581 .is_non_null_ptr => @panic("TODO try self.airIsNonNullPtr(inst)"),
583 .is_null => try self.airIsNull(inst),582 .is_null => try self.airIsNull(inst),
...@@ -589,7 +588,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -589,7 +588,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
589 .load => try self.airLoad(inst),588 .load => try self.airLoad(inst),
590 .loop => try self.airLoop(inst),589 .loop => try self.airLoop(inst),
591 .not => try self.airNot(inst),590 .not => try self.airNot(inst),
592 .int_from_ptr => try self.airIntFromPtr(inst),
593 .ret => try self.airRet(inst),591 .ret => try self.airRet(inst),
594 .ret_safe => try self.airRet(inst), // TODO592 .ret_safe => try self.airRet(inst), // TODO
595 .ret_load => try self.airRetLoad(inst),593 .ret_load => try self.airRetLoad(inst),
...@@ -1077,13 +1075,6 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {...@@ -1077,13 +1075,6 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
1077 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1075 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1078}1076}
10791077
1080fn airIntFromBool(self: *Self, inst: Air.Inst.Index) !void {
1081 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
1082 const operand = try self.resolveInst(un_op);
1083 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else operand;
1084 return self.finishAir(inst, result, .{ un_op, .none, .none });
1085}
1086
1087fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {1078fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
1088 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;1079 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
1089 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;1080 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
...@@ -2230,12 +2221,6 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2230,12 +2221,6 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {
2230 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });2221 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2231}2222}
22322223
2233fn airIntFromPtr(self: *Self, inst: Air.Inst.Index) !void {
2234 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
2235 const result = try self.resolveInst(un_op);
2236 return self.finishAir(inst, result, .{ un_op, .none, .none });
2237}
2238
2239fn airRem(self: *Self, inst: Air.Inst.Index) !void {2224fn airRem(self: *Self, inst: Air.Inst.Index) !void {
2240 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2225 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2241 const lhs = try self.resolveInst(bin_op.lhs);2226 const lhs = try self.resolveInst(bin_op.lhs);
src/arch/wasm/CodeGen.zig+5-26
...@@ -1926,7 +1926,6 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -1926,7 +1926,6 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
1926 .br => cg.airBr(inst),1926 .br => cg.airBr(inst),
1927 .repeat => cg.airRepeat(inst),1927 .repeat => cg.airRepeat(inst),
1928 .switch_dispatch => return cg.fail("TODO implement `switch_dispatch`", .{}),1928 .switch_dispatch => return cg.fail("TODO implement `switch_dispatch`", .{}),
1929 .int_from_bool => cg.airIntFromBool(inst),
1930 .cond_br => cg.airCondBr(inst),1929 .cond_br => cg.airCondBr(inst),
1931 .intcast => cg.airIntcast(inst),1930 .intcast => cg.airIntcast(inst),
1932 .fptrunc => cg.airFptrunc(inst),1931 .fptrunc => cg.airFptrunc(inst),
...@@ -1972,7 +1971,6 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -1972,7 +1971,6 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
1972 .ptr_sub => cg.airPtrBinOp(inst, .sub),1971 .ptr_sub => cg.airPtrBinOp(inst, .sub),
1973 .ptr_elem_ptr => cg.airPtrElemPtr(inst),1972 .ptr_elem_ptr => cg.airPtrElemPtr(inst),
1974 .ptr_elem_val => cg.airPtrElemVal(inst),1973 .ptr_elem_val => cg.airPtrElemVal(inst),
1975 .int_from_ptr => cg.airIntFromPtr(inst),
1976 .ret => cg.airRet(inst),1974 .ret => cg.airRet(inst),
1977 .ret_safe => cg.airRet(inst), // TODO1975 .ret_safe => cg.airRet(inst), // TODO
1978 .ret_ptr => cg.airRetPtr(inst),1976 .ret_ptr => cg.airRetPtr(inst),
...@@ -3777,7 +3775,11 @@ fn airBitcast(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3777,7 +3775,11 @@ fn airBitcast(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3777 break :result try cg.wrapOperand(operand, wanted_ty);3775 break :result try cg.wrapOperand(operand, wanted_ty);
3778 }3776 }
37793777
3780 break :result cg.reuseOperand(ty_op.operand, operand);3778 break :result switch (operand) {
3779 // for stack offset, return a pointer to this offset.
3780 .stack_offset => try cg.buildPointerOffset(operand, 0, .new),
3781 else => cg.reuseOperand(ty_op.operand, operand),
3782 };
3781 };3783 };
3782 return cg.finishAir(inst, result, &.{ty_op.operand});3784 return cg.finishAir(inst, result, &.{ty_op.operand});
3783}3785}
...@@ -4637,14 +4639,6 @@ fn trunc(cg: *CodeGen, operand: WValue, wanted_ty: Type, given_ty: Type) InnerEr...@@ -4637,14 +4639,6 @@ fn trunc(cg: *CodeGen, operand: WValue, wanted_ty: Type, given_ty: Type) InnerEr
4637 return result;4639 return result;
4638}4640}
46394641
4640fn airIntFromBool(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4641 const un_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4642 const operand = try cg.resolveInst(un_op);
4643 const result = cg.reuseOperand(un_op, operand);
4644
4645 return cg.finishAir(inst, result, &.{un_op});
4646}
4647
4648fn airArrayToSlice(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {4642fn airArrayToSlice(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4649 const zcu = cg.pt.zcu;4643 const zcu = cg.pt.zcu;
4650 const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;4644 const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
...@@ -4668,21 +4662,6 @@ fn airArrayToSlice(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4668,21 +4662,6 @@ fn airArrayToSlice(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4668 return cg.finishAir(inst, slice_local, &.{ty_op.operand});4662 return cg.finishAir(inst, slice_local, &.{ty_op.operand});
4669}4663}
46704664
4671fn airIntFromPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4672 const zcu = cg.pt.zcu;
4673 const un_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4674 const operand = try cg.resolveInst(un_op);
4675 const ptr_ty = cg.typeOf(un_op);
4676 const result = if (ptr_ty.isSlice(zcu))
4677 try cg.slicePtr(operand)
4678 else switch (operand) {
4679 // for stack offset, return a pointer to this offset.
4680 .stack_offset => try cg.buildPointerOffset(operand, 0, .new),
4681 else => cg.reuseOperand(un_op, operand),
4682 };
4683 return cg.finishAir(inst, result, &.{un_op});
4684}
4685
4686fn airPtrElemVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {4665fn airPtrElemVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4687 const zcu = cg.pt.zcu;4666 const zcu = cg.pt.zcu;
4688 const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;4667 const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
src/arch/x86_64/CodeGen.zig-39
...@@ -21853,17 +21853,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -21853,17 +21853,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
21853 }, cg);21853 }, cg);
21854 try res.finish(inst, &.{ty_op.operand}, &ops, cg);21854 try res.finish(inst, &.{ty_op.operand}, &ops, cg);
21855 },21855 },
21856 .int_from_ptr => if (use_old) try cg.airIntFromPtr(inst) else {
21857 const un_op = air_datas[@intFromEnum(inst)].un_op;
21858 var ops = try cg.tempsFromOperands(inst, .{un_op});
21859 try ops[0].toSlicePtr(cg);
21860 try ops[0].finish(inst, &.{un_op}, &ops, cg);
21861 },
21862 .int_from_bool => if (use_old) try cg.airIntFromBool(inst) else {
21863 const un_op = air_datas[@intFromEnum(inst)].un_op;
21864 const ops = try cg.tempsFromOperands(inst, .{un_op});
21865 try ops[0].finish(inst, &.{un_op}, &ops, cg);
21866 },
21867 .ret => try cg.airRet(inst, false),21856 .ret => try cg.airRet(inst, false),
21868 .ret_safe => try cg.airRet(inst, true),21857 .ret_safe => try cg.airRet(inst, true),
21869 .ret_load => try cg.airRetLoad(inst),21858 .ret_load => try cg.airRetLoad(inst),
...@@ -24493,19 +24482,6 @@ fn airTrunc(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -24493,19 +24482,6 @@ fn airTrunc(self: *CodeGen, inst: Air.Inst.Index) !void {
24493 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });24482 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
24494}24483}
2449524484
24496fn airIntFromBool(self: *CodeGen, inst: Air.Inst.Index) !void {
24497 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
24498 const ty = self.typeOfIndex(inst);
24499
24500 const operand = try self.resolveInst(un_op);
24501 const dst_mcv = if (self.reuseOperand(inst, un_op, 0, operand))
24502 operand
24503 else
24504 try self.copyToRegisterWithInstTracking(inst, ty, operand);
24505
24506 return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none });
24507}
24508
24509fn airSlice(self: *CodeGen, inst: Air.Inst.Index) !void {24485fn airSlice(self: *CodeGen, inst: Air.Inst.Index) !void {
24510 const zcu = self.pt.zcu;24486 const zcu = self.pt.zcu;
24511 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;24487 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
...@@ -37205,21 +37181,6 @@ fn genLazySymbolRef(...@@ -37205,21 +37181,6 @@ fn genLazySymbolRef(
37205 }37181 }
37206}37182}
3720737183
37208fn airIntFromPtr(self: *CodeGen, inst: Air.Inst.Index) !void {
37209 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
37210 const result = result: {
37211 // TODO: handle case where the operand is a slice not a raw pointer
37212 const src_mcv = try self.resolveInst(un_op);
37213 if (self.reuseOperand(inst, un_op, 0, src_mcv)) break :result src_mcv;
37214
37215 const dst_mcv = try self.allocRegOrMem(inst, true);
37216 const dst_ty = self.typeOfIndex(inst);
37217 try self.genCopy(dst_ty, dst_mcv, src_mcv, .{});
37218 break :result dst_mcv;
37219 };
37220 return self.finishAir(inst, result, .{ un_op, .none, .none });
37221}
37222
37223fn airBitCast(self: *CodeGen, inst: Air.Inst.Index) !void {37184fn airBitCast(self: *CodeGen, inst: Air.Inst.Index) !void {
37224 const pt = self.pt;37185 const pt = self.pt;
37225 const zcu = pt.zcu;37186 const zcu = pt.zcu;
src/codegen/c.zig+1-43
...@@ -3325,7 +3325,6 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -3325,7 +3325,6 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
3325 .bitcast => try airBitcast(f, inst),3325 .bitcast => try airBitcast(f, inst),
3326 .intcast => try airIntCast(f, inst),3326 .intcast => try airIntCast(f, inst),
3327 .trunc => try airTrunc(f, inst),3327 .trunc => try airTrunc(f, inst),
3328 .int_from_bool => try airIntFromBool(f, inst),
3329 .load => try airLoad(f, inst),3328 .load => try airLoad(f, inst),
3330 .store => try airStore(f, inst, false),3329 .store => try airStore(f, inst, false),
3331 .store_safe => try airStore(f, inst, true),3330 .store_safe => try airStore(f, inst, true),
...@@ -3371,8 +3370,6 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -3371,8 +3370,6 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
3371 .fpext,3370 .fpext,
3372 => try airFloatCast(f, inst),3371 => try airFloatCast(f, inst),
33733372
3374 .int_from_ptr => try airIntFromPtr(f, inst),
3375
3376 .atomic_store_unordered => try airAtomicStore(f, inst, toMemoryOrder(.unordered)),3373 .atomic_store_unordered => try airAtomicStore(f, inst, toMemoryOrder(.unordered)),
3377 .atomic_store_monotonic => try airAtomicStore(f, inst, toMemoryOrder(.monotonic)),3374 .atomic_store_monotonic => try airAtomicStore(f, inst, toMemoryOrder(.monotonic)),
3378 .atomic_store_release => try airAtomicStore(f, inst, toMemoryOrder(.release)),3375 .atomic_store_release => try airAtomicStore(f, inst, toMemoryOrder(.release)),
...@@ -3983,21 +3980,6 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3983,21 +3980,6 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
3983 return local;3980 return local;
3984}3981}
39853982
3986fn airIntFromBool(f: *Function, inst: Air.Inst.Index) !CValue {
3987 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
3988 const operand = try f.resolveInst(un_op);
3989 try reap(f, inst, &.{un_op});
3990 const writer = f.object.writer();
3991 const inst_ty = f.typeOfIndex(inst);
3992 const local = try f.allocLocal(inst, inst_ty);
3993 const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete));
3994 try f.writeCValue(writer, local, .Other);
3995 try a.assign(f, writer);
3996 try f.writeCValue(writer, operand, .Other);
3997 try a.end(f, writer);
3998 return local;
3999}
4000
4001fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {3983fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
4002 const pt = f.object.dg.pt;3984 const pt = f.object.dg.pt;
4003 const zcu = pt.zcu;3985 const zcu = pt.zcu;
...@@ -4970,7 +4952,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal...@@ -4970,7 +4952,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal
4970 src_info.bits == dest_info.bits) return operand;4952 src_info.bits == dest_info.bits) return operand;
4971 }4953 }
49724954
4973 if (dest_ty.isPtrAtRuntime(zcu) and operand_ty.isPtrAtRuntime(zcu)) {4955 if (dest_ty.isPtrAtRuntime(zcu) or operand_ty.isPtrAtRuntime(zcu)) {
4974 const local = try f.allocLocal(null, dest_ty);4956 const local = try f.allocLocal(null, dest_ty);
4975 try f.writeCValue(writer, local, .Other);4957 try f.writeCValue(writer, local, .Other);
4976 try writer.writeAll(" = (");4958 try writer.writeAll(" = (");
...@@ -6455,30 +6437,6 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6455,30 +6437,6 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
6455 return local;6437 return local;
6456}6438}
64576439
6458fn airIntFromPtr(f: *Function, inst: Air.Inst.Index) !CValue {
6459 const pt = f.object.dg.pt;
6460 const zcu = pt.zcu;
6461 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
6462
6463 const operand = try f.resolveInst(un_op);
6464 const operand_ty = f.typeOf(un_op);
6465 try reap(f, inst, &.{un_op});
6466 const inst_ty = f.typeOfIndex(inst);
6467 const writer = f.object.writer();
6468 const local = try f.allocLocal(inst, inst_ty);
6469 try f.writeCValue(writer, local, .Other);
6470
6471 try writer.writeAll(" = (");
6472 try f.renderType(writer, inst_ty);
6473 try writer.writeByte(')');
6474 if (operand_ty.isSlice(zcu))
6475 try f.writeCValueMember(writer, operand, .{ .identifier = "ptr" })
6476 else
6477 try f.writeCValue(writer, operand, .Other);
6478 try writer.writeAll(";\n");
6479 return local;
6480}
6481
6482fn airUnBuiltinCall(6440fn airUnBuiltinCall(
6483 f: *Function,6441 f: *Function,
6484 inst: Air.Inst.Index,6442 inst: Air.Inst.Index,
src/codegen/llvm.zig+4-18
...@@ -5154,7 +5154,6 @@ pub const FuncGen = struct {...@@ -5154,7 +5154,6 @@ pub const FuncGen = struct {
5154 .ret_ptr => try self.airRetPtr(inst),5154 .ret_ptr => try self.airRetPtr(inst),
5155 .arg => try self.airArg(inst),5155 .arg => try self.airArg(inst),
5156 .bitcast => try self.airBitCast(inst),5156 .bitcast => try self.airBitCast(inst),
5157 .int_from_bool => try self.airIntFromBool(inst),
5158 .breakpoint => try self.airBreakpoint(inst),5157 .breakpoint => try self.airBreakpoint(inst),
5159 .ret_addr => try self.airRetAddr(inst),5158 .ret_addr => try self.airRetAddr(inst),
5160 .frame_addr => try self.airFrameAddress(inst),5159 .frame_addr => try self.airFrameAddress(inst),
...@@ -5167,7 +5166,6 @@ pub const FuncGen = struct {...@@ -5167,7 +5166,6 @@ pub const FuncGen = struct {
5167 .trunc => try self.airTrunc(inst),5166 .trunc => try self.airTrunc(inst),
5168 .fptrunc => try self.airFptrunc(inst),5167 .fptrunc => try self.airFptrunc(inst),
5169 .fpext => try self.airFpext(inst),5168 .fpext => try self.airFpext(inst),
5170 .int_from_ptr => try self.airIntFromPtr(inst),
5171 .load => try self.airLoad(body[i..]),5169 .load => try self.airLoad(body[i..]),
5172 .not => try self.airNot(inst),5170 .not => try self.airNot(inst),
5173 .store => try self.airStore(inst, false),5171 .store => try self.airStore(inst, false),
...@@ -9435,16 +9433,6 @@ pub const FuncGen = struct {...@@ -9435,16 +9433,6 @@ pub const FuncGen = struct {
9435 }9433 }
9436 }9434 }
94379435
9438 fn airIntFromPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
9439 const o = self.ng.object;
9440 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
9441 const operand = try self.resolveInst(un_op);
9442 const ptr_ty = self.typeOf(un_op);
9443 const operand_ptr = try self.sliceOrArrayPtr(operand, ptr_ty);
9444 const dest_llvm_ty = try o.lowerType(self.typeOfIndex(inst));
9445 return self.wip.cast(.ptrtoint, operand_ptr, dest_llvm_ty, "");
9446 }
9447
9448 fn airBitCast(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {9436 fn airBitCast(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
9449 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;9437 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
9450 const operand_ty = self.typeOf(ty_op.operand);9438 const operand_ty = self.typeOf(ty_op.operand);
...@@ -9476,6 +9464,10 @@ pub const FuncGen = struct {...@@ -9476,6 +9464,10 @@ pub const FuncGen = struct {
9476 return self.wip.cast(.inttoptr, operand, llvm_dest_ty, "");9464 return self.wip.cast(.inttoptr, operand, llvm_dest_ty, "");
9477 }9465 }
94789466
9467 if (operand_ty.isPtrAtRuntime(zcu) and inst_ty.zigTypeTag(zcu) == .int) {
9468 return self.wip.cast(.ptrtoint, operand, llvm_dest_ty, "");
9469 }
9470
9479 if (operand_ty.zigTypeTag(zcu) == .vector and inst_ty.zigTypeTag(zcu) == .array) {9471 if (operand_ty.zigTypeTag(zcu) == .vector and inst_ty.zigTypeTag(zcu) == .array) {
9480 const elem_ty = operand_ty.childType(zcu);9472 const elem_ty = operand_ty.childType(zcu);
9481 if (!result_is_ref) {9473 if (!result_is_ref) {
...@@ -9564,12 +9556,6 @@ pub const FuncGen = struct {...@@ -9564,12 +9556,6 @@ pub const FuncGen = struct {
9564 return self.wip.cast(.bitcast, operand, llvm_dest_ty, "");9556 return self.wip.cast(.bitcast, operand, llvm_dest_ty, "");
9565 }9557 }
95669558
9567 fn airIntFromBool(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
9568 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
9569 const operand = try self.resolveInst(un_op);
9570 return operand;
9571 }
9572
9573 fn airArg(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {9559 fn airArg(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
9574 const o = self.ng.object;9560 const o = self.ng.object;
9575 const pt = o.pt;9561 const pt = o.pt;
src/codegen/spirv.zig+6-16
...@@ -3449,10 +3449,8 @@ const NavGen = struct {...@@ -3449,10 +3449,8 @@ const NavGen = struct {
34493449
3450 .bitcast => try self.airBitCast(inst),3450 .bitcast => try self.airBitCast(inst),
3451 .intcast, .trunc => try self.airIntCast(inst),3451 .intcast, .trunc => try self.airIntCast(inst),
3452 .int_from_ptr => try self.airIntFromPtr(inst),
3453 .float_from_int => try self.airFloatFromInt(inst),3452 .float_from_int => try self.airFloatFromInt(inst),
3454 .int_from_float => try self.airIntFromFloat(inst),3453 .int_from_float => try self.airIntFromFloat(inst),
3455 .int_from_bool => try self.airIntFromBool(inst),
3456 .fpext, .fptrunc => try self.airFloatCast(inst),3454 .fpext, .fptrunc => try self.airFloatCast(inst),
3457 .not => try self.airNot(inst),3455 .not => try self.airNot(inst),
34583456
...@@ -4706,9 +4704,14 @@ const NavGen = struct {...@@ -4706,9 +4704,14 @@ const NavGen = struct {
47064704
4707 fn airBitCast(self: *NavGen, inst: Air.Inst.Index) !?IdRef {4705 fn airBitCast(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
4708 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;4706 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
4709 const operand_id = try self.resolve(ty_op.operand);
4710 const operand_ty = self.typeOf(ty_op.operand);4707 const operand_ty = self.typeOf(ty_op.operand);
4711 const result_ty = self.typeOfIndex(inst);4708 const result_ty = self.typeOfIndex(inst);
4709 if (operand_ty.toIntern() == .bool_type) {
4710 const operand = try self.temporary(ty_op.operand);
4711 const result = try self.intFromBool(operand);
4712 return try result.materialize(self);
4713 }
4714 const operand_id = try self.resolve(ty_op.operand);
4712 return try self.bitCast(result_ty, operand_ty, operand_id);4715 return try self.bitCast(result_ty, operand_ty, operand_id);
4713 }4716 }
47144717
...@@ -4749,12 +4752,6 @@ const NavGen = struct {...@@ -4749,12 +4752,6 @@ const NavGen = struct {
4749 return result_id;4752 return result_id;
4750 }4753 }
47514754
4752 fn airIntFromPtr(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
4753 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4754 const operand_id = try self.resolve(un_op);
4755 return try self.intFromPtr(operand_id);
4756 }
4757
4758 fn airFloatFromInt(self: *NavGen, inst: Air.Inst.Index) !?IdRef {4755 fn airFloatFromInt(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
4759 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;4756 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
4760 const operand_ty = self.typeOf(ty_op.operand);4757 const operand_ty = self.typeOf(ty_op.operand);
...@@ -4808,13 +4805,6 @@ const NavGen = struct {...@@ -4808,13 +4805,6 @@ const NavGen = struct {
4808 return result_id;4805 return result_id;
4809 }4806 }
48104807
4811 fn airIntFromBool(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
4812 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
4813 const operand = try self.temporary(un_op);
4814 const result = try self.intFromBool(operand);
4815 return try result.materialize(self);
4816 }
4817
4818 fn airFloatCast(self: *NavGen, inst: Air.Inst.Index) !?IdRef {4808 fn airFloatCast(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
4819 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;4809 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
4820 const operand_id = try self.resolve(ty_op.operand);4810 const operand_id = try self.resolve(ty_op.operand);
src/print_air.zig-2
...@@ -172,8 +172,6 @@ const Writer = struct {...@@ -172,8 +172,6 @@ const Writer = struct {
172 .is_non_err,172 .is_non_err,
173 .is_err_ptr,173 .is_err_ptr,
174 .is_non_err_ptr,174 .is_non_err_ptr,
175 .int_from_ptr,
176 .int_from_bool,
177 .ret,175 .ret,
178 .ret_safe,176 .ret_safe,
179 .ret_load,177 .ret_load,
src/target.zig+3
...@@ -745,5 +745,8 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt...@@ -745,5 +745,8 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt
745 .stage2_llvm => false,745 .stage2_llvm => false,
746 else => true,746 else => true,
747 },747 },
748 .all_vector_instructions => switch (backend) {
749 else => false,
750 },
748 };751 };
749}752}