Skip to content

Commit 6198f7a

Browse files
committed
Sema: remove all_vector_instructions logic
Backends can instead ask legalization on a per-instruction basis.
1 parent b4a0a08 commit 6198f7a

File tree

15 files changed

+224
-197
lines changed

15 files changed

+224
-197
lines changed

src/Air/Legalize.zig

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 47 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -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

1018010171
fn 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

1065610637
fn 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

2073720709
fn 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

2236822321
fn 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

2240922351
fn 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

2254122448
fn ptrFromIntVal(

src/Zcu.zig

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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

38543845
pub fn backendSupportsFeature(zcu: *const Zcu, comptime feature: Feature) bool {

0 commit comments

Comments
 (0)