1
1
pt : Zcu.PerThread ,
2
2
air_instructions : std .MultiArrayList (Air .Inst ),
3
3
air_extra : std .ArrayListUnmanaged (u32 ),
4
- features : * const Features ,
4
+ features : 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
+ },
5
34
6
35
pub const Feature = enum {
7
36
scalarize_add ,
@@ -199,7 +228,7 @@ pub const Feature = enum {
199
228
.float_from_int = > .scalarize_float_from_int ,
200
229
.shuffle_one = > .scalarize_shuffle_one ,
201
230
.shuffle_two = > .scalarize_shuffle_two ,
202
- .select = > .scalarize_selects ,
231
+ .select = > .scalarize_select ,
203
232
.mul_add = > .scalarize_mul_add ,
204
233
};
205
234
}
@@ -210,13 +239,12 @@ pub const Features = std.enums.EnumSet(Feature);
210
239
pub const Error = std .mem .Allocator .Error ;
211
240
212
241
pub fn legalize (air : * Air , pt : Zcu.PerThread , features : * const Features ) Error ! void {
213
- dev .check (.legalize );
214
242
assert (! features .eql (comptime .initEmpty ())); // backend asked to run legalize, but no features were enabled
215
243
var l : Legalize = .{
216
244
.pt = pt ,
217
245
.air_instructions = air .instructions .toMultiArrayList (),
218
246
.air_extra = air .extra ,
219
- .features = features ,
247
+ .features = . init ( features ) ,
220
248
};
221
249
defer air .* = l .getTmpAir ();
222
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
306
.bit_and ,
279
307
.bit_or ,
280
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
310
const bin_op = l .air_instructions .items (.data )[@intFromEnum (inst )].bin_op ;
283
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 )) {
286
- assert (! l .features .contains (.scalarize_add_safe )); // it doesn't make sense to do both
313
+ .add_safe = > if (l .features .has (.expand_add_safe )) {
314
+ assert (! l .features .has (.scalarize_add_safe )); // it doesn't make sense to do both
287
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
317
const bin_op = l .air_instructions .items (.data )[@intFromEnum (inst )].bin_op ;
290
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 )) {
293
- assert (! l .features .contains (.scalarize_sub_safe )); // it doesn't make sense to do both
320
+ .sub_safe = > if (l .features .has (.expand_sub_safe )) {
321
+ assert (! l .features .has (.scalarize_sub_safe )); // it doesn't make sense to do both
294
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
324
const bin_op = l .air_instructions .items (.data )[@intFromEnum (inst )].bin_op ;
297
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 )) {
300
- assert (! l .features .contains (.scalarize_mul_safe )); // it doesn't make sense to do both
327
+ .mul_safe = > if (l .features .has (.expand_mul_safe )) {
328
+ assert (! l .features .has (.scalarize_mul_safe )); // it doesn't make sense to do both
301
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
331
const bin_op = l .air_instructions .items (.data )[@intFromEnum (inst )].bin_op ;
304
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
336
.sub_with_overflow ,
309
337
.mul_with_overflow ,
310
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
340
const ty_pl = l .air_instructions .items (.data )[@intFromEnum (inst )].ty_pl ;
313
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
348
.shl ,
321
349
.shl_exact ,
322
350
.shl_sat ,
323
- = > | air_tag | if (! l .features .intersectWith ( comptime . initMany (&.{
351
+ = > | air_tag | if (l .features .hasAny (&.{
324
352
.unsplat_shift_rhs ,
325
353
.scalarize (air_tag ),
326
- })). eql ( comptime . initEmpty ())) {
354
+ })) {
327
355
const bin_op = l .air_instructions .items (.data )[@intFromEnum (inst )].bin_op ;
328
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
358
if (bin_op .rhs .toInterned ()) | rhs_ip_index | switch (ip .indexToKey (rhs_ip_index )) {
331
359
else = > {},
332
360
.aggregate = > | aggregate | switch (aggregate .storage ) {
@@ -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
381
inline .not ,
@@ -364,11 +392,11 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
364
392
.int_from_float ,
365
393
.int_from_float_optimized ,
366
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
396
const ty_op = l .air_instructions .items (.data )[@intFromEnum (inst )].ty_op ;
369
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
400
const ty_op = l .air_instructions .items (.data )[@intFromEnum (inst )].ty_op ;
373
401
374
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
432
};
405
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 )) {
408
- assert (! l .features .contains (.scalarize_intcast_safe )); // it doesn't make sense to do both
435
+ .intcast_safe = > if (l .features .has (.expand_intcast_safe )) {
436
+ assert (! l .features .has (.scalarize_intcast_safe )); // it doesn't make sense to do both
409
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
439
const ty_op = l .air_instructions .items (.data )[@intFromEnum (inst )].ty_op ;
412
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
470
.trunc_float ,
443
471
.neg ,
444
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
474
const un_op = l .air_instructions .items (.data )[@intFromEnum (inst )].un_op ;
447
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
487
.cmp_neq ,
460
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
491
const ty_pl = l .air_instructions .items (.data )[@intFromEnum (inst )].ty_pl ;
464
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
541
.bool_and ,
514
542
.bool_or ,
515
543
= > {},
516
- .load = > if (l .features .contains (.expand_packed_load )) {
544
+ .load = > if (l .features .has (.expand_packed_load )) {
517
545
const ty_op = l .air_instructions .items (.data )[@intFromEnum (inst )].ty_op ;
518
546
const ptr_info = l .typeOf (ty_op .operand ).ptrInfo (zcu );
519
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
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
551
const bin_op = l .air_instructions .items (.data )[@intFromEnum (inst )].bin_op ;
524
552
const ptr_info = l .typeOf (bin_op .lhs ).ptrInfo (zcu );
525
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
570
.struct_field_ptr_index_2 ,
543
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
574
const ty_pl = l .air_instructions .items (.data )[@intFromEnum (inst )].ty_pl ;
547
575
const extra = l .extraData (Air .StructField , ty_pl .payload ).data ;
548
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
592
.ptr_elem_ptr ,
565
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
596
const reduce = l .air_instructions .items (.data )[@intFromEnum (inst )].reduce ;
569
597
const vector_ty = l .typeOf (reduce .operand );
570
598
switch (vector_ty .vectorLen (zcu )) {
@@ -577,9 +605,9 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
577
605
}
578
606
},
579
607
.splat = > {},
580
- .shuffle_one = > if (l .features .contains (.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 ),
582
- .select = > if (l .features .contains (.scalarize_select )) continue :inst try l .scalarize (inst , .select ),
608
+ .shuffle_one = > if (l .features .has (.scalarize_shuffle_one )) continue :inst try l .scalarize (inst , .shuffle_one ),
609
+ .shuffle_two = > if (l .features .has (.scalarize_shuffle_two )) continue :inst try l .scalarize (inst , .shuffle_two ),
610
+ .select = > if (l .features .has (.scalarize_select )) continue :inst try l .scalarize (inst , .select ),
583
611
.memset ,
584
612
.memset_safe ,
585
613
.memcpy ,
@@ -597,7 +625,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
597
625
.error_name ,
598
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
629
const ty_pl = l .air_instructions .items (.data )[@intFromEnum (inst )].ty_pl ;
602
630
const agg_ty = ty_pl .ty .toType ();
603
631
switch (agg_ty .zigTypeTag (zcu )) {
@@ -609,7 +637,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
609
637
}
610
638
},
611
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
641
const pl_op = l .air_instructions .items (.data )[@intFromEnum (inst )].pl_op ;
614
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
664
}
637
665
638
666
const 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.
639
668
inline fn scalarize (l : * Legalize , orig_inst : Air.Inst.Index , comptime form : ScalarizeForm ) Error ! Air.Inst.Tag {
640
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
2720
}
2692
2721
2693
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 .
2695
2724
inline fn replaceInst (l : * Legalize , inst : Air.Inst.Index , comptime tag : Air.Inst.Tag , data : Air.Inst.Data ) Air.Inst.Tag {
2696
2725
const orig_ty = if (std .debug .runtime_safety ) l .typeOfIndex (inst ) else {};
2697
2726
l .air_instructions .set (@intFromEnum (inst ), .{ .tag = tag , .data = data });
0 commit comments