authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-05-30 12:13:18-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-05-31 18:54:28-04:00
log6198f7afb76b7a5a6d359bfd24f8fbdabc77939b
tree8acd0c84bde1d8e05e87a89b222a2d3c6ced2781
parentb4a0a082dca22b47fe394908c44eec7102def417

Sema: remove `all_vector_instructions` logic

Backends can instead ask legalization on a per-instruction basis.

15 files changed, 224 insertions(+), 197 deletions(-)

src/Air/Legalize.zig+13-6
......@@ -42,6 +42,7 @@ pub const Feature = enum {
4242 scalarize_shl_sat,
4343 scalarize_xor,
4444 scalarize_not,
45 scalarize_bitcast,
4546 scalarize_clz,
4647 scalarize_ctz,
4748 scalarize_popcount,
......@@ -76,7 +77,7 @@ pub const Feature = enum {
7677 scalarize_mul_add,
7778
7879 /// Legalize (shift lhs, (splat rhs)) -> (shift lhs, rhs)
79 remove_shift_vector_rhs_splat,
80 unsplat_shift_rhs,
8081 /// Legalize reduce of a one element vector to a bitcast
8182 reduce_one_elem_to_bitcast,
8283
......@@ -121,6 +122,7 @@ pub const Feature = enum {
121122 .shl_sat => .scalarize_shl_sat,
122123 .xor => .scalarize_xor,
123124 .not => .scalarize_not,
125 .bitcast => .scalarize_bitcast,
124126 .clz => .scalarize_clz,
125127 .ctz => .scalarize_ctz,
126128 .popcount => .scalarize_popcount,
......@@ -259,9 +261,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
259261 => |air_tag| done: {
260262 const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op;
261263 if (!l.typeOf(bin_op.rhs).isVector(zcu)) break :done;
262 if (l.features.contains(comptime .scalarize(air_tag))) {
263 continue :inst try l.scalarize(inst, .bin_op);
264 } else if (l.features.contains(.remove_shift_vector_rhs_splat)) {
264 if (l.features.contains(.unsplat_shift_rhs)) {
265265 if (bin_op.rhs.toInterned()) |rhs_ip_index| switch (ip.indexToKey(rhs_ip_index)) {
266266 else => {},
267267 .aggregate => |aggregate| switch (aggregate.storage) {
......@@ -282,6 +282,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
282282 }
283283 }
284284 }
285 if (l.features.contains(comptime .scalarize(air_tag))) continue :inst try l.scalarize(inst, .bin_op);
285286 },
286287 inline .not,
287288 .clz,
......@@ -302,8 +303,14 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
302303 const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op;
303304 if (ty_op.ty.toType().isVector(zcu)) continue :inst try l.scalarize(inst, .ty_op);
304305 },
305 .bitcast,
306 => {},
306 inline .bitcast,
307 => |air_tag| if (l.features.contains(comptime .scalarize(air_tag))) {
308 const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op;
309 const to_ty = ty_op.ty.toType();
310 const from_ty = l.typeOf(ty_op.operand);
311 if (to_ty.isVector(zcu) and from_ty.isVector(zcu) and to_ty.vectorLen(zcu) == from_ty.vectorLen(zcu))
312 continue :inst try l.scalarize(inst, .ty_op);
313 },
307314 .block,
308315 .loop,
309316 => {
src/Sema.zig+47-140
......@@ -10165,16 +10165,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1016510165 try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), ptr_src);
1016610166 try sema.validateRuntimeValue(block, ptr_src, operand);
1016710167 try sema.checkLogicalPtrOperation(block, ptr_src, ptr_ty);
10168 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {
10169 return block.addBitCast(dest_ty, operand);
10170 }
10171 const new_elems = try sema.arena.alloc(Air.Inst.Ref, len);
10172 for (new_elems, 0..) |*new_elem, i| {
10173 const idx_ref = try pt.intRef(.usize, i);
10174 const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref);
10175 new_elem.* = try block.addBitCast(.usize, old_elem);
10176 }
10177 return block.addAggregateInit(dest_ty, new_elems);
10168 return block.addBitCast(dest_ty, operand);
1017810169}
1017910170
1018010171fn zirFieldVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -10640,17 +10631,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1064010631 if (dst_bits >= src_bits) {
1064110632 return sema.coerce(block, dest_ty, operand, operand_src);
1064210633 }
10643 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {
10644 return block.addTyOp(.fptrunc, dest_ty, operand);
10645 }
10646 const vec_len = operand_ty.vectorLen(zcu);
10647 const new_elems = try sema.arena.alloc(Air.Inst.Ref, vec_len);
10648 for (new_elems, 0..) |*new_elem, i| {
10649 const idx_ref = try pt.intRef(.usize, i);
10650 const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref);
10651 new_elem.* = try block.addTyOp(.fptrunc, dest_scalar_ty, old_elem);
10652 }
10653 return block.addAggregateInit(dest_ty, new_elems);
10634 return block.addTyOp(.fptrunc, dest_ty, operand);
1065410635}
1065510636
1065610637fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -20722,16 +20703,7 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
2072220703 .storage = .{ .elems = new_elems },
2072320704 } }));
2072420705 }
20725 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {
20726 return block.addBitCast(dest_ty, operand);
20727 }
20728 const new_elems = try sema.arena.alloc(Air.Inst.Ref, len);
20729 for (new_elems, 0..) |*new_elem, i| {
20730 const idx_ref = try pt.intRef(.usize, i);
20731 const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref);
20732 new_elem.* = try block.addBitCast(.u1, old_elem);
20733 }
20734 return block.addAggregateInit(dest_ty, new_elems);
20706 return block.addBitCast(dest_ty, operand);
2073520707}
2073620708
2073720709fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -22327,42 +22299,23 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
2232722299 .storage = .{ .repeated_elem = (try pt.intValue(dest_scalar_ty, 0)).toIntern() },
2232822300 } }));
2232922301 }
22330 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {
22331 const result = try block.addTyOp(if (block.float_mode == .optimized) .int_from_float_optimized else .int_from_float, dest_ty, operand);
22332 if (block.wantSafety()) {
22333 const back = try block.addTyOp(.float_from_int, operand_ty, result);
22334 const diff = try block.addBinOp(if (block.float_mode == .optimized) .sub_optimized else .sub, operand, back);
22335 const ok = if (is_vector) ok: {
22336 const ok_pos = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, 1.0))).toIntern()), .lt);
22337 const ok_neg = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, -1.0))).toIntern()), .gt);
22338 const ok = try block.addBinOp(.bit_and, ok_pos, ok_neg);
22339 break :ok try block.addReduce(ok, .And);
22340 } else ok: {
22341 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()));
22342 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()));
22343 break :ok try block.addBinOp(.bool_and, ok_pos, ok_neg);
22344 };
22345 try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds);
22346 }
22347 return result;
22348 }
22349 const len = dest_ty.vectorLen(zcu);
22350 const new_elems = try sema.arena.alloc(Air.Inst.Ref, len);
22351 for (new_elems, 0..) |*new_elem, i| {
22352 const idx_ref = try pt.intRef(.usize, i);
22353 const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref);
22354 const result = try block.addTyOp(if (block.float_mode == .optimized) .int_from_float_optimized else .int_from_float, dest_scalar_ty, old_elem);
22355 if (block.wantSafety()) {
22356 const back = try block.addTyOp(.float_from_int, operand_scalar_ty, result);
22357 const diff = try block.addBinOp(.sub, old_elem, back);
22358 const ok_pos = try block.addBinOp(if (block.float_mode == .optimized) .cmp_lt_optimized else .cmp_lt, diff, Air.internedToRef((try pt.floatValue(operand_scalar_ty, 1.0)).toIntern()));
22359 const ok_neg = try block.addBinOp(if (block.float_mode == .optimized) .cmp_gt_optimized else .cmp_gt, diff, Air.internedToRef((try pt.floatValue(operand_scalar_ty, -1.0)).toIntern()));
22360 const ok = try block.addBinOp(.bool_and, ok_pos, ok_neg);
22361 try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds);
22362 }
22363 new_elem.* = result;
22302 const result = try block.addTyOp(if (block.float_mode == .optimized) .int_from_float_optimized else .int_from_float, dest_ty, operand);
22303 if (block.wantSafety()) {
22304 const back = try block.addTyOp(.float_from_int, operand_ty, result);
22305 const diff = try block.addBinOp(if (block.float_mode == .optimized) .sub_optimized else .sub, operand, back);
22306 const ok = if (is_vector) ok: {
22307 const ok_pos = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, 1.0))).toIntern()), .lt);
22308 const ok_neg = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, -1.0))).toIntern()), .gt);
22309 const ok = try block.addBinOp(.bit_and, ok_pos, ok_neg);
22310 break :ok try block.addReduce(ok, .And);
22311 } else ok: {
22312 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()));
22313 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()));
22314 break :ok try block.addBinOp(.bool_and, ok_pos, ok_neg);
22315 };
22316 try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds);
2236422317 }
22365 return block.addAggregateInit(dest_ty, new_elems);
22318 return result;
2236622319}
2236722320
2236822321fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -22377,7 +22330,6 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
2237722330 const operand_ty = sema.typeOf(operand);
2237822331
2237922332 try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, src, operand_src);
22380 const is_vector = dest_ty.zigTypeTag(zcu) == .vector;
2238122333
2238222334 const dest_scalar_ty = dest_ty.scalarType(zcu);
2238322335 const operand_scalar_ty = operand_ty.scalarType(zcu);
......@@ -22393,17 +22345,7 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
2239322345 }
2239422346
2239522347 try sema.requireRuntimeBlock(block, src, operand_src);
22396 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {
22397 return block.addTyOp(.float_from_int, dest_ty, operand);
22398 }
22399 const len = operand_ty.vectorLen(zcu);
22400 const new_elems = try sema.arena.alloc(Air.Inst.Ref, len);
22401 for (new_elems, 0..) |*new_elem, i| {
22402 const idx_ref = try pt.intRef(.usize, i);
22403 const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref);
22404 new_elem.* = try block.addTyOp(.float_from_int, dest_scalar_ty, old_elem);
22405 }
22406 return block.addAggregateInit(dest_ty, new_elems);
22348 return block.addTyOp(.float_from_int, dest_ty, operand);
2240722349}
2240822350
2240922351fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -22473,69 +22415,34 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2247322415 }
2247422416 try sema.requireRuntimeBlock(block, src, operand_src);
2247522417 try sema.checkLogicalPtrOperation(block, src, ptr_ty);
22476 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {
22477 if (block.wantSafety() and (try elem_ty.hasRuntimeBitsSema(pt) or elem_ty.zigTypeTag(zcu) == .@"fn")) {
22478 if (!ptr_ty.isAllowzeroPtr(zcu)) {
22479 const is_non_zero = if (is_vector) all_non_zero: {
22480 const zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern());
22481 const is_non_zero = try block.addCmpVector(operand_coerced, zero_usize, .neq);
22482 break :all_non_zero try block.addReduce(is_non_zero, .And);
22483 } else try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize);
22484 try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null);
22485 }
22486 if (ptr_align.compare(.gt, .@"1")) {
22487 const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1;
22488 const align_mask = Air.internedToRef((try sema.splat(operand_ty, try pt.intValue(
22489 .usize,
22490 if (elem_ty.fnPtrMaskOrNull(zcu)) |mask|
22491 align_bytes_minus_1 & mask
22492 else
22493 align_bytes_minus_1,
22494 ))).toIntern());
22495 const remainder = try block.addBinOp(.bit_and, operand_coerced, align_mask);
22496 const is_aligned = if (is_vector) all_aligned: {
22497 const splat_zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern());
22498 const is_aligned = try block.addCmpVector(remainder, splat_zero_usize, .eq);
22499 break :all_aligned try block.addReduce(is_aligned, .And);
22500 } else try block.addBinOp(.cmp_eq, remainder, .zero_usize);
22501 try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment);
22502 }
22503 }
22504 return block.addBitCast(dest_ty, operand_coerced);
22505 }
22506
22507 const len = dest_ty.vectorLen(zcu);
2250822418 if (block.wantSafety() and (try elem_ty.hasRuntimeBitsSema(pt) or elem_ty.zigTypeTag(zcu) == .@"fn")) {
22509 for (0..len) |i| {
22510 const idx_ref = try pt.intRef(.usize, i);
22511 const elem_coerced = try block.addBinOp(.array_elem_val, operand_coerced, idx_ref);
22512 if (!ptr_ty.isAllowzeroPtr(zcu)) {
22513 const is_non_zero = try block.addBinOp(.cmp_neq, elem_coerced, .zero_usize);
22514 try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null);
22515 }
22516 if (ptr_align.compare(.gt, .@"1")) {
22517 const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1;
22518 const align_mask = Air.internedToRef((try pt.intValue(
22519 .usize,
22520 if (elem_ty.fnPtrMaskOrNull(zcu)) |mask|
22521 align_bytes_minus_1 & mask
22522 else
22523 align_bytes_minus_1,
22524 )).toIntern());
22525 const remainder = try block.addBinOp(.bit_and, elem_coerced, align_mask);
22526 const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize);
22527 try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment);
22528 }
22529 }
22530 }
22531
22532 const new_elems = try sema.arena.alloc(Air.Inst.Ref, len);
22533 for (new_elems, 0..) |*new_elem, i| {
22534 const idx_ref = try pt.intRef(.usize, i);
22535 const old_elem = try block.addBinOp(.array_elem_val, operand_coerced, idx_ref);
22536 new_elem.* = try block.addBitCast(ptr_ty, old_elem);
22537 }
22538 return block.addAggregateInit(dest_ty, new_elems);
22419 if (!ptr_ty.isAllowzeroPtr(zcu)) {
22420 const is_non_zero = if (is_vector) all_non_zero: {
22421 const zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern());
22422 const is_non_zero = try block.addCmpVector(operand_coerced, zero_usize, .neq);
22423 break :all_non_zero try block.addReduce(is_non_zero, .And);
22424 } else try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize);
22425 try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null);
22426 }
22427 if (ptr_align.compare(.gt, .@"1")) {
22428 const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1;
22429 const align_mask = Air.internedToRef((try sema.splat(operand_ty, try pt.intValue(
22430 .usize,
22431 if (elem_ty.fnPtrMaskOrNull(zcu)) |mask|
22432 align_bytes_minus_1 & mask
22433 else
22434 align_bytes_minus_1,
22435 ))).toIntern());
22436 const remainder = try block.addBinOp(.bit_and, operand_coerced, align_mask);
22437 const is_aligned = if (is_vector) all_aligned: {
22438 const splat_zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern());
22439 const is_aligned = try block.addCmpVector(remainder, splat_zero_usize, .eq);
22440 break :all_aligned try block.addReduce(is_aligned, .And);
22441 } else try block.addBinOp(.cmp_eq, remainder, .zero_usize);
22442 try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment);
22443 }
22444 }
22445 return block.addBitCast(dest_ty, operand_coerced);
2253922446}
2254022447
2254122448fn ptrFromIntVal(
src/Zcu.zig-9
......@@ -3840,15 +3840,6 @@ pub const Feature = enum {
38403840 safety_checked_instructions,
38413841 /// If the backend supports running from another thread.
38423842 separate_thread,
3843 /// If the backend supports the following AIR instructions with vector types:
3844 /// * `Air.Inst.Tag.bit_and`
3845 /// * `Air.Inst.Tag.bit_or`
3846 /// * `Air.Inst.Tag.bitcast`
3847 /// * `Air.Inst.Tag.float_from_int`
3848 /// * `Air.Inst.Tag.fptrunc`
3849 /// * `Air.Inst.Tag.int_from_float`
3850 /// If not supported, Sema will scalarize the operation.
3851 all_vector_instructions,
38523843};
38533844
38543845pub fn backendSupportsFeature(zcu: *const Zcu, comptime feature: Feature) bool {
src/arch/aarch64/CodeGen.zig+23-6
......@@ -40,6 +40,10 @@ const gp = abi.RegisterClass.gp;
4040
4141const InnerError = CodeGenError || error{OutOfRegisters};
4242
43pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
44 return comptime &.initEmpty();
45}
46
4347gpa: Allocator,
4448pt: Zcu.PerThread,
4549air: Air,
......@@ -2261,12 +2265,13 @@ fn shiftExact(
22612265 rhs_ty: Type,
22622266 maybe_inst: ?Air.Inst.Index,
22632267) InnerError!MCValue {
2264 _ = rhs_ty;
2265
22662268 const pt = self.pt;
22672269 const zcu = pt.zcu;
22682270 switch (lhs_ty.zigTypeTag(zcu)) {
2269 .vector => return self.fail("TODO binary operations on vectors", .{}),
2271 .vector => if (!rhs_ty.isVector(zcu))
2272 return self.fail("TODO vector shift with scalar rhs", .{})
2273 else
2274 return self.fail("TODO binary operations on vectors", .{}),
22702275 .int => {
22712276 const int_info = lhs_ty.intInfo(zcu);
22722277 if (int_info.bits <= 64) {
......@@ -2317,7 +2322,10 @@ fn shiftNormal(
23172322 const pt = self.pt;
23182323 const zcu = pt.zcu;
23192324 switch (lhs_ty.zigTypeTag(zcu)) {
2320 .vector => return self.fail("TODO binary operations on vectors", .{}),
2325 .vector => if (!rhs_ty.isVector(zcu))
2326 return self.fail("TODO vector shift with scalar rhs", .{})
2327 else
2328 return self.fail("TODO binary operations on vectors", .{}),
23212329 .int => {
23222330 const int_info = lhs_ty.intInfo(zcu);
23232331 if (int_info.bits <= 64) {
......@@ -2874,7 +2882,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!void {
28742882 const overflow_bit_offset = @as(u32, @intCast(tuple_ty.structFieldOffset(1, zcu)));
28752883
28762884 switch (lhs_ty.zigTypeTag(zcu)) {
2877 .vector => return self.fail("TODO implement shl_with_overflow for vectors", .{}),
2885 .vector => if (!rhs_ty.isVector(zcu))
2886 return self.fail("TODO implement vector shl_with_overflow with scalar rhs", .{})
2887 else
2888 return self.fail("TODO implement shl_with_overflow for vectors", .{}),
28782889 .int => {
28792890 const int_info = lhs_ty.intInfo(zcu);
28802891 if (int_info.bits <= 64) {
......@@ -2993,8 +3004,14 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!void {
29933004}
29943005
29953006fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!void {
3007 const zcu = self.pt.zcu;
29963008 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2997 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch});
3009 const result: MCValue = if (self.liveness.isUnused(inst))
3010 .dead
3011 else if (self.typeOf(bin_op.lhs).isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu))
3012 return self.fail("TODO implement vector shl_sat with scalar rhs for {}", .{self.target.cpu.arch})
3013 else
3014 return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch});
29983015 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
29993016}
30003017
src/arch/arm/CodeGen.zig+23-4
......@@ -41,6 +41,10 @@ const gp = abi.RegisterClass.gp;
4141
4242const InnerError = CodeGenError || error{OutOfRegisters};
4343
44pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
45 return comptime &.initEmpty();
46}
47
4448gpa: Allocator,
4549pt: Zcu.PerThread,
4650air: Air,
......@@ -1857,7 +1861,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
18571861 const overflow_bit_offset: u32 = @intCast(tuple_ty.structFieldOffset(1, zcu));
18581862
18591863 switch (lhs_ty.zigTypeTag(zcu)) {
1860 .vector => return self.fail("TODO implement shl_with_overflow for vectors", .{}),
1864 .vector => if (!rhs_ty.isVector(zcu))
1865 return self.fail("TODO implement vector shl_with_overflow with scalar rhs", .{})
1866 else
1867 return self.fail("TODO implement shl_with_overflow for vectors", .{}),
18611868 .int => {
18621869 const int_info = lhs_ty.intInfo(zcu);
18631870 if (int_info.bits <= 32) {
......@@ -1978,8 +1985,14 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
19781985}
19791986
19801987fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
1988 const zcu = self.pt.zcu;
19811989 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
1982 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch});
1990 const result: MCValue = if (self.liveness.isUnused(inst))
1991 .dead
1992 else if (self.typeOf(bin_op.lhs).isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu))
1993 return self.fail("TODO implement vector shl_sat with scalar rhs for {}", .{self.target.cpu.arch})
1994 else
1995 return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch});
19831996 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
19841997}
19851998
......@@ -3788,7 +3801,10 @@ fn shiftExact(
37883801 const pt = self.pt;
37893802 const zcu = pt.zcu;
37903803 switch (lhs_ty.zigTypeTag(zcu)) {
3791 .vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3804 .vector => if (!rhs_ty.isVector(zcu))
3805 return self.fail("TODO ARM vector shift with scalar rhs", .{})
3806 else
3807 return self.fail("TODO ARM binary operations on vectors", .{}),
37923808 .int => {
37933809 const int_info = lhs_ty.intInfo(zcu);
37943810 if (int_info.bits <= 32) {
......@@ -3828,7 +3844,10 @@ fn shiftNormal(
38283844 const pt = self.pt;
38293845 const zcu = pt.zcu;
38303846 switch (lhs_ty.zigTypeTag(zcu)) {
3831 .vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3847 .vector => if (!rhs_ty.isVector(zcu))
3848 return self.fail("TODO ARM vector shift with scalar rhs", .{})
3849 else
3850 return self.fail("TODO ARM binary operations on vectors", .{}),
38323851 .int => {
38333852 const int_info = lhs_ty.intInfo(zcu);
38343853 if (int_info.bits <= 32) {
src/arch/powerpc/CodeGen.zig+4
......@@ -10,6 +10,10 @@ const Zcu = @import("../../Zcu.zig");
1010const assert = std.debug.assert;
1111const log = std.log.scoped(.codegen);
1212
13pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
14 return comptime &.initEmpty();
15}
16
1317pub fn generate(
1418 bin_file: *link.File,
1519 pt: Zcu.PerThread,
src/arch/riscv64/CodeGen.zig+19-2
......@@ -51,6 +51,10 @@ const Instruction = encoding.Instruction;
5151
5252const InnerError = CodeGenError || error{OutOfRegisters};
5353
54pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
55 return comptime &.initEmpty();
56}
57
5458pt: Zcu.PerThread,
5559air: Air,
5660liveness: Air.Liveness,
......@@ -2764,6 +2768,7 @@ fn genBinOp(
27642768 .shl,
27652769 .shl_exact,
27662770 => {
2771 if (lhs_ty.isVector(zcu) and !rhs_ty.isVector(zcu)) return func.fail("TODO: vector shift with scalar rhs", .{});
27672772 if (bit_size > 64) return func.fail("TODO: genBinOp shift > 64 bits, {}", .{bit_size});
27682773 try func.truncateRegister(rhs_ty, rhs_reg);
27692774
......@@ -3248,8 +3253,14 @@ fn airMulWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
32483253}
32493254
32503255fn airShlWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
3256 const zcu = func.pt.zcu;
32513257 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
3252 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airShlWithOverflow", .{});
3258 const result: MCValue = if (func.liveness.isUnused(inst))
3259 .unreach
3260 else if (func.typeOf(bin_op.lhs).isVector(zcu) and !func.typeOf(bin_op.rhs).isVector(zcu))
3261 return func.fail("TODO implement vector airShlWithOverflow with scalar rhs", .{})
3262 else
3263 return func.fail("TODO implement airShlWithOverflow", .{});
32533264 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
32543265}
32553266
......@@ -3266,8 +3277,14 @@ fn airMulSat(func: *Func, inst: Air.Inst.Index) !void {
32663277}
32673278
32683279fn airShlSat(func: *Func, inst: Air.Inst.Index) !void {
3280 const zcu = func.pt.zcu;
32693281 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
3270 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airShlSat", .{});
3282 const result: MCValue = if (func.liveness.isUnused(inst))
3283 .unreach
3284 else if (func.typeOf(bin_op.lhs).isVector(zcu) and !func.typeOf(bin_op.rhs).isVector(zcu))
3285 return func.fail("TODO implement vector airShlSat with scalar rhs", .{})
3286 else
3287 return func.fail("TODO implement airShlSat", .{});
32713288 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
32723289}
32733290
src/arch/sparc64/CodeGen.zig+23-4
......@@ -41,6 +41,10 @@ const Self = @This();
4141
4242const InnerError = CodeGenError || error{OutOfRegisters};
4343
44pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
45 return comptime &.initEmpty();
46}
47
4448const RegisterView = enum(u1) {
4549 caller,
4650 callee,
......@@ -2270,8 +2274,14 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
22702274}
22712275
22722276fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
2277 const zcu = self.pt.zcu;
22732278 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
2274 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch});
2279 const result: MCValue = if (self.liveness.isUnused(inst))
2280 .dead
2281 else if (self.typeOf(bin_op.lhs).isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu))
2282 return self.fail("TODO implement vector shl_sat with scalar rhs for {}", .{self.target.cpu.arch})
2283 else
2284 return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch});
22752285 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
22762286}
22772287
......@@ -2287,7 +2297,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
22872297 const rhs_ty = self.typeOf(extra.rhs);
22882298
22892299 switch (lhs_ty.zigTypeTag(zcu)) {
2290 .vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}),
2300 .vector => if (!rhs_ty.isVector(zcu))
2301 return self.fail("TODO implement vector shl_with_overflow with scalar rhs", .{})
2302 else
2303 return self.fail("TODO implement mul_with_overflow for vectors", .{}),
22912304 .int => {
22922305 const int_info = lhs_ty.intInfo(zcu);
22932306 if (int_info.bits <= 64) {
......@@ -3002,7 +3015,10 @@ fn binOp(
30023015
30033016 // Truncate if necessary
30043017 switch (lhs_ty.zigTypeTag(zcu)) {
3005 .vector => return self.fail("TODO binary operations on vectors", .{}),
3018 .vector => if (rhs_ty.isVector(zcu))
3019 return self.fail("TODO vector shift with scalar rhs", .{})
3020 else
3021 return self.fail("TODO binary operations on vectors", .{}),
30063022 .int => {
30073023 const int_info = lhs_ty.intInfo(zcu);
30083024 if (int_info.bits <= 64) {
......@@ -3024,7 +3040,10 @@ fn binOp(
30243040 .shr_exact,
30253041 => {
30263042 switch (lhs_ty.zigTypeTag(zcu)) {
3027 .vector => return self.fail("TODO binary operations on vectors", .{}),
3043 .vector => if (rhs_ty.isVector(zcu))
3044 return self.fail("TODO vector shift with scalar rhs", .{})
3045 else
3046 return self.fail("TODO binary operations on vectors", .{}),
30283047 .int => {
30293048 const int_info = lhs_ty.intInfo(zcu);
30303049 if (int_info.bits <= 64) {
src/arch/wasm/CodeGen.zig+26-5
......@@ -31,6 +31,10 @@ const libcFloatSuffix = target_util.libcFloatSuffix;
3131const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev;
3232const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev;
3333
34pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
35 return comptime &.initEmpty();
36}
37
3438/// Reference to the function declaration the code
3539/// section belongs to
3640owner_nav: InternPool.Nav.Index,
......@@ -2638,6 +2642,10 @@ fn airBinOp(cg: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
26382642 // For big integers we can ignore this as we will call into compiler-rt which handles this.
26392643 const result = switch (op) {
26402644 .shr, .shl => result: {
2645 if (lhs_ty.isVector(zcu) and !rhs_ty.isVector(zcu)) {
2646 return cg.fail("TODO: implement vector '{s}' with scalar rhs", .{@tagName(op)});
2647 }
2648
26412649 const lhs_wasm_bits = toWasmBits(@intCast(lhs_ty.bitSize(zcu))) orelse {
26422650 return cg.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)});
26432651 };
......@@ -3055,8 +3063,12 @@ fn airWrapBinOp(cg: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
30553063 const lhs_ty = cg.typeOf(bin_op.lhs);
30563064 const rhs_ty = cg.typeOf(bin_op.rhs);
30573065
3058 if (lhs_ty.zigTypeTag(zcu) == .vector or rhs_ty.zigTypeTag(zcu) == .vector) {
3059 return cg.fail("TODO: Implement wrapping arithmetic for vectors", .{});
3066 if (lhs_ty.isVector(zcu)) {
3067 if ((op == .shr or op == .shl) and !rhs_ty.isVector(zcu)) {
3068 return cg.fail("TODO: implement wrapping vector '{s}' with scalar rhs", .{@tagName(op)});
3069 } else {
3070 return cg.fail("TODO: implement wrapping '{s}' for vectors", .{@tagName(op)});
3071 }
30603072 }
30613073
30623074 // For certain operations, such as shifting, the types are different.
......@@ -6067,13 +6079,17 @@ fn airShlWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
60676079 const ty = cg.typeOf(extra.lhs);
60686080 const rhs_ty = cg.typeOf(extra.rhs);
60696081
6070 if (ty.zigTypeTag(zcu) == .vector) {
6071 return cg.fail("TODO: Implement overflow arithmetic for vectors", .{});
6082 if (ty.isVector(zcu)) {
6083 if (!rhs_ty.isVector(zcu)) {
6084 return cg.fail("TODO: implement vector 'shl_with_overflow' with scalar rhs", .{});
6085 } else {
6086 return cg.fail("TODO: implement vector 'shl_with_overflow'", .{});
6087 }
60726088 }
60736089
60746090 const int_info = ty.intInfo(zcu);
60756091 const wasm_bits = toWasmBits(int_info.bits) orelse {
6076 return cg.fail("TODO: Implement shl_with_overflow for integer bitsize: {d}", .{int_info.bits});
6092 return cg.fail("TODO: implement 'shl_with_overflow' for integer bitsize: {d}", .{int_info.bits});
60776093 };
60786094
60796095 // Ensure rhs is coerced to lhs as they must have the same WebAssembly types
......@@ -6994,6 +7010,11 @@ fn airShlSat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
69947010
69957011 const pt = cg.pt;
69967012 const zcu = pt.zcu;
7013
7014 if (cg.typeOf(bin_op.lhs).isVector(zcu) and !cg.typeOf(bin_op.rhs).isVector(zcu)) {
7015 return cg.fail("TODO: implement vector 'shl_sat' with scalar rhs", .{});
7016 }
7017
69977018 const ty = cg.typeOfIndex(inst);
69987019 const int_info = ty.intInfo(zcu);
69997020 const is_signed = int_info.signedness == .signed;
src/arch/x86_64/CodeGen.zig+2-2
......@@ -32,7 +32,7 @@ const FrameIndex = bits.FrameIndex;
3232
3333const InnerError = codegen.CodeGenError || error{OutOfRegisters};
3434
35pub inline fn legalizeFeatures(target: *const std.Target) *const Air.Legalize.Features {
35pub fn legalizeFeatures(target: *const std.Target) *const Air.Legalize.Features {
3636 @setEvalBranchQuota(1_200);
3737 return switch (target.ofmt == .coff) {
3838 inline false, true => |use_old| comptime &.init(.{
......@@ -86,7 +86,7 @@ pub inline fn legalizeFeatures(target: *const std.Target) *const Air.Legalize.Fe
8686 .scalarize_float_from_int = use_old,
8787 .scalarize_mul_add = use_old,
8888
89 .remove_shift_vector_rhs_splat = false,
89 .unsplat_shift_rhs = false,
9090 .reduce_one_elem_to_bitcast = true,
9191 }),
9292 };
src/codegen.zig+3-6
......@@ -52,7 +52,7 @@ fn importBackend(comptime backend: std.builtin.CompilerBackend) type {
5252pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) *const Air.Legalize.Features {
5353 const zcu = pt.zcu;
5454 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;
55 switch (target_util.zigBackend(target.*, zcu.comp.config.use_llvm)) {
55 return switch (target_util.zigBackend(target.*, zcu.comp.config.use_llvm)) {
5656 else => unreachable,
5757 inline .stage2_llvm,
5858 .stage2_c,
......@@ -65,11 +65,8 @@ pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) *con
6565 .stage2_sparc64,
6666 .stage2_spirv64,
6767 .stage2_powerpc,
68 => |backend| {
69 const Backend = importBackend(backend);
70 return if (@hasDecl(Backend, "legalizeFeatures")) Backend.legalizeFeatures(target) else comptime &.initEmpty();
71 },
72 }
68 => |backend| importBackend(backend).legalizeFeatures(target),
69 };
7370}
7471
7572pub fn generateFunction(
src/codegen/c.zig+6-2
......@@ -20,6 +20,10 @@ const Alignment = InternPool.Alignment;
2020const BigIntLimb = std.math.big.Limb;
2121const BigInt = std.math.big.int;
2222
23pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
24 return comptime &.initEmpty();
25}
26
2327pub const CType = @import("c/Type.zig");
2428
2529pub const CValue = union(enum) {
......@@ -4179,7 +4183,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
41794183 try v.elem(f, w);
41804184 try w.writeAll(", ");
41814185 try f.writeCValue(w, rhs, .FunctionArgument);
4182 try v.elem(f, w);
4186 if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);
41834187 try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
41844188 try w.writeAll(");\n");
41854189 try v.end(f, inst, w);
......@@ -6536,7 +6540,7 @@ fn airBinBuiltinCall(
65366540 try v.elem(f, writer);
65376541 try writer.writeAll(", ");
65386542 try f.writeCValue(writer, rhs, .FunctionArgument);
6539 try v.elem(f, writer);
6543 if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, writer);
65406544 try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info);
65416545 try writer.writeAll(");\n");
65426546 try v.end(f, inst, writer);
src/codegen/llvm.zig+23-7
......@@ -36,6 +36,10 @@ const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev;
3636
3737const Error = error{ OutOfMemory, CodegenFail };
3838
39pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
40 return comptime &.initEmpty();
41}
42
3943fn subArchName(features: std.Target.Cpu.Feature.Set, arch: anytype, mappings: anytype) ?[]const u8 {
4044 inline for (mappings) |mapping| {
4145 if (arch.featureSetHas(features, mapping[0])) return mapping[1];
......@@ -8923,6 +8927,8 @@ pub const FuncGen = struct {
89238927 const rhs = try self.resolveInst(extra.rhs);
89248928
89258929 const lhs_ty = self.typeOf(extra.lhs);
8930 if (lhs_ty.isVector(zcu) and !self.typeOf(extra.rhs).isVector(zcu))
8931 return self.ng.todo("implement vector shifts with scalar rhs", .{});
89268932 const lhs_scalar_ty = lhs_ty.scalarType(zcu);
89278933
89288934 const dest_ty = self.typeOfIndex(inst);
......@@ -8992,6 +8998,8 @@ pub const FuncGen = struct {
89928998 const rhs = try self.resolveInst(bin_op.rhs);
89938999
89949000 const lhs_ty = self.typeOf(bin_op.lhs);
9001 if (lhs_ty.isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu))
9002 return self.ng.todo("implement vector shifts with scalar rhs", .{});
89959003 const lhs_scalar_ty = lhs_ty.scalarType(zcu);
89969004
89979005 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), "");
......@@ -9003,14 +9011,17 @@ pub const FuncGen = struct {
90039011
90049012 fn airShl(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
90059013 const o = self.ng.object;
9014 const zcu = o.pt.zcu;
90069015 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
90079016
90089017 const lhs = try self.resolveInst(bin_op.lhs);
90099018 const rhs = try self.resolveInst(bin_op.rhs);
90109019
9011 const lhs_type = self.typeOf(bin_op.lhs);
9020 const lhs_ty = self.typeOf(bin_op.lhs);
9021 if (lhs_ty.isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu))
9022 return self.ng.todo("implement vector shifts with scalar rhs", .{});
90129023
9013 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_type), "");
9024 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), "");
90149025 return self.wip.bin(.shl, lhs, casted_rhs, "");
90159026 }
90169027
......@@ -9029,6 +9040,8 @@ pub const FuncGen = struct {
90299040 const llvm_lhs_scalar_ty = llvm_lhs_ty.scalarType(&o.builder);
90309041
90319042 const rhs_ty = self.typeOf(bin_op.rhs);
9043 if (lhs_ty.isVector(zcu) and !rhs_ty.isVector(zcu))
9044 return self.ng.todo("implement vector shifts with scalar rhs", .{});
90329045 const rhs_info = rhs_ty.intInfo(zcu);
90339046 assert(rhs_info.signedness == .unsigned);
90349047 const llvm_rhs_ty = try o.lowerType(rhs_ty);
......@@ -9101,6 +9114,8 @@ pub const FuncGen = struct {
91019114 const rhs = try self.resolveInst(bin_op.rhs);
91029115
91039116 const lhs_ty = self.typeOf(bin_op.lhs);
9117 if (lhs_ty.isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu))
9118 return self.ng.todo("implement vector shifts with scalar rhs", .{});
91049119 const lhs_scalar_ty = lhs_ty.scalarType(zcu);
91059120
91069121 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), "");
......@@ -9255,8 +9270,6 @@ pub const FuncGen = struct {
92559270 const operand_ty = self.typeOf(ty_op.operand);
92569271 const dest_ty = self.typeOfIndex(inst);
92579272 const target = zcu.getTarget();
9258 const dest_bits = dest_ty.floatBits(target);
9259 const src_bits = operand_ty.floatBits(target);
92609273
92619274 if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) {
92629275 return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty), "");
......@@ -9264,6 +9277,8 @@ pub const FuncGen = struct {
92649277 const operand_llvm_ty = try o.lowerType(operand_ty);
92659278 const dest_llvm_ty = try o.lowerType(dest_ty);
92669279
9280 const dest_bits = dest_ty.floatBits(target);
9281 const src_bits = operand_ty.floatBits(target);
92679282 const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{
92689283 compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits),
92699284 });
......@@ -9348,11 +9363,12 @@ pub const FuncGen = struct {
93489363 return self.wip.conv(.unsigned, operand, llvm_dest_ty, "");
93499364 }
93509365
9351 if (operand_ty.zigTypeTag(zcu) == .int and inst_ty.isPtrAtRuntime(zcu)) {
9366 const operand_scalar_ty = operand_ty.scalarType(zcu);
9367 const inst_scalar_ty = inst_ty.scalarType(zcu);
9368 if (operand_scalar_ty.zigTypeTag(zcu) == .int and inst_scalar_ty.isPtrAtRuntime(zcu)) {
93529369 return self.wip.cast(.inttoptr, operand, llvm_dest_ty, "");
93539370 }
9354
9355 if (operand_ty.isPtrAtRuntime(zcu) and inst_ty.zigTypeTag(zcu) == .int) {
9371 if (operand_scalar_ty.isPtrAtRuntime(zcu) and inst_scalar_ty.zigTypeTag(zcu) == .int) {
93569372 return self.wip.cast(.ptrtoint, operand, llvm_dest_ty, "");
93579373 }
93589374
src/codegen/spirv.zig+12
......@@ -28,6 +28,10 @@ const SpvAssembler = @import("spirv/Assembler.zig");
2828
2929const InstMap = std.AutoHashMapUnmanaged(Air.Inst.Index, IdRef);
3030
31pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
32 return comptime &.initEmpty();
33}
34
3135pub const zig_call_abi_ver = 3;
3236pub const big_int_bits = 32;
3337
......@@ -3380,6 +3384,10 @@ const NavGen = struct {
33803384 const zcu = self.pt.zcu;
33813385 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
33823386
3387 if (self.typeOf(bin_op.lhs).isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) {
3388 return self.fail("vector shift with scalar rhs", .{});
3389 }
3390
33833391 const base = try self.temporary(bin_op.lhs);
33843392 const shift = try self.temporary(bin_op.rhs);
33853393
......@@ -3866,6 +3874,10 @@ const NavGen = struct {
38663874 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
38673875 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
38683876
3877 if (self.typeOf(extra.lhs).isVector(zcu) and !self.typeOf(extra.rhs).isVector(zcu)) {
3878 return self.fail("vector shift with scalar rhs", .{});
3879 }
3880
38693881 const base = try self.temporary(extra.lhs);
38703882 const shift = try self.temporary(extra.rhs);
38713883
src/target.zig-4
......@@ -850,9 +850,5 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt
850850 .stage2_llvm => false,
851851 else => true,
852852 },
853 .all_vector_instructions => switch (backend) {
854 .stage2_x86_64 => true,
855 else => false,
856 },
857853 };
858854}