authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-06-15 11:36:15-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-06-15 11:42:03-04:00
log6e72026e3b04586cf44deadeddeb8bf44a42ee99
tree03524f47e38bd7d150bff083b52aca7c7700073a
parent1ca213dab02db42c63a6b7e191044c0124f9bfb2

Legalize: make the feature set comptime-known in zig1

This allows legalizations to be added that aren't used by zig1 without affecting the size of zig1.

2 files changed, 78 insertions(+), 42 deletions(-)

src/Air/Legalize.zig+65-36
...@@ -1,7 +1,36 @@...@@ -1,7 +1,36 @@
1pt: Zcu.PerThread,1pt: Zcu.PerThread,
2air_instructions: std.MultiArrayList(Air.Inst),2air_instructions: std.MultiArrayList(Air.Inst),
3air_extra: std.ArrayListUnmanaged(u32),3air_extra: std.ArrayListUnmanaged(u32),
4features: *const Features,4features: if (switch (dev.env) {
5 .bootstrap => @import("../codegen/c.zig").legalizeFeatures(undefined),
6 else => null,
7}) |bootstrap_features| struct {
8 fn init(features: *const Features) @This() {
9 assert(features.eql(bootstrap_features.*));
10 return .{};
11 }
12 /// `inline` to propagate comptime-known result.
13 inline fn has(_: @This(), comptime feature: Feature) bool {
14 return comptime bootstrap_features.contains(feature);
15 }
16 /// `inline` to propagate comptime-known result.
17 fn hasAny(_: @This(), comptime features: []const Feature) bool {
18 return comptime !bootstrap_features.intersectWith(.initMany(features)).eql(.initEmpty());
19 }
20} else struct {
21 features: *const Features,
22 /// `inline` to propagate whether `dev.check` returns.
23 inline fn init(features: *const Features) @This() {
24 dev.check(.legalize);
25 return .{ .features = features };
26 }
27 fn has(rt: @This(), comptime feature: Feature) bool {
28 return rt.features.contains(feature);
29 }
30 fn hasAny(rt: @This(), comptime features: []const Feature) bool {
31 return !rt.features.intersectWith(comptime .initMany(features)).eql(comptime .initEmpty());
32 }
33},
534
6pub const Feature = enum {35pub const Feature = enum {
7 scalarize_add,36 scalarize_add,
...@@ -199,7 +228,7 @@ pub const Feature = enum {...@@ -199,7 +228,7 @@ pub const Feature = enum {
199 .float_from_int => .scalarize_float_from_int,228 .float_from_int => .scalarize_float_from_int,
200 .shuffle_one => .scalarize_shuffle_one,229 .shuffle_one => .scalarize_shuffle_one,
201 .shuffle_two => .scalarize_shuffle_two,230 .shuffle_two => .scalarize_shuffle_two,
202 .select => .scalarize_selects,231 .select => .scalarize_select,
203 .mul_add => .scalarize_mul_add,232 .mul_add => .scalarize_mul_add,
204 };233 };
205 }234 }
...@@ -210,13 +239,12 @@ pub const Features = std.enums.EnumSet(Feature);...@@ -210,13 +239,12 @@ pub const Features = std.enums.EnumSet(Feature);
210pub const Error = std.mem.Allocator.Error;239pub const Error = std.mem.Allocator.Error;
211240
212pub fn legalize(air: *Air, pt: Zcu.PerThread, features: *const Features) Error!void {241pub fn legalize(air: *Air, pt: Zcu.PerThread, features: *const Features) Error!void {
213 dev.check(.legalize);
214 assert(!features.eql(comptime .initEmpty())); // backend asked to run legalize, but no features were enabled242 assert(!features.eql(comptime .initEmpty())); // backend asked to run legalize, but no features were enabled
215 var l: Legalize = .{243 var l: Legalize = .{
216 .pt = pt,244 .pt = pt,
217 .air_instructions = air.instructions.toMultiArrayList(),245 .air_instructions = air.instructions.toMultiArrayList(),
218 .air_extra = air.extra,246 .air_extra = air.extra,
219 .features = features,247 .features = .init(features),
220 };248 };
221 defer air.* = l.getTmpAir();249 defer air.* = l.getTmpAir();
222 const main_extra = l.extraData(Air.Block, l.air_extra.items[@intFromEnum(Air.ExtraIndex.main_block)]);250 const main_extra = l.extraData(Air.Block, l.air_extra.items[@intFromEnum(Air.ExtraIndex.main_block)]);
...@@ -278,28 +306,28 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -278,28 +306,28 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
278 .bit_and,306 .bit_and,
279 .bit_or,307 .bit_or,
280 .xor,308 .xor,
281 => |air_tag| if (l.features.contains(comptime .scalarize(air_tag))) {309 => |air_tag| if (l.features.has(comptime .scalarize(air_tag))) {
282 const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op;310 const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op;
283 if (l.typeOf(bin_op.lhs).isVector(zcu)) continue :inst try l.scalarize(inst, .bin_op);311 if (l.typeOf(bin_op.lhs).isVector(zcu)) continue :inst try l.scalarize(inst, .bin_op);
284 },312 },
285 .add_safe => if (l.features.contains(.expand_add_safe)) {313 .add_safe => if (l.features.has(.expand_add_safe)) {
286 assert(!l.features.contains(.scalarize_add_safe)); // it doesn't make sense to do both314 assert(!l.features.has(.scalarize_add_safe)); // it doesn't make sense to do both
287 continue :inst l.replaceInst(inst, .block, try l.safeArithmeticBlockPayload(inst, .add_with_overflow));315 continue :inst l.replaceInst(inst, .block, try l.safeArithmeticBlockPayload(inst, .add_with_overflow));
288 } else if (l.features.contains(.scalarize_add_safe)) {316 } else if (l.features.has(.scalarize_add_safe)) {
289 const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op;317 const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op;
290 if (l.typeOf(bin_op.lhs).isVector(zcu)) continue :inst try l.scalarize(inst, .bin_op);318 if (l.typeOf(bin_op.lhs).isVector(zcu)) continue :inst try l.scalarize(inst, .bin_op);
291 },319 },
292 .sub_safe => if (l.features.contains(.expand_sub_safe)) {320 .sub_safe => if (l.features.has(.expand_sub_safe)) {
293 assert(!l.features.contains(.scalarize_sub_safe)); // it doesn't make sense to do both321 assert(!l.features.has(.scalarize_sub_safe)); // it doesn't make sense to do both
294 continue :inst l.replaceInst(inst, .block, try l.safeArithmeticBlockPayload(inst, .sub_with_overflow));322 continue :inst l.replaceInst(inst, .block, try l.safeArithmeticBlockPayload(inst, .sub_with_overflow));
295 } else if (l.features.contains(.scalarize_sub_safe)) {323 } else if (l.features.has(.scalarize_sub_safe)) {
296 const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op;324 const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op;
297 if (l.typeOf(bin_op.lhs).isVector(zcu)) continue :inst try l.scalarize(inst, .bin_op);325 if (l.typeOf(bin_op.lhs).isVector(zcu)) continue :inst try l.scalarize(inst, .bin_op);
298 },326 },
299 .mul_safe => if (l.features.contains(.expand_mul_safe)) {327 .mul_safe => if (l.features.has(.expand_mul_safe)) {
300 assert(!l.features.contains(.scalarize_mul_safe)); // it doesn't make sense to do both328 assert(!l.features.has(.scalarize_mul_safe)); // it doesn't make sense to do both
301 continue :inst l.replaceInst(inst, .block, try l.safeArithmeticBlockPayload(inst, .mul_with_overflow));329 continue :inst l.replaceInst(inst, .block, try l.safeArithmeticBlockPayload(inst, .mul_with_overflow));
302 } else if (l.features.contains(.scalarize_mul_safe)) {330 } else if (l.features.has(.scalarize_mul_safe)) {
303 const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op;331 const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op;
304 if (l.typeOf(bin_op.lhs).isVector(zcu)) continue :inst try l.scalarize(inst, .bin_op);332 if (l.typeOf(bin_op.lhs).isVector(zcu)) continue :inst try l.scalarize(inst, .bin_op);
305 },333 },
...@@ -308,7 +336,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -308,7 +336,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
308 .sub_with_overflow,336 .sub_with_overflow,
309 .mul_with_overflow,337 .mul_with_overflow,
310 .shl_with_overflow,338 .shl_with_overflow,
311 => |air_tag| if (l.features.contains(comptime .scalarize(air_tag))) {339 => |air_tag| if (l.features.has(comptime .scalarize(air_tag))) {
312 const ty_pl = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_pl;340 const ty_pl = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_pl;
313 if (ty_pl.ty.toType().fieldType(0, zcu).isVector(zcu)) continue :inst l.replaceInst(inst, .block, try l.scalarizeOverflowBlockPayload(inst));341 if (ty_pl.ty.toType().fieldType(0, zcu).isVector(zcu)) continue :inst l.replaceInst(inst, .block, try l.scalarizeOverflowBlockPayload(inst));
314 },342 },
...@@ -320,13 +348,13 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -320,13 +348,13 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
320 .shl,348 .shl,
321 .shl_exact,349 .shl_exact,
322 .shl_sat,350 .shl_sat,
323 => |air_tag| if (!l.features.intersectWith(comptime .initMany(&.{351 => |air_tag| if (l.features.hasAny(&.{
324 .unsplat_shift_rhs,352 .unsplat_shift_rhs,
325 .scalarize(air_tag),353 .scalarize(air_tag),
326 })).eql(comptime .initEmpty())) {354 })) {
327 const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op;355 const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op;
328 if (l.typeOf(bin_op.rhs).isVector(zcu)) {356 if (l.typeOf(bin_op.rhs).isVector(zcu)) {
329 if (l.features.contains(.unsplat_shift_rhs)) {357 if (l.features.has(.unsplat_shift_rhs)) {
330 if (bin_op.rhs.toInterned()) |rhs_ip_index| switch (ip.indexToKey(rhs_ip_index)) {358 if (bin_op.rhs.toInterned()) |rhs_ip_index| switch (ip.indexToKey(rhs_ip_index)) {
331 else => {},359 else => {},
332 .aggregate => |aggregate| switch (aggregate.storage) {360 .aggregate => |aggregate| switch (aggregate.storage) {
...@@ -347,7 +375,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -347,7 +375,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
347 }375 }
348 }376 }
349 }377 }
350 if (l.features.contains(comptime .scalarize(air_tag))) continue :inst try l.scalarize(inst, .bin_op);378 if (l.features.has(comptime .scalarize(air_tag))) continue :inst try l.scalarize(inst, .bin_op);
351 }379 }
352 },380 },
353 inline .not,381 inline .not,
...@@ -364,11 +392,11 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -364,11 +392,11 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
364 .int_from_float,392 .int_from_float,
365 .int_from_float_optimized,393 .int_from_float_optimized,
366 .float_from_int,394 .float_from_int,
367 => |air_tag| if (l.features.contains(comptime .scalarize(air_tag))) {395 => |air_tag| if (l.features.has(comptime .scalarize(air_tag))) {
368 const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op;396 const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op;
369 if (ty_op.ty.toType().isVector(zcu)) continue :inst try l.scalarize(inst, .ty_op);397 if (ty_op.ty.toType().isVector(zcu)) continue :inst try l.scalarize(inst, .ty_op);
370 },398 },
371 .bitcast => if (l.features.contains(.scalarize_bitcast)) {399 .bitcast => if (l.features.has(.scalarize_bitcast)) {
372 const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op;400 const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op;
373401
374 const to_ty = ty_op.ty.toType();402 const to_ty = ty_op.ty.toType();
...@@ -404,10 +432,10 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -404,10 +432,10 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
404 };432 };
405 if (!from_ty_legal) continue :inst l.replaceInst(inst, .block, try l.scalarizeBitcastOperandBlockPayload(inst));433 if (!from_ty_legal) continue :inst l.replaceInst(inst, .block, try l.scalarizeBitcastOperandBlockPayload(inst));
406 },434 },
407 .intcast_safe => if (l.features.contains(.expand_intcast_safe)) {435 .intcast_safe => if (l.features.has(.expand_intcast_safe)) {
408 assert(!l.features.contains(.scalarize_intcast_safe)); // it doesn't make sense to do both436 assert(!l.features.has(.scalarize_intcast_safe)); // it doesn't make sense to do both
409 continue :inst l.replaceInst(inst, .block, try l.safeIntcastBlockPayload(inst));437 continue :inst l.replaceInst(inst, .block, try l.safeIntcastBlockPayload(inst));
410 } else if (l.features.contains(.scalarize_intcast_safe)) {438 } else if (l.features.has(.scalarize_intcast_safe)) {
411 const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op;439 const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op;
412 if (ty_op.ty.toType().isVector(zcu)) continue :inst try l.scalarize(inst, .ty_op);440 if (ty_op.ty.toType().isVector(zcu)) continue :inst try l.scalarize(inst, .ty_op);
413 },441 },
...@@ -442,7 +470,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -442,7 +470,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
442 .trunc_float,470 .trunc_float,
443 .neg,471 .neg,
444 .neg_optimized,472 .neg_optimized,
445 => |air_tag| if (l.features.contains(comptime .scalarize(air_tag))) {473 => |air_tag| if (l.features.has(comptime .scalarize(air_tag))) {
446 const un_op = l.air_instructions.items(.data)[@intFromEnum(inst)].un_op;474 const un_op = l.air_instructions.items(.data)[@intFromEnum(inst)].un_op;
447 if (l.typeOf(un_op).isVector(zcu)) continue :inst try l.scalarize(inst, .un_op);475 if (l.typeOf(un_op).isVector(zcu)) continue :inst try l.scalarize(inst, .un_op);
448 },476 },
...@@ -459,7 +487,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -459,7 +487,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
459 .cmp_neq,487 .cmp_neq,
460 .cmp_neq_optimized,488 .cmp_neq_optimized,
461 => {},489 => {},
462 inline .cmp_vector, .cmp_vector_optimized => |air_tag| if (l.features.contains(comptime .scalarize(air_tag))) {490 inline .cmp_vector, .cmp_vector_optimized => |air_tag| if (l.features.has(comptime .scalarize(air_tag))) {
463 const ty_pl = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_pl;491 const ty_pl = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_pl;
464 if (ty_pl.ty.toType().isVector(zcu)) continue :inst try l.scalarize(inst, .cmp_vector);492 if (ty_pl.ty.toType().isVector(zcu)) continue :inst try l.scalarize(inst, .cmp_vector);
465 },493 },
...@@ -513,13 +541,13 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -513,13 +541,13 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
513 .bool_and,541 .bool_and,
514 .bool_or,542 .bool_or,
515 => {},543 => {},
516 .load => if (l.features.contains(.expand_packed_load)) {544 .load => if (l.features.has(.expand_packed_load)) {
517 const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op;545 const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op;
518 const ptr_info = l.typeOf(ty_op.operand).ptrInfo(zcu);546 const ptr_info = l.typeOf(ty_op.operand).ptrInfo(zcu);
519 if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) continue :inst l.replaceInst(inst, .block, try l.packedLoadBlockPayload(inst));547 if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) continue :inst l.replaceInst(inst, .block, try l.packedLoadBlockPayload(inst));
520 },548 },
521 .ret, .ret_safe, .ret_load => {},549 .ret, .ret_safe, .ret_load => {},
522 .store, .store_safe => if (l.features.contains(.expand_packed_store)) {550 .store, .store_safe => if (l.features.has(.expand_packed_store)) {
523 const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op;551 const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op;
524 const ptr_info = l.typeOf(bin_op.lhs).ptrInfo(zcu);552 const ptr_info = l.typeOf(bin_op.lhs).ptrInfo(zcu);
525 if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) continue :inst l.replaceInst(inst, .block, try l.packedStoreBlockPayload(inst));553 if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) continue :inst l.replaceInst(inst, .block, try l.packedStoreBlockPayload(inst));
...@@ -542,7 +570,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -542,7 +570,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
542 .struct_field_ptr_index_2,570 .struct_field_ptr_index_2,
543 .struct_field_ptr_index_3,571 .struct_field_ptr_index_3,
544 => {},572 => {},
545 .struct_field_val => if (l.features.contains(.expand_packed_struct_field_val)) {573 .struct_field_val => if (l.features.has(.expand_packed_struct_field_val)) {
546 const ty_pl = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_pl;574 const ty_pl = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_pl;
547 const extra = l.extraData(Air.StructField, ty_pl.payload).data;575 const extra = l.extraData(Air.StructField, ty_pl.payload).data;
548 switch (l.typeOf(extra.struct_operand).containerLayout(zcu)) {576 switch (l.typeOf(extra.struct_operand).containerLayout(zcu)) {
...@@ -564,7 +592,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -564,7 +592,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
564 .ptr_elem_ptr,592 .ptr_elem_ptr,
565 .array_to_slice,593 .array_to_slice,
566 => {},594 => {},
567 .reduce, .reduce_optimized => if (l.features.contains(.reduce_one_elem_to_bitcast)) {595 .reduce, .reduce_optimized => if (l.features.has(.reduce_one_elem_to_bitcast)) {
568 const reduce = l.air_instructions.items(.data)[@intFromEnum(inst)].reduce;596 const reduce = l.air_instructions.items(.data)[@intFromEnum(inst)].reduce;
569 const vector_ty = l.typeOf(reduce.operand);597 const vector_ty = l.typeOf(reduce.operand);
570 switch (vector_ty.vectorLen(zcu)) {598 switch (vector_ty.vectorLen(zcu)) {
...@@ -577,9 +605,9 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -577,9 +605,9 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
577 }605 }
578 },606 },
579 .splat => {},607 .splat => {},
580 .shuffle_one => if (l.features.contains(.scalarize_shuffle_one)) continue :inst try l.scalarize(inst, .shuffle_one),608 .shuffle_one => if (l.features.has(.scalarize_shuffle_one)) continue :inst try l.scalarize(inst, .shuffle_one),
581 .shuffle_two => if (l.features.contains(.scalarize_shuffle_two)) continue :inst try l.scalarize(inst, .shuffle_two),609 .shuffle_two => if (l.features.has(.scalarize_shuffle_two)) continue :inst try l.scalarize(inst, .shuffle_two),
582 .select => if (l.features.contains(.scalarize_select)) continue :inst try l.scalarize(inst, .select),610 .select => if (l.features.has(.scalarize_select)) continue :inst try l.scalarize(inst, .select),
583 .memset,611 .memset,
584 .memset_safe,612 .memset_safe,
585 .memcpy,613 .memcpy,
...@@ -597,7 +625,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -597,7 +625,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
597 .error_name,625 .error_name,
598 .error_set_has_value,626 .error_set_has_value,
599 => {},627 => {},
600 .aggregate_init => if (l.features.contains(.expand_packed_aggregate_init)) {628 .aggregate_init => if (l.features.has(.expand_packed_aggregate_init)) {
601 const ty_pl = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_pl;629 const ty_pl = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_pl;
602 const agg_ty = ty_pl.ty.toType();630 const agg_ty = ty_pl.ty.toType();
603 switch (agg_ty.zigTypeTag(zcu)) {631 switch (agg_ty.zigTypeTag(zcu)) {
...@@ -609,7 +637,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -609,7 +637,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
609 }637 }
610 },638 },
611 .union_init, .prefetch => {},639 .union_init, .prefetch => {},
612 .mul_add => if (l.features.contains(.scalarize_mul_add)) {640 .mul_add => if (l.features.has(.scalarize_mul_add)) {
613 const pl_op = l.air_instructions.items(.data)[@intFromEnum(inst)].pl_op;641 const pl_op = l.air_instructions.items(.data)[@intFromEnum(inst)].pl_op;
614 if (l.typeOf(pl_op.operand).isVector(zcu)) continue :inst try l.scalarize(inst, .pl_op_bin);642 if (l.typeOf(pl_op.operand).isVector(zcu)) continue :inst try l.scalarize(inst, .pl_op_bin);
615 },643 },
...@@ -636,6 +664,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {...@@ -636,6 +664,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
636}664}
637665
638const ScalarizeForm = enum { un_op, ty_op, bin_op, pl_op_bin, bitcast, cmp_vector, shuffle_one, shuffle_two, select };666const ScalarizeForm = enum { un_op, ty_op, bin_op, pl_op_bin, bitcast, cmp_vector, shuffle_one, shuffle_two, select };
667/// inline to propagate comptime-known `replaceInst` result.
639inline fn scalarize(l: *Legalize, orig_inst: Air.Inst.Index, comptime form: ScalarizeForm) Error!Air.Inst.Tag {668inline fn scalarize(l: *Legalize, orig_inst: Air.Inst.Index, comptime form: ScalarizeForm) Error!Air.Inst.Tag {
640 return l.replaceInst(orig_inst, .block, try l.scalarizeBlockPayload(orig_inst, form));669 return l.replaceInst(orig_inst, .block, try l.scalarizeBlockPayload(orig_inst, form));
641}670}
...@@ -2691,7 +2720,7 @@ fn addBlockBody(l: *Legalize, body: []const Air.Inst.Index) Error!u32 {...@@ -2691,7 +2720,7 @@ fn addBlockBody(l: *Legalize, body: []const Air.Inst.Index) Error!u32 {
2691}2720}
26922721
2693/// Returns `tag` to remind the caller to `continue :inst` the result.2722/// Returns `tag` to remind the caller to `continue :inst` the result.
2694/// This is inline to propagate the comptime-known `tag`.2723/// `inline` to propagate the comptime-known `tag` result.
2695inline fn replaceInst(l: *Legalize, inst: Air.Inst.Index, comptime tag: Air.Inst.Tag, data: Air.Inst.Data) Air.Inst.Tag {2724inline fn replaceInst(l: *Legalize, inst: Air.Inst.Index, comptime tag: Air.Inst.Tag, data: Air.Inst.Data) Air.Inst.Tag {
2696 const orig_ty = if (std.debug.runtime_safety) l.typeOfIndex(inst) else {};2725 const orig_ty = if (std.debug.runtime_safety) l.typeOfIndex(inst) else {};
2697 l.air_instructions.set(@intFromEnum(inst), .{ .tag = tag, .data = data });2726 l.air_instructions.set(@intFromEnum(inst), .{ .tag = tag, .data = data });
src/codegen/c.zig+13-6
...@@ -23,12 +23,19 @@ const BigIntLimb = std.math.big.Limb;...@@ -23,12 +23,19 @@ const BigIntLimb = std.math.big.Limb;
23const BigInt = std.math.big.int;23const BigInt = std.math.big.int;
2424
25pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features {25pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features {
26 return if (dev.env.supports(.legalize)) comptime &.initMany(&.{26 return comptime switch (dev.env.supports(.legalize)) {
27 .expand_intcast_safe,27 inline false, true => |supports_legalize| &.init(.{
28 .expand_add_safe,28 // we don't currently ask zig1 to use safe optimization modes
29 .expand_sub_safe,29 .expand_intcast_safe = supports_legalize,
30 .expand_mul_safe,30 .expand_add_safe = supports_legalize,
31 }) else null; // we don't currently ask zig1 to use safe optimization modes31 .expand_sub_safe = supports_legalize,
32 .expand_mul_safe = supports_legalize,
33
34 .expand_packed_load = true,
35 .expand_packed_store = true,
36 .expand_packed_struct_field_val = true,
37 }),
38 };
32}39}
3340
34/// For most backends, MIR is basically a sequence of machine code instructions, perhaps with some41/// For most backends, MIR is basically a sequence of machine code instructions, perhaps with some