Skip to content

Commit 7c31f9d

Browse files
mluggjacobly0
authored andcommitted
Sema: don't emit AIR reduce for single-element vectors
This is equivalent to `array_elem_val`, and doing that conversion in Sema (seems reasonable since it's just a simple branch) is much easier for the self-hosted x86_64 backend then actually handling this case.
1 parent 7bfdb7f commit 7c31f9d

File tree

1 file changed

+41
-126
lines changed

1 file changed

+41
-126
lines changed

src/Sema.zig

Lines changed: 41 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,29 @@ pub const Block = struct {
753753
});
754754
}
755755

756+
fn addReduce(block: *Block, operand: Air.Inst.Ref, operation: std.builtin.ReduceOp) !Air.Inst.Ref {
757+
const sema = block.sema;
758+
const zcu = sema.pt.zcu;
759+
const vector_ty = sema.typeOf(operand);
760+
switch (vector_ty.vectorLen(zcu)) {
761+
0 => unreachable,
762+
1 => return block.addBinOp(.array_elem_val, operand, .zero_usize),
763+
else => {},
764+
}
765+
const allow_optimized = switch (vector_ty.childType(zcu).zigTypeTag(zcu)) {
766+
.float => true,
767+
.bool, .int => false,
768+
else => unreachable,
769+
};
770+
return block.addInst(.{
771+
.tag = if (allow_optimized and block.float_mode == .optimized) .reduce_optimized else .reduce,
772+
.data = .{ .reduce = .{
773+
.operand = operand,
774+
.operation = operation,
775+
} },
776+
});
777+
}
778+
756779
fn addAggregateInit(
757780
block: *Block,
758781
aggregate_ty: Type,
@@ -10307,10 +10330,7 @@ fn intCast(
1030710330
const zeros = try sema.splat(operand_ty, try pt.intValue(operand_scalar_ty, 0));
1030810331
const zero_inst = Air.internedToRef(zeros.toIntern());
1030910332
const is_in_range = try block.addCmpVector(operand, zero_inst, .eq);
10310-
const all_in_range = try block.addInst(.{
10311-
.tag = .reduce,
10312-
.data = .{ .reduce = .{ .operand = is_in_range, .operation = .And } },
10313-
});
10333+
const all_in_range = try block.addReduce(is_in_range, .And);
1031410334
break :ok all_in_range;
1031510335
} else ok: {
1031610336
const zero_inst = Air.internedToRef((try pt.intValue(operand_ty, 0)).toIntern());
@@ -10374,13 +10394,7 @@ fn intCast(
1037410394

1037510395
const ok = if (is_vector) ok: {
1037610396
const is_in_range = try block.addCmpVector(diff_unsigned, dest_range, .lte);
10377-
const all_in_range = try block.addInst(.{
10378-
.tag = if (block.float_mode == .optimized) .reduce_optimized else .reduce,
10379-
.data = .{ .reduce = .{
10380-
.operand = is_in_range,
10381-
.operation = .And,
10382-
} },
10383-
});
10397+
const all_in_range = try block.addReduce(is_in_range, .And);
1038410398
break :ok all_in_range;
1038510399
} else ok: {
1038610400
const is_in_range = try block.addBinOp(.cmp_lte, diff_unsigned, dest_range);
@@ -10391,13 +10405,7 @@ fn intCast(
1039110405
} else {
1039210406
const ok = if (is_vector) ok: {
1039310407
const is_in_range = try block.addCmpVector(operand, dest_max, .lte);
10394-
const all_in_range = try block.addInst(.{
10395-
.tag = if (block.float_mode == .optimized) .reduce_optimized else .reduce,
10396-
.data = .{ .reduce = .{
10397-
.operand = is_in_range,
10398-
.operation = .And,
10399-
} },
10400-
});
10408+
const all_in_range = try block.addReduce(is_in_range, .And);
1040110409
break :ok all_in_range;
1040210410
} else ok: {
1040310411
const is_in_range = try block.addBinOp(.cmp_lte, operand, dest_max);
@@ -10413,13 +10421,7 @@ fn intCast(
1041310421
const zero_val = try sema.splat(operand_ty, scalar_zero);
1041410422
const zero_inst = Air.internedToRef(zero_val.toIntern());
1041510423
const is_in_range = try block.addCmpVector(operand, zero_inst, .gte);
10416-
const all_in_range = try block.addInst(.{
10417-
.tag = if (block.float_mode == .optimized) .reduce_optimized else .reduce,
10418-
.data = .{ .reduce = .{
10419-
.operand = is_in_range,
10420-
.operation = .And,
10421-
} },
10422-
});
10424+
const all_in_range = try block.addReduce(is_in_range, .And);
1042310425
break :ok all_in_range;
1042410426
} else ok: {
1042510427
const zero_inst = Air.internedToRef((try pt.intValue(operand_ty, 0)).toIntern());
@@ -14330,13 +14332,7 @@ fn zirShl(
1433014332
const ok = if (rhs_ty.zigTypeTag(zcu) == .vector) ok: {
1433114333
const bit_count_inst = Air.internedToRef((try sema.splat(rhs_ty, bit_count_val)).toIntern());
1433214334
const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);
14333-
break :ok try block.addInst(.{
14334-
.tag = .reduce,
14335-
.data = .{ .reduce = .{
14336-
.operand = lt,
14337-
.operation = .And,
14338-
} },
14339-
});
14335+
break :ok try block.addReduce(lt, .And);
1434014336
} else ok: {
1434114337
const bit_count_inst = Air.internedToRef(bit_count_val.toIntern());
1434214338
break :ok try block.addBinOp(.cmp_lt, rhs, bit_count_inst);
@@ -14358,13 +14354,7 @@ fn zirShl(
1435814354
});
1435914355
const ov_bit = try sema.tupleFieldValByIndex(block, op_ov, 1, op_ov_tuple_ty);
1436014356
const any_ov_bit = if (lhs_ty.zigTypeTag(zcu) == .vector)
14361-
try block.addInst(.{
14362-
.tag = if (block.float_mode == .optimized) .reduce_optimized else .reduce,
14363-
.data = .{ .reduce = .{
14364-
.operand = ov_bit,
14365-
.operation = .Or,
14366-
} },
14367-
})
14357+
try block.addReduce(ov_bit, .Or)
1436814358
else
1436914359
ov_bit;
1437014360
const zero_ov = Air.internedToRef((try pt.intValue(Type.u1, 0)).toIntern());
@@ -14490,13 +14480,7 @@ fn zirShr(
1449014480
const ok = if (rhs_ty.zigTypeTag(zcu) == .vector) ok: {
1449114481
const bit_count_inst = Air.internedToRef((try sema.splat(rhs_ty, bit_count_val)).toIntern());
1449214482
const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);
14493-
break :ok try block.addInst(.{
14494-
.tag = .reduce,
14495-
.data = .{ .reduce = .{
14496-
.operand = lt,
14497-
.operation = .And,
14498-
} },
14499-
});
14483+
break :ok try block.addReduce(lt, .And);
1450014484
} else ok: {
1450114485
const bit_count_inst = Air.internedToRef(bit_count_val.toIntern());
1450214486
break :ok try block.addBinOp(.cmp_lt, rhs, bit_count_inst);
@@ -14509,13 +14493,7 @@ fn zirShr(
1450914493

1451014494
const ok = if (rhs_ty.zigTypeTag(zcu) == .vector) ok: {
1451114495
const eql = try block.addCmpVector(lhs, back, .eq);
14512-
break :ok try block.addInst(.{
14513-
.tag = if (block.float_mode == .optimized) .reduce_optimized else .reduce,
14514-
.data = .{ .reduce = .{
14515-
.operand = eql,
14516-
.operation = .And,
14517-
} },
14518-
});
14496+
break :ok try block.addReduce(eql, .And);
1451914497
} else try block.addBinOp(.cmp_eq, lhs, back);
1452014498
try sema.addSafetyCheck(block, src, ok, .shr_overflow);
1452114499
}
@@ -15565,16 +15543,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1556515543

1556615544
if (resolved_type.zigTypeTag(zcu) == .vector) {
1556715545
const eql = try block.addCmpVector(result, floored, .eq);
15568-
break :ok try block.addInst(.{
15569-
.tag = switch (block.float_mode) {
15570-
.strict => .reduce,
15571-
.optimized => .reduce_optimized,
15572-
},
15573-
.data = .{ .reduce = .{
15574-
.operand = eql,
15575-
.operation = .And,
15576-
} },
15577-
});
15546+
break :ok try block.addReduce(eql, .And);
1557815547
} else {
1557915548
const is_in_range = try block.addBinOp(switch (block.float_mode) {
1558015549
.strict => .cmp_eq,
@@ -15594,13 +15563,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1559415563
const zero_val = try sema.splat(resolved_type, scalar_zero);
1559515564
const zero = Air.internedToRef(zero_val.toIntern());
1559615565
const eql = try block.addCmpVector(remainder, zero, .eq);
15597-
break :ok try block.addInst(.{
15598-
.tag = .reduce,
15599-
.data = .{ .reduce = .{
15600-
.operand = eql,
15601-
.operation = .And,
15602-
} },
15603-
});
15566+
break :ok try block.addReduce(eql, .And);
1560415567
} else {
1560515568
const zero = Air.internedToRef(scalar_zero.toIntern());
1560615569
const is_in_range = try block.addBinOp(.cmp_eq, remainder, zero);
@@ -15829,13 +15792,7 @@ fn addDivIntOverflowSafety(
1582915792
break :ok try block.addCmpVector(casted_rhs, neg_one_ref, .neq);
1583015793
};
1583115794

15832-
const ok = try block.addInst(.{
15833-
.tag = .reduce,
15834-
.data = .{ .reduce = .{
15835-
.operand = try block.addBinOp(.bool_or, lhs_ok, rhs_ok),
15836-
.operation = .And,
15837-
} },
15838-
});
15795+
const ok = try block.addReduce(try block.addBinOp(.bool_or, lhs_ok, rhs_ok), .And);
1583915796
try sema.addSafetyCheck(block, src, ok, .integer_overflow);
1584015797
} else {
1584115798
const lhs_ok: Air.Inst.Ref = if (maybe_lhs_val == null) ok: {
@@ -15886,13 +15843,7 @@ fn addDivByZeroSafety(
1588615843
const zero_val = try sema.splat(resolved_type, scalar_zero);
1588715844
const zero = Air.internedToRef(zero_val.toIntern());
1588815845
const ok = try block.addCmpVector(casted_rhs, zero, .neq);
15889-
break :ok try block.addInst(.{
15890-
.tag = if (is_int) .reduce else .reduce_optimized,
15891-
.data = .{ .reduce = .{
15892-
.operand = ok,
15893-
.operation = .And,
15894-
} },
15895-
});
15846+
break :ok try block.addReduce(ok, .And);
1589615847
} else ok: {
1589715848
const zero = Air.internedToRef(scalar_zero.toIntern());
1589815849
break :ok try block.addBinOp(if (is_int) .cmp_neq else .cmp_neq_optimized, casted_rhs, zero);
@@ -16579,13 +16530,7 @@ fn analyzeArithmetic(
1657916530
});
1658016531
const ov_bit = try sema.tupleFieldValByIndex(block, op_ov, 1, op_ov_tuple_ty);
1658116532
const any_ov_bit = if (resolved_type.zigTypeTag(zcu) == .vector)
16582-
try block.addInst(.{
16583-
.tag = if (block.float_mode == .optimized) .reduce_optimized else .reduce,
16584-
.data = .{ .reduce = .{
16585-
.operand = ov_bit,
16586-
.operation = .Or,
16587-
} },
16588-
})
16533+
try block.addReduce(ov_bit, .Or)
1658916534
else
1659016535
ov_bit;
1659116536
const zero_ov = Air.internedToRef((try pt.intValue(Type.u1, 0)).toIntern());
@@ -22406,13 +22351,7 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
2240622351
const ok_pos = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, 1.0))).toIntern()), .lt);
2240722352
const ok_neg = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, -1.0))).toIntern()), .gt);
2240822353
const ok = try block.addBinOp(.bit_and, ok_pos, ok_neg);
22409-
break :ok try block.addInst(.{
22410-
.tag = .reduce,
22411-
.data = .{ .reduce = .{
22412-
.operand = ok,
22413-
.operation = .And,
22414-
} },
22415-
});
22354+
break :ok try block.addReduce(ok, .And);
2241622355
} else ok: {
2241722356
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()));
2241822357
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()));
@@ -22555,13 +22494,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2255522494
const is_non_zero = if (is_vector) all_non_zero: {
2255622495
const zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern());
2255722496
const is_non_zero = try block.addCmpVector(operand_coerced, zero_usize, .neq);
22558-
break :all_non_zero try block.addInst(.{
22559-
.tag = .reduce,
22560-
.data = .{ .reduce = .{
22561-
.operand = is_non_zero,
22562-
.operation = .And,
22563-
} },
22564-
});
22497+
break :all_non_zero try block.addReduce(is_non_zero, .And);
2256522498
} else try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize);
2256622499
try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null);
2256722500
}
@@ -22578,13 +22511,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2257822511
const is_aligned = if (is_vector) all_aligned: {
2257922512
const splat_zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern());
2258022513
const is_aligned = try block.addCmpVector(remainder, splat_zero_usize, .eq);
22581-
break :all_aligned try block.addInst(.{
22582-
.tag = .reduce,
22583-
.data = .{ .reduce = .{
22584-
.operand = is_aligned,
22585-
.operation = .And,
22586-
} },
22587-
});
22514+
break :all_aligned try block.addReduce(is_aligned, .And);
2258822515
} else try block.addBinOp(.cmp_eq, remainder, .zero_usize);
2258922516
try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment);
2259022517
}
@@ -24540,13 +24467,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
2454024467
}
2454124468

2454224469
try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), operand_src);
24543-
return block.addInst(.{
24544-
.tag = if (block.float_mode == .optimized) .reduce_optimized else .reduce,
24545-
.data = .{ .reduce = .{
24546-
.operand = operand,
24547-
.operation = operation,
24548-
} },
24549-
});
24470+
return block.addReduce(operand, operation);
2455024471
}
2455124472

2455224473
fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -27324,13 +27245,7 @@ fn addSafetyCheckSentinelMismatch(
2732427245

2732527246
const ok = if (sentinel_ty.zigTypeTag(zcu) == .vector) ok: {
2732627247
const eql = try parent_block.addCmpVector(expected_sentinel, actual_sentinel, .eq);
27327-
break :ok try parent_block.addInst(.{
27328-
.tag = .reduce,
27329-
.data = .{ .reduce = .{
27330-
.operand = eql,
27331-
.operation = .And,
27332-
} },
27333-
});
27248+
break :ok try parent_block.addReduce(eql, .And);
2733427249
} else ok: {
2733527250
assert(sentinel_ty.isSelfComparable(zcu, true));
2733627251
break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel);

0 commit comments

Comments
 (0)