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 {...@@ -42,6 +42,7 @@ pub const Feature = enum {
42 scalarize_shl_sat,42 scalarize_shl_sat,
43 scalarize_xor,43 scalarize_xor,
44 scalarize_not,44 scalarize_not,
45 scalarize_bitcast,
45 scalarize_clz,46 scalarize_clz,
46 scalarize_ctz,47 scalarize_ctz,
47 scalarize_popcount,48 scalarize_popcount,
...@@ -76,7 +77,7 @@ pub const Feature = enum {...@@ -76,7 +77,7 @@ pub const Feature = enum {
76 scalarize_mul_add,77 scalarize_mul_add,
7778
78 /// Legalize (shift lhs, (splat rhs)) -> (shift lhs, rhs)79 /// Legalize (shift lhs, (splat rhs)) -> (shift lhs, rhs)
79 remove_shift_vector_rhs_splat,80 unsplat_shift_rhs,
80 /// Legalize reduce of a one element vector to a bitcast81 /// Legalize reduce of a one element vector to a bitcast
81 reduce_one_elem_to_bitcast,82 reduce_one_elem_to_bitcast,
8283
...@@ -121,6 +122,7 @@ pub const Feature = enum {...@@ -121,6 +122,7 @@ pub const Feature = enum {
121 .shl_sat => .scalarize_shl_sat,122 .shl_sat => .scalarize_shl_sat,
122 .xor => .scalarize_xor,123 .xor => .scalarize_xor,
123 .not => .scalarize_not,124 .not => .scalarize_not,
125 .bitcast => .scalarize_bitcast,
124 .clz => .scalarize_clz,126 .clz => .scalarize_clz,
125 .ctz => .scalarize_ctz,127 .ctz => .scalarize_ctz,
126 .popcount => .scalarize_popcount,128 .popcount => .scalarize_popcount,
...@@ -259,9 +261,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -259,9 +261,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
259 => |air_tag| done: {261 => |air_tag| done: {
260 const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op;262 const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op;
261 if (!l.typeOf(bin_op.rhs).isVector(zcu)) break :done;263 if (!l.typeOf(bin_op.rhs).isVector(zcu)) break :done;
262 if (l.features.contains(comptime .scalarize(air_tag))) {264 if (l.features.contains(.unsplat_shift_rhs)) {
263 continue :inst try l.scalarize(inst, .bin_op);
264 } else if (l.features.contains(.remove_shift_vector_rhs_splat)) {
265 if (bin_op.rhs.toInterned()) |rhs_ip_index| switch (ip.indexToKey(rhs_ip_index)) {265 if (bin_op.rhs.toInterned()) |rhs_ip_index| switch (ip.indexToKey(rhs_ip_index)) {
266 else => {},266 else => {},
267 .aggregate => |aggregate| switch (aggregate.storage) {267 .aggregate => |aggregate| switch (aggregate.storage) {
...@@ -282,6 +282,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -282,6 +282,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
282 }282 }
283 }283 }
284 }284 }
285 if (l.features.contains(comptime .scalarize(air_tag))) continue :inst try l.scalarize(inst, .bin_op);
285 },286 },
286 inline .not,287 inline .not,
287 .clz,288 .clz,
...@@ -302,8 +303,14 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -302,8 +303,14 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
302 const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op;303 const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op;
303 if (ty_op.ty.toType().isVector(zcu)) continue :inst try l.scalarize(inst, .ty_op);304 if (ty_op.ty.toType().isVector(zcu)) continue :inst try l.scalarize(inst, .ty_op);
304 },305 },
305 .bitcast,306 inline .bitcast,
306 => {},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 },
307 .block,314 .block,
308 .loop,315 .loop,
309 => {316 => {
src/Sema.zig+47-140
...@@ -10165,16 +10165,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -10165,16 +10165,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
10165 try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), ptr_src);10165 try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), ptr_src);
10166 try sema.validateRuntimeValue(block, ptr_src, operand);10166 try sema.validateRuntimeValue(block, ptr_src, operand);
10167 try sema.checkLogicalPtrOperation(block, ptr_src, ptr_ty);10167 try sema.checkLogicalPtrOperation(block, ptr_src, ptr_ty);
10168 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {10168 return block.addBitCast(dest_ty, operand);
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);
10178}10169}
1017910170
10180fn zirFieldVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {10171fn 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...@@ -10640,17 +10631,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
10640 if (dst_bits >= src_bits) {10631 if (dst_bits >= src_bits) {
10641 return sema.coerce(block, dest_ty, operand, operand_src);10632 return sema.coerce(block, dest_ty, operand, operand_src);
10642 }10633 }
10643 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {10634 return block.addTyOp(.fptrunc, dest_ty, operand);
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);
10654}10635}
1065510636
10656fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {10637fn 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...@@ -20722,16 +20703,7 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
20722 .storage = .{ .elems = new_elems },20703 .storage = .{ .elems = new_elems },
20723 } }));20704 } }));
20724 }20705 }
20725 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {20706 return block.addBitCast(dest_ty, operand);
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);
20735}20707}
2073620708
20737fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {20709fn 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...@@ -22327,42 +22299,23 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
22327 .storage = .{ .repeated_elem = (try pt.intValue(dest_scalar_ty, 0)).toIntern() },22299 .storage = .{ .repeated_elem = (try pt.intValue(dest_scalar_ty, 0)).toIntern() },
22328 } }));22300 } }));
22329 }22301 }
22330 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {22302 const result = try block.addTyOp(if (block.float_mode == .optimized) .int_from_float_optimized else .int_from_float, dest_ty, operand);
22331 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()) {
22332 if (block.wantSafety()) {22304 const back = try block.addTyOp(.float_from_int, operand_ty, result);
22333 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);
22334 const diff = try block.addBinOp(if (block.float_mode == .optimized) .sub_optimized else .sub, operand, back);22306 const ok = if (is_vector) ok: {
22335 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);
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);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);
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);22309 const ok = try block.addBinOp(.bit_and, ok_pos, ok_neg);
22338 const ok = try block.addBinOp(.bit_and, ok_pos, ok_neg);22310 break :ok try block.addReduce(ok, .And);
22339 break :ok try block.addReduce(ok, .And);22311 } else ok: {
22340 } 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()));
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()));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()));
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()));22314 break :ok try block.addBinOp(.bool_and, ok_pos, ok_neg);
22343 break :ok try block.addBinOp(.bool_and, ok_pos, ok_neg);22315 };
22344 };22316 try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds);
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;
22364 }22317 }
22365 return block.addAggregateInit(dest_ty, new_elems);22318 return result;
22366}22319}
2236722320
22368fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {22321fn 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...@@ -22377,7 +22330,6 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
22377 const operand_ty = sema.typeOf(operand);22330 const operand_ty = sema.typeOf(operand);
2237822331
22379 try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, src, operand_src);22332 try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, src, operand_src);
22380 const is_vector = dest_ty.zigTypeTag(zcu) == .vector;
2238122333
22382 const dest_scalar_ty = dest_ty.scalarType(zcu);22334 const dest_scalar_ty = dest_ty.scalarType(zcu);
22383 const operand_scalar_ty = operand_ty.scalarType(zcu);22335 const operand_scalar_ty = operand_ty.scalarType(zcu);
...@@ -22393,17 +22345,7 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -22393,17 +22345,7 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
22393 }22345 }
2239422346
22395 try sema.requireRuntimeBlock(block, src, operand_src);22347 try sema.requireRuntimeBlock(block, src, operand_src);
22396 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {22348 return block.addTyOp(.float_from_int, dest_ty, operand);
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);
22407}22349}
2240822350
22409fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {22351fn 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!...@@ -22473,69 +22415,34 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
22473 }22415 }
22474 try sema.requireRuntimeBlock(block, src, operand_src);22416 try sema.requireRuntimeBlock(block, src, operand_src);
22475 try sema.checkLogicalPtrOperation(block, src, ptr_ty);22417 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);
22508 if (block.wantSafety() and (try elem_ty.hasRuntimeBitsSema(pt) or elem_ty.zigTypeTag(zcu) == .@"fn")) {22418 if (block.wantSafety() and (try elem_ty.hasRuntimeBitsSema(pt) or elem_ty.zigTypeTag(zcu) == .@"fn")) {
22509 for (0..len) |i| {22419 if (!ptr_ty.isAllowzeroPtr(zcu)) {
22510 const idx_ref = try pt.intRef(.usize, i);22420 const is_non_zero = if (is_vector) all_non_zero: {
22511 const elem_coerced = try block.addBinOp(.array_elem_val, operand_coerced, idx_ref);22421 const zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern());
22512 if (!ptr_ty.isAllowzeroPtr(zcu)) {22422 const is_non_zero = try block.addCmpVector(operand_coerced, zero_usize, .neq);
22513 const is_non_zero = try block.addBinOp(.cmp_neq, elem_coerced, .zero_usize);22423 break :all_non_zero try block.addReduce(is_non_zero, .And);
22514 try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null);22424 } else try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize);
22515 }22425 try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null);
22516 if (ptr_align.compare(.gt, .@"1")) {22426 }
22517 const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1;22427 if (ptr_align.compare(.gt, .@"1")) {
22518 const align_mask = Air.internedToRef((try pt.intValue(22428 const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1;
22519 .usize,22429 const align_mask = Air.internedToRef((try sema.splat(operand_ty, try pt.intValue(
22520 if (elem_ty.fnPtrMaskOrNull(zcu)) |mask|22430 .usize,
22521 align_bytes_minus_1 & mask22431 if (elem_ty.fnPtrMaskOrNull(zcu)) |mask|
22522 else22432 align_bytes_minus_1 & mask
22523 align_bytes_minus_1,22433 else
22524 )).toIntern());22434 align_bytes_minus_1,
22525 const remainder = try block.addBinOp(.bit_and, elem_coerced, align_mask);22435 ))).toIntern());
22526 const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize);22436 const remainder = try block.addBinOp(.bit_and, operand_coerced, align_mask);
22527 try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment);22437 const is_aligned = if (is_vector) all_aligned: {
22528 }22438 const splat_zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern());
22529 }22439 const is_aligned = try block.addCmpVector(remainder, splat_zero_usize, .eq);
22530 }22440 break :all_aligned try block.addReduce(is_aligned, .And);
2253122441 } else try block.addBinOp(.cmp_eq, remainder, .zero_usize);
22532 const new_elems = try sema.arena.alloc(Air.Inst.Ref, len);22442 try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment);
22533 for (new_elems, 0..) |*new_elem, i| {22443 }
22534 const idx_ref = try pt.intRef(.usize, i);22444 }
22535 const old_elem = try block.addBinOp(.array_elem_val, operand_coerced, idx_ref);22445 return block.addBitCast(dest_ty, operand_coerced);
22536 new_elem.* = try block.addBitCast(ptr_ty, old_elem);
22537 }
22538 return block.addAggregateInit(dest_ty, new_elems);
22539}22446}
2254022447
22541fn ptrFromIntVal(22448fn ptrFromIntVal(
src/Zcu.zig-9
...@@ -3840,15 +3840,6 @@ pub const Feature = enum {...@@ -3840,15 +3840,6 @@ pub const Feature = enum {
3840 safety_checked_instructions,3840 safety_checked_instructions,
3841 /// If the backend supports running from another thread.3841 /// If the backend supports running from another thread.
3842 separate_thread,3842 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,
3852};3843};
38533844
3854pub fn backendSupportsFeature(zcu: *const Zcu, comptime feature: Feature) bool {3845pub 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;...@@ -40,6 +40,10 @@ const gp = abi.RegisterClass.gp;
4040
41const InnerError = CodeGenError || error{OutOfRegisters};41const InnerError = CodeGenError || error{OutOfRegisters};
4242
43pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
44 return comptime &.initEmpty();
45}
46
43gpa: Allocator,47gpa: Allocator,
44pt: Zcu.PerThread,48pt: Zcu.PerThread,
45air: Air,49air: Air,
...@@ -2261,12 +2265,13 @@ fn shiftExact(...@@ -2261,12 +2265,13 @@ fn shiftExact(
2261 rhs_ty: Type,2265 rhs_ty: Type,
2262 maybe_inst: ?Air.Inst.Index,2266 maybe_inst: ?Air.Inst.Index,
2263) InnerError!MCValue {2267) InnerError!MCValue {
2264 _ = rhs_ty;
2265
2266 const pt = self.pt;2268 const pt = self.pt;
2267 const zcu = pt.zcu;2269 const zcu = pt.zcu;
2268 switch (lhs_ty.zigTypeTag(zcu)) {2270 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", .{}),
2270 .int => {2275 .int => {
2271 const int_info = lhs_ty.intInfo(zcu);2276 const int_info = lhs_ty.intInfo(zcu);
2272 if (int_info.bits <= 64) {2277 if (int_info.bits <= 64) {
...@@ -2317,7 +2322,10 @@ fn shiftNormal(...@@ -2317,7 +2322,10 @@ fn shiftNormal(
2317 const pt = self.pt;2322 const pt = self.pt;
2318 const zcu = pt.zcu;2323 const zcu = pt.zcu;
2319 switch (lhs_ty.zigTypeTag(zcu)) {2324 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", .{}),
2321 .int => {2329 .int => {
2322 const int_info = lhs_ty.intInfo(zcu);2330 const int_info = lhs_ty.intInfo(zcu);
2323 if (int_info.bits <= 64) {2331 if (int_info.bits <= 64) {
...@@ -2874,7 +2882,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!void {...@@ -2874,7 +2882,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!void {
2874 const overflow_bit_offset = @as(u32, @intCast(tuple_ty.structFieldOffset(1, zcu)));2882 const overflow_bit_offset = @as(u32, @intCast(tuple_ty.structFieldOffset(1, zcu)));
28752883
2876 switch (lhs_ty.zigTypeTag(zcu)) {2884 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", .{}),
2878 .int => {2889 .int => {
2879 const int_info = lhs_ty.intInfo(zcu);2890 const int_info = lhs_ty.intInfo(zcu);
2880 if (int_info.bits <= 64) {2891 if (int_info.bits <= 64) {
...@@ -2993,8 +3004,14 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!void {...@@ -2993,8 +3004,14 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!void {
2993}3004}
29943005
2995fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!void {3006fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!void {
3007 const zcu = self.pt.zcu;
2996 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;3008 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});
2998 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });3015 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2999}3016}
30003017
src/arch/arm/CodeGen.zig+23-4
...@@ -41,6 +41,10 @@ const gp = abi.RegisterClass.gp;...@@ -41,6 +41,10 @@ const gp = abi.RegisterClass.gp;
4141
42const InnerError = CodeGenError || error{OutOfRegisters};42const InnerError = CodeGenError || error{OutOfRegisters};
4343
44pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
45 return comptime &.initEmpty();
46}
47
44gpa: Allocator,48gpa: Allocator,
45pt: Zcu.PerThread,49pt: Zcu.PerThread,
46air: Air,50air: Air,
...@@ -1857,7 +1861,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1857,7 +1861,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1857 const overflow_bit_offset: u32 = @intCast(tuple_ty.structFieldOffset(1, zcu));1861 const overflow_bit_offset: u32 = @intCast(tuple_ty.structFieldOffset(1, zcu));
18581862
1859 switch (lhs_ty.zigTypeTag(zcu)) {1863 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", .{}),
1861 .int => {1868 .int => {
1862 const int_info = lhs_ty.intInfo(zcu);1869 const int_info = lhs_ty.intInfo(zcu);
1863 if (int_info.bits <= 32) {1870 if (int_info.bits <= 32) {
...@@ -1978,8 +1985,14 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1978,8 +1985,14 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1978}1985}
19791986
1980fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {1987fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
1988 const zcu = self.pt.zcu;
1981 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;1989 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});
1983 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1996 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1984}1997}
19851998
...@@ -3788,7 +3801,10 @@ fn shiftExact(...@@ -3788,7 +3801,10 @@ fn shiftExact(
3788 const pt = self.pt;3801 const pt = self.pt;
3789 const zcu = pt.zcu;3802 const zcu = pt.zcu;
3790 switch (lhs_ty.zigTypeTag(zcu)) {3803 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", .{}),
3792 .int => {3808 .int => {
3793 const int_info = lhs_ty.intInfo(zcu);3809 const int_info = lhs_ty.intInfo(zcu);
3794 if (int_info.bits <= 32) {3810 if (int_info.bits <= 32) {
...@@ -3828,7 +3844,10 @@ fn shiftNormal(...@@ -3828,7 +3844,10 @@ fn shiftNormal(
3828 const pt = self.pt;3844 const pt = self.pt;
3829 const zcu = pt.zcu;3845 const zcu = pt.zcu;
3830 switch (lhs_ty.zigTypeTag(zcu)) {3846 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", .{}),
3832 .int => {3851 .int => {
3833 const int_info = lhs_ty.intInfo(zcu);3852 const int_info = lhs_ty.intInfo(zcu);
3834 if (int_info.bits <= 32) {3853 if (int_info.bits <= 32) {
src/arch/powerpc/CodeGen.zig+4
...@@ -10,6 +10,10 @@ const Zcu = @import("../../Zcu.zig");...@@ -10,6 +10,10 @@ const Zcu = @import("../../Zcu.zig");
10const assert = std.debug.assert;10const assert = std.debug.assert;
11const log = std.log.scoped(.codegen);11const log = std.log.scoped(.codegen);
1212
13pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
14 return comptime &.initEmpty();
15}
16
13pub fn generate(17pub fn generate(
14 bin_file: *link.File,18 bin_file: *link.File,
15 pt: Zcu.PerThread,19 pt: Zcu.PerThread,
src/arch/riscv64/CodeGen.zig+19-2
...@@ -51,6 +51,10 @@ const Instruction = encoding.Instruction;...@@ -51,6 +51,10 @@ const Instruction = encoding.Instruction;
5151
52const InnerError = CodeGenError || error{OutOfRegisters};52const InnerError = CodeGenError || error{OutOfRegisters};
5353
54pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
55 return comptime &.initEmpty();
56}
57
54pt: Zcu.PerThread,58pt: Zcu.PerThread,
55air: Air,59air: Air,
56liveness: Air.Liveness,60liveness: Air.Liveness,
...@@ -2764,6 +2768,7 @@ fn genBinOp(...@@ -2764,6 +2768,7 @@ fn genBinOp(
2764 .shl,2768 .shl,
2765 .shl_exact,2769 .shl_exact,
2766 => {2770 => {
2771 if (lhs_ty.isVector(zcu) and !rhs_ty.isVector(zcu)) return func.fail("TODO: vector shift with scalar rhs", .{});
2767 if (bit_size > 64) return func.fail("TODO: genBinOp shift > 64 bits, {}", .{bit_size});2772 if (bit_size > 64) return func.fail("TODO: genBinOp shift > 64 bits, {}", .{bit_size});
2768 try func.truncateRegister(rhs_ty, rhs_reg);2773 try func.truncateRegister(rhs_ty, rhs_reg);
27692774
...@@ -3248,8 +3253,14 @@ fn airMulWithOverflow(func: *Func, inst: Air.Inst.Index) !void {...@@ -3248,8 +3253,14 @@ fn airMulWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
3248}3253}
32493254
3250fn airShlWithOverflow(func: *Func, inst: Air.Inst.Index) !void {3255fn airShlWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
3256 const zcu = func.pt.zcu;
3251 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;3257 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", .{});
3253 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });3264 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
3254}3265}
32553266
...@@ -3266,8 +3277,14 @@ fn airMulSat(func: *Func, inst: Air.Inst.Index) !void {...@@ -3266,8 +3277,14 @@ fn airMulSat(func: *Func, inst: Air.Inst.Index) !void {
3266}3277}
32673278
3268fn airShlSat(func: *Func, inst: Air.Inst.Index) !void {3279fn airShlSat(func: *Func, inst: Air.Inst.Index) !void {
3280 const zcu = func.pt.zcu;
3269 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;3281 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", .{});
3271 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });3288 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
3272}3289}
32733290
src/arch/sparc64/CodeGen.zig+23-4
...@@ -41,6 +41,10 @@ const Self = @This();...@@ -41,6 +41,10 @@ const Self = @This();
4141
42const InnerError = CodeGenError || error{OutOfRegisters};42const InnerError = CodeGenError || error{OutOfRegisters};
4343
44pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
45 return comptime &.initEmpty();
46}
47
44const RegisterView = enum(u1) {48const RegisterView = enum(u1) {
45 caller,49 caller,
46 callee,50 callee,
...@@ -2270,8 +2274,14 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {...@@ -2270,8 +2274,14 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
2270}2274}
22712275
2272fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {2276fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
2277 const zcu = self.pt.zcu;
2273 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;2278 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});
2275 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2285 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2276}2286}
22772287
...@@ -2287,7 +2297,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2287,7 +2297,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2287 const rhs_ty = self.typeOf(extra.rhs);2297 const rhs_ty = self.typeOf(extra.rhs);
22882298
2289 switch (lhs_ty.zigTypeTag(zcu)) {2299 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", .{}),
2291 .int => {2304 .int => {
2292 const int_info = lhs_ty.intInfo(zcu);2305 const int_info = lhs_ty.intInfo(zcu);
2293 if (int_info.bits <= 64) {2306 if (int_info.bits <= 64) {
...@@ -3002,7 +3015,10 @@ fn binOp(...@@ -3002,7 +3015,10 @@ fn binOp(
30023015
3003 // Truncate if necessary3016 // Truncate if necessary
3004 switch (lhs_ty.zigTypeTag(zcu)) {3017 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", .{}),
3006 .int => {3022 .int => {
3007 const int_info = lhs_ty.intInfo(zcu);3023 const int_info = lhs_ty.intInfo(zcu);
3008 if (int_info.bits <= 64) {3024 if (int_info.bits <= 64) {
...@@ -3024,7 +3040,10 @@ fn binOp(...@@ -3024,7 +3040,10 @@ fn binOp(
3024 .shr_exact,3040 .shr_exact,
3025 => {3041 => {
3026 switch (lhs_ty.zigTypeTag(zcu)) {3042 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", .{}),
3028 .int => {3047 .int => {
3029 const int_info = lhs_ty.intInfo(zcu);3048 const int_info = lhs_ty.intInfo(zcu);
3030 if (int_info.bits <= 64) {3049 if (int_info.bits <= 64) {
src/arch/wasm/CodeGen.zig+26-5
...@@ -31,6 +31,10 @@ const libcFloatSuffix = target_util.libcFloatSuffix;...@@ -31,6 +31,10 @@ const libcFloatSuffix = target_util.libcFloatSuffix;
31const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev;31const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev;
32const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev;32const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev;
3333
34pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
35 return comptime &.initEmpty();
36}
37
34/// Reference to the function declaration the code38/// Reference to the function declaration the code
35/// section belongs to39/// section belongs to
36owner_nav: InternPool.Nav.Index,40owner_nav: InternPool.Nav.Index,
...@@ -2638,6 +2642,10 @@ fn airBinOp(cg: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {...@@ -2638,6 +2642,10 @@ fn airBinOp(cg: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
2638 // For big integers we can ignore this as we will call into compiler-rt which handles this.2642 // For big integers we can ignore this as we will call into compiler-rt which handles this.
2639 const result = switch (op) {2643 const result = switch (op) {
2640 .shr, .shl => result: {2644 .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
2641 const lhs_wasm_bits = toWasmBits(@intCast(lhs_ty.bitSize(zcu))) orelse {2649 const lhs_wasm_bits = toWasmBits(@intCast(lhs_ty.bitSize(zcu))) orelse {
2642 return cg.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)});2650 return cg.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)});
2643 };2651 };
...@@ -3055,8 +3063,12 @@ fn airWrapBinOp(cg: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {...@@ -3055,8 +3063,12 @@ fn airWrapBinOp(cg: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
3055 const lhs_ty = cg.typeOf(bin_op.lhs);3063 const lhs_ty = cg.typeOf(bin_op.lhs);
3056 const rhs_ty = cg.typeOf(bin_op.rhs);3064 const rhs_ty = cg.typeOf(bin_op.rhs);
30573065
3058 if (lhs_ty.zigTypeTag(zcu) == .vector or rhs_ty.zigTypeTag(zcu) == .vector) {3066 if (lhs_ty.isVector(zcu)) {
3059 return cg.fail("TODO: Implement wrapping arithmetic for vectors", .{});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 }
3060 }3072 }
30613073
3062 // For certain operations, such as shifting, the types are different.3074 // For certain operations, such as shifting, the types are different.
...@@ -6067,13 +6079,17 @@ fn airShlWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6067,13 +6079,17 @@ fn airShlWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6067 const ty = cg.typeOf(extra.lhs);6079 const ty = cg.typeOf(extra.lhs);
6068 const rhs_ty = cg.typeOf(extra.rhs);6080 const rhs_ty = cg.typeOf(extra.rhs);
60696081
6070 if (ty.zigTypeTag(zcu) == .vector) {6082 if (ty.isVector(zcu)) {
6071 return cg.fail("TODO: Implement overflow arithmetic for vectors", .{});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 }
6072 }6088 }
60736089
6074 const int_info = ty.intInfo(zcu);6090 const int_info = ty.intInfo(zcu);
6075 const wasm_bits = toWasmBits(int_info.bits) orelse {6091 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});
6077 };6093 };
60786094
6079 // Ensure rhs is coerced to lhs as they must have the same WebAssembly types6095 // 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 {...@@ -6994,6 +7010,11 @@ fn airShlSat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
69947010
6995 const pt = cg.pt;7011 const pt = cg.pt;
6996 const zcu = pt.zcu;7012 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
6997 const ty = cg.typeOfIndex(inst);7018 const ty = cg.typeOfIndex(inst);
6998 const int_info = ty.intInfo(zcu);7019 const int_info = ty.intInfo(zcu);
6999 const is_signed = int_info.signedness == .signed;7020 const is_signed = int_info.signedness == .signed;
src/arch/x86_64/CodeGen.zig+2-2
...@@ -32,7 +32,7 @@ const FrameIndex = bits.FrameIndex;...@@ -32,7 +32,7 @@ const FrameIndex = bits.FrameIndex;
3232
33const InnerError = codegen.CodeGenError || error{OutOfRegisters};33const 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 {
36 @setEvalBranchQuota(1_200);36 @setEvalBranchQuota(1_200);
37 return switch (target.ofmt == .coff) {37 return switch (target.ofmt == .coff) {
38 inline false, true => |use_old| comptime &.init(.{38 inline false, true => |use_old| comptime &.init(.{
...@@ -86,7 +86,7 @@ pub inline fn legalizeFeatures(target: *const std.Target) *const Air.Legalize.Fe...@@ -86,7 +86,7 @@ pub inline fn legalizeFeatures(target: *const std.Target) *const Air.Legalize.Fe
86 .scalarize_float_from_int = use_old,86 .scalarize_float_from_int = use_old,
87 .scalarize_mul_add = use_old,87 .scalarize_mul_add = use_old,
8888
89 .remove_shift_vector_rhs_splat = false,89 .unsplat_shift_rhs = false,
90 .reduce_one_elem_to_bitcast = true,90 .reduce_one_elem_to_bitcast = true,
91 }),91 }),
92 };92 };
src/codegen.zig+3-6
...@@ -52,7 +52,7 @@ fn importBackend(comptime backend: std.builtin.CompilerBackend) type {...@@ -52,7 +52,7 @@ fn importBackend(comptime backend: std.builtin.CompilerBackend) type {
52pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) *const Air.Legalize.Features {52pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) *const Air.Legalize.Features {
53 const zcu = pt.zcu;53 const zcu = pt.zcu;
54 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;54 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)) {
56 else => unreachable,56 else => unreachable,
57 inline .stage2_llvm,57 inline .stage2_llvm,
58 .stage2_c,58 .stage2_c,
...@@ -65,11 +65,8 @@ pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) *con...@@ -65,11 +65,8 @@ pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) *con
65 .stage2_sparc64,65 .stage2_sparc64,
66 .stage2_spirv64,66 .stage2_spirv64,
67 .stage2_powerpc,67 .stage2_powerpc,
68 => |backend| {68 => |backend| importBackend(backend).legalizeFeatures(target),
69 const Backend = importBackend(backend);69 };
70 return if (@hasDecl(Backend, "legalizeFeatures")) Backend.legalizeFeatures(target) else comptime &.initEmpty();
71 },
72 }
73}70}
7471
75pub fn generateFunction(72pub fn generateFunction(
src/codegen/c.zig+6-2
...@@ -20,6 +20,10 @@ const Alignment = InternPool.Alignment;...@@ -20,6 +20,10 @@ const Alignment = InternPool.Alignment;
20const BigIntLimb = std.math.big.Limb;20const BigIntLimb = std.math.big.Limb;
21const BigInt = std.math.big.int;21const BigInt = std.math.big.int;
2222
23pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
24 return comptime &.initEmpty();
25}
26
23pub const CType = @import("c/Type.zig");27pub const CType = @import("c/Type.zig");
2428
25pub const CValue = union(enum) {29pub const CValue = union(enum) {
...@@ -4179,7 +4183,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:...@@ -4179,7 +4183,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
4179 try v.elem(f, w);4183 try v.elem(f, w);
4180 try w.writeAll(", ");4184 try w.writeAll(", ");
4181 try f.writeCValue(w, rhs, .FunctionArgument);4185 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);
4183 try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);4187 try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
4184 try w.writeAll(");\n");4188 try w.writeAll(");\n");
4185 try v.end(f, inst, w);4189 try v.end(f, inst, w);
...@@ -6536,7 +6540,7 @@ fn airBinBuiltinCall(...@@ -6536,7 +6540,7 @@ fn airBinBuiltinCall(
6536 try v.elem(f, writer);6540 try v.elem(f, writer);
6537 try writer.writeAll(", ");6541 try writer.writeAll(", ");
6538 try f.writeCValue(writer, rhs, .FunctionArgument);6542 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);
6540 try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info);6544 try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info);
6541 try writer.writeAll(");\n");6545 try writer.writeAll(");\n");
6542 try v.end(f, inst, writer);6546 try v.end(f, inst, writer);
src/codegen/llvm.zig+23-7
...@@ -36,6 +36,10 @@ const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev;...@@ -36,6 +36,10 @@ const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev;
3636
37const Error = error{ OutOfMemory, CodegenFail };37const Error = error{ OutOfMemory, CodegenFail };
3838
39pub inline fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
40 return comptime &.initEmpty();
41}
42
39fn subArchName(features: std.Target.Cpu.Feature.Set, arch: anytype, mappings: anytype) ?[]const u8 {43fn subArchName(features: std.Target.Cpu.Feature.Set, arch: anytype, mappings: anytype) ?[]const u8 {
40 inline for (mappings) |mapping| {44 inline for (mappings) |mapping| {
41 if (arch.featureSetHas(features, mapping[0])) return mapping[1];45 if (arch.featureSetHas(features, mapping[0])) return mapping[1];
...@@ -8923,6 +8927,8 @@ pub const FuncGen = struct {...@@ -8923,6 +8927,8 @@ pub const FuncGen = struct {
8923 const rhs = try self.resolveInst(extra.rhs);8927 const rhs = try self.resolveInst(extra.rhs);
89248928
8925 const lhs_ty = self.typeOf(extra.lhs);8929 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", .{});
8926 const lhs_scalar_ty = lhs_ty.scalarType(zcu);8932 const lhs_scalar_ty = lhs_ty.scalarType(zcu);
89278933
8928 const dest_ty = self.typeOfIndex(inst);8934 const dest_ty = self.typeOfIndex(inst);
...@@ -8992,6 +8998,8 @@ pub const FuncGen = struct {...@@ -8992,6 +8998,8 @@ pub const FuncGen = struct {
8992 const rhs = try self.resolveInst(bin_op.rhs);8998 const rhs = try self.resolveInst(bin_op.rhs);
89938999
8994 const lhs_ty = self.typeOf(bin_op.lhs);9000 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", .{});
8995 const lhs_scalar_ty = lhs_ty.scalarType(zcu);9003 const lhs_scalar_ty = lhs_ty.scalarType(zcu);
89969004
8997 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), "");9005 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), "");
...@@ -9003,14 +9011,17 @@ pub const FuncGen = struct {...@@ -9003,14 +9011,17 @@ pub const FuncGen = struct {
90039011
9004 fn airShl(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {9012 fn airShl(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
9005 const o = self.ng.object;9013 const o = self.ng.object;
9014 const zcu = o.pt.zcu;
9006 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;9015 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
90079016
9008 const lhs = try self.resolveInst(bin_op.lhs);9017 const lhs = try self.resolveInst(bin_op.lhs);
9009 const rhs = try self.resolveInst(bin_op.rhs);9018 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), "");
9014 return self.wip.bin(.shl, lhs, casted_rhs, "");9025 return self.wip.bin(.shl, lhs, casted_rhs, "");
9015 }9026 }
90169027
...@@ -9029,6 +9040,8 @@ pub const FuncGen = struct {...@@ -9029,6 +9040,8 @@ pub const FuncGen = struct {
9029 const llvm_lhs_scalar_ty = llvm_lhs_ty.scalarType(&o.builder);9040 const llvm_lhs_scalar_ty = llvm_lhs_ty.scalarType(&o.builder);
90309041
9031 const rhs_ty = self.typeOf(bin_op.rhs);9042 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", .{});
9032 const rhs_info = rhs_ty.intInfo(zcu);9045 const rhs_info = rhs_ty.intInfo(zcu);
9033 assert(rhs_info.signedness == .unsigned);9046 assert(rhs_info.signedness == .unsigned);
9034 const llvm_rhs_ty = try o.lowerType(rhs_ty);9047 const llvm_rhs_ty = try o.lowerType(rhs_ty);
...@@ -9101,6 +9114,8 @@ pub const FuncGen = struct {...@@ -9101,6 +9114,8 @@ pub const FuncGen = struct {
9101 const rhs = try self.resolveInst(bin_op.rhs);9114 const rhs = try self.resolveInst(bin_op.rhs);
91029115
9103 const lhs_ty = self.typeOf(bin_op.lhs);9116 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", .{});
9104 const lhs_scalar_ty = lhs_ty.scalarType(zcu);9119 const lhs_scalar_ty = lhs_ty.scalarType(zcu);
91059120
9106 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), "");9121 const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), "");
...@@ -9255,8 +9270,6 @@ pub const FuncGen = struct {...@@ -9255,8 +9270,6 @@ pub const FuncGen = struct {
9255 const operand_ty = self.typeOf(ty_op.operand);9270 const operand_ty = self.typeOf(ty_op.operand);
9256 const dest_ty = self.typeOfIndex(inst);9271 const dest_ty = self.typeOfIndex(inst);
9257 const target = zcu.getTarget();9272 const target = zcu.getTarget();
9258 const dest_bits = dest_ty.floatBits(target);
9259 const src_bits = operand_ty.floatBits(target);
92609273
9261 if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) {9274 if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) {
9262 return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty), "");9275 return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty), "");
...@@ -9264,6 +9277,8 @@ pub const FuncGen = struct {...@@ -9264,6 +9277,8 @@ pub const FuncGen = struct {
9264 const operand_llvm_ty = try o.lowerType(operand_ty);9277 const operand_llvm_ty = try o.lowerType(operand_ty);
9265 const dest_llvm_ty = try o.lowerType(dest_ty);9278 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);
9267 const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{9282 const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{
9268 compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits),9283 compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits),
9269 });9284 });
...@@ -9348,11 +9363,12 @@ pub const FuncGen = struct {...@@ -9348,11 +9363,12 @@ pub const FuncGen = struct {
9348 return self.wip.conv(.unsigned, operand, llvm_dest_ty, "");9363 return self.wip.conv(.unsigned, operand, llvm_dest_ty, "");
9349 }9364 }
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)) {
9352 return self.wip.cast(.inttoptr, operand, llvm_dest_ty, "");9369 return self.wip.cast(.inttoptr, operand, llvm_dest_ty, "");
9353 }9370 }
93549371 if (operand_scalar_ty.isPtrAtRuntime(zcu) and inst_scalar_ty.zigTypeTag(zcu) == .int) {
9355 if (operand_ty.isPtrAtRuntime(zcu) and inst_ty.zigTypeTag(zcu) == .int) {
9356 return self.wip.cast(.ptrtoint, operand, llvm_dest_ty, "");9372 return self.wip.cast(.ptrtoint, operand, llvm_dest_ty, "");
9357 }9373 }
93589374
src/codegen/spirv.zig+12
...@@ -28,6 +28,10 @@ const SpvAssembler = @import("spirv/Assembler.zig");...@@ -28,6 +28,10 @@ const SpvAssembler = @import("spirv/Assembler.zig");
2828
29const InstMap = std.AutoHashMapUnmanaged(Air.Inst.Index, IdRef);29const 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
31pub const zig_call_abi_ver = 3;35pub const zig_call_abi_ver = 3;
32pub const big_int_bits = 32;36pub const big_int_bits = 32;
3337
...@@ -3380,6 +3384,10 @@ const NavGen = struct {...@@ -3380,6 +3384,10 @@ const NavGen = struct {
3380 const zcu = self.pt.zcu;3384 const zcu = self.pt.zcu;
3381 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;3385 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
3383 const base = try self.temporary(bin_op.lhs);3391 const base = try self.temporary(bin_op.lhs);
3384 const shift = try self.temporary(bin_op.rhs);3392 const shift = try self.temporary(bin_op.rhs);
33853393
...@@ -3866,6 +3874,10 @@ const NavGen = struct {...@@ -3866,6 +3874,10 @@ const NavGen = struct {
3866 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;3874 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
3867 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;3875 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
3869 const base = try self.temporary(extra.lhs);3881 const base = try self.temporary(extra.lhs);
3870 const shift = try self.temporary(extra.rhs);3882 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...@@ -850,9 +850,5 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt
850 .stage2_llvm => false,850 .stage2_llvm => false,
851 else => true,851 else => true,
852 },852 },
853 .all_vector_instructions => switch (backend) {
854 .stage2_x86_64 => true,
855 else => false,
856 },
857 };853 };
858}854}