authorgravatar for william@sengir.comWilliam Sengir <william@sengir.com> 2022-03-19 23:44:55-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-21 16:54:19-07:00
log0f4830704171b734bb4a0235fc14809282457dc3
treef14d426793b2878db30315195c068e6d28ca608d
parent862e63f535ec8d65e33ed7ea67eb9cf03bfc7d6a

stage2: add AIR instruction `cmp_vector`

The existing `cmp_*` instructions get their result type from `lhs`, but vector comparison will always return a vector of bools with only the length derived from its operands. This necessitates the creation of a new AIR instruction.

11 files changed, 86 insertions(+), 1 deletions(-)

src/Air.zig+19
...@@ -308,6 +308,10 @@ pub const Inst = struct {...@@ -308,6 +308,10 @@ pub const Inst = struct {
308 /// `!=`. Result type is always bool.308 /// `!=`. Result type is always bool.
309 /// Uses the `bin_op` field.309 /// Uses the `bin_op` field.
310 cmp_neq,310 cmp_neq,
311 /// Conditional between two vectors.
312 /// Result type is always a vector of bools.
313 /// Uses the `ty_pl` field, payload is `VectorCmp`.
314 cmp_vector,
311315
312 /// Conditional branch.316 /// Conditional branch.
313 /// Result type is always noreturn; no instructions in a block follow this one.317 /// Result type is always noreturn; no instructions in a block follow this one.
...@@ -781,6 +785,20 @@ pub const Shuffle = struct {...@@ -781,6 +785,20 @@ pub const Shuffle = struct {
781 mask_len: u32,785 mask_len: u32,
782};786};
783787
788pub const VectorCmp = struct {
789 lhs: Inst.Ref,
790 rhs: Inst.Ref,
791 op: u32,
792
793 pub fn compareOperator(self: VectorCmp) std.math.CompareOperator {
794 return @intToEnum(std.math.CompareOperator, @truncate(u3, self.op));
795 }
796
797 pub fn encodeOp(compare_operator: std.math.CompareOperator) u32 {
798 return @enumToInt(compare_operator);
799 }
800};
801
784/// Trailing:802/// Trailing:
785/// 0. `Inst.Ref` for every outputs_len803/// 0. `Inst.Ref` for every outputs_len
786/// 1. `Inst.Ref` for every inputs_len804/// 1. `Inst.Ref` for every inputs_len
...@@ -942,6 +960,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -942,6 +960,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
942 .aggregate_init,960 .aggregate_init,
943 .union_init,961 .union_init,
944 .field_parent_ptr,962 .field_parent_ptr,
963 .cmp_vector,
945 => return air.getRefType(datas[inst].ty_pl.ty),964 => return air.getRefType(datas[inst].ty_pl.ty),
946965
947 .not,966 .not,
src/Liveness.zig+4
...@@ -441,6 +441,10 @@ fn analyzeInst(...@@ -441,6 +441,10 @@ fn analyzeInst(
441 const reduce = inst_datas[inst].reduce;441 const reduce = inst_datas[inst].reduce;
442 return trackOperands(a, new_set, inst, main_tomb, .{ reduce.operand, .none, .none });442 return trackOperands(a, new_set, inst, main_tomb, .{ reduce.operand, .none, .none });
443 },443 },
444 .cmp_vector => {
445 const extra = a.air.extraData(Air.VectorCmp, inst_datas[inst].ty_pl.payload).data;
446 return trackOperands(a, new_set, inst, main_tomb, .{ extra.lhs, extra.rhs, .none });
447 },
444 .aggregate_init => {448 .aggregate_init => {
445 const ty_pl = inst_datas[inst].ty_pl;449 const ty_pl = inst_datas[inst].ty_pl;
446 const aggregate_ty = a.air.getRefType(ty_pl.ty);450 const aggregate_ty = a.air.getRefType(ty_pl.ty);
src/Sema.zig+14
...@@ -397,6 +397,20 @@ pub const Block = struct {...@@ -397,6 +397,20 @@ pub const Block = struct {
397 });397 });
398 }398 }
399399
400 fn addCmpVector(block: *Block, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref, cmp_op: std.math.CompareOperator, vector_ty: Air.Inst.Ref) !Air.Inst.Ref {
401 return block.addInst(.{
402 .tag = .cmp_vector,
403 .data = .{ .ty_pl = .{
404 .ty = vector_ty,
405 .payload = try block.sema.addExtra(Air.VectorCmp{
406 .lhs = lhs,
407 .rhs = rhs,
408 .op = Air.VectorCmp.encodeOp(cmp_op),
409 }),
410 } },
411 });
412 }
413
400 fn addAggregateInit(414 fn addAggregateInit(
401 block: *Block,415 block: *Block,
402 aggregate_ty: Type,416 aggregate_ty: Type,
src/arch/aarch64/CodeGen.zig+6
...@@ -577,6 +577,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -577,6 +577,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
577 .cmp_gte => try self.airCmp(inst, .gte),577 .cmp_gte => try self.airCmp(inst, .gte),
578 .cmp_gt => try self.airCmp(inst, .gt),578 .cmp_gt => try self.airCmp(inst, .gt),
579 .cmp_neq => try self.airCmp(inst, .neq),579 .cmp_neq => try self.airCmp(inst, .neq),
580 .cmp_vector => try self.airCmpVector(inst),
580581
581 .bool_and => try self.airBinOp(inst),582 .bool_and => try self.airBinOp(inst),
582 .bool_or => try self.airBinOp(inst),583 .bool_or => try self.airBinOp(inst),
...@@ -2713,6 +2714,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -2713,6 +2714,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
2713 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2714 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2714}2715}
27152716
2717fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {
2718 _ = inst;
2719 return self.fail("TODO implement airCmpVector for {}", .{self.target.cpu.arch});
2720}
2721
2716fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {2722fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
2717 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;2723 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
27182724
src/arch/arm/CodeGen.zig+6-1
...@@ -567,6 +567,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -567,6 +567,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
567 .cmp_gte => try self.airCmp(inst, .gte),567 .cmp_gte => try self.airCmp(inst, .gte),
568 .cmp_gt => try self.airCmp(inst, .gt),568 .cmp_gt => try self.airCmp(inst, .gt),
569 .cmp_neq => try self.airCmp(inst, .neq),569 .cmp_neq => try self.airCmp(inst, .neq),
570 .cmp_vector => try self.airCmpVector(inst),
570571
571 .bool_and => try self.airBinOp(inst),572 .bool_and => try self.airBinOp(inst),
572 .bool_or => try self.airBinOp(inst),573 .bool_or => try self.airBinOp(inst),
...@@ -2894,7 +2895,6 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -2894,7 +2895,6 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
2894 const lhs_ty = self.air.typeOf(bin_op.lhs);2895 const lhs_ty = self.air.typeOf(bin_op.lhs);
28952896
2896 switch (lhs_ty.zigTypeTag()) {2897 switch (lhs_ty.zigTypeTag()) {
2897 .Vector => return self.fail("TODO ARM cmp vectors", .{}),
2898 .Optional => return self.fail("TODO ARM cmp optionals", .{}),2898 .Optional => return self.fail("TODO ARM cmp optionals", .{}),
2899 .Float => return self.fail("TODO ARM cmp floats", .{}),2899 .Float => return self.fail("TODO ARM cmp floats", .{}),
2900 .Int, .Bool, .Pointer, .ErrorSet, .Enum => {2900 .Int, .Bool, .Pointer, .ErrorSet, .Enum => {
...@@ -2929,6 +2929,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -2929,6 +2929,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
2929 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2929 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2930}2930}
29312931
2932fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {
2933 _ = inst;
2934 return self.fail("TODO implement airCmpVector for {}", .{self.target.cpu.arch});
2935}
2936
2932fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {2937fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
2933 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;2938 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
29342939
src/arch/riscv64/CodeGen.zig+6
...@@ -537,6 +537,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -537,6 +537,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
537 .cmp_gte => try self.airCmp(inst, .gte),537 .cmp_gte => try self.airCmp(inst, .gte),
538 .cmp_gt => try self.airCmp(inst, .gt),538 .cmp_gt => try self.airCmp(inst, .gt),
539 .cmp_neq => try self.airCmp(inst, .neq),539 .cmp_neq => try self.airCmp(inst, .neq),
540 .cmp_vector => try self.airCmpVector(inst),
540541
541 .bool_and => try self.airBoolOp(inst),542 .bool_and => try self.airBoolOp(inst),
542 .bool_or => try self.airBoolOp(inst),543 .bool_or => try self.airBoolOp(inst),
...@@ -1791,6 +1792,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -1791,6 +1792,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1791 // return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1792 // return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1792}1793}
17931794
1795fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {
1796 _ = inst;
1797 return self.fail("TODO implement airCmpVector for {}", .{self.target.cpu.arch});
1798}
1799
1794fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {1800fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
1795 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;1801 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
17961802
src/arch/wasm/CodeGen.zig+6
...@@ -1309,6 +1309,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {...@@ -1309,6 +1309,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
1309 .cmp_lte => self.airCmp(inst, .lte),1309 .cmp_lte => self.airCmp(inst, .lte),
1310 .cmp_lt => self.airCmp(inst, .lt),1310 .cmp_lt => self.airCmp(inst, .lt),
1311 .cmp_neq => self.airCmp(inst, .neq),1311 .cmp_neq => self.airCmp(inst, .neq),
1312 .cmp_vector => self.airCmpVector(inst),
13121313
1313 .array_elem_val => self.airArrayElemVal(inst),1314 .array_elem_val => self.airArrayElemVal(inst),
1314 .array_to_slice => self.airArrayToSlice(inst),1315 .array_to_slice => self.airArrayToSlice(inst),
...@@ -2222,6 +2223,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: std.math.CompareOperator) Inner...@@ -2222,6 +2223,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: std.math.CompareOperator) Inner
2222 return cmp_tmp;2223 return cmp_tmp;
2223}2224}
22242225
2226fn airCmpVector(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
2227 _ = inst;
2228 return self.fail("TODO implement airCmpVector for wasm", .{});
2229}
2230
2225fn airBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {2231fn airBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
2226 const br = self.air.instructions.items(.data)[inst].br;2232 const br = self.air.instructions.items(.data)[inst].br;
2227 const block = self.blocks.get(br.block_inst).?;2233 const block = self.blocks.get(br.block_inst).?;
src/arch/x86_64/CodeGen.zig+6
...@@ -658,6 +658,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -658,6 +658,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
658 .cmp_gte => try self.airCmp(inst, .gte),658 .cmp_gte => try self.airCmp(inst, .gte),
659 .cmp_gt => try self.airCmp(inst, .gt),659 .cmp_gt => try self.airCmp(inst, .gt),
660 .cmp_neq => try self.airCmp(inst, .neq),660 .cmp_neq => try self.airCmp(inst, .neq),
661 .cmp_vector => try self.airCmpVector(inst),
661662
662 .bool_and => try self.airBoolOp(inst),663 .bool_and => try self.airBoolOp(inst),
663 .bool_or => try self.airBoolOp(inst),664 .bool_or => try self.airBoolOp(inst),
...@@ -3699,6 +3700,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -3699,6 +3700,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
3699 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });3700 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
3700}3701}
37013702
3703fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {
3704 _ = inst;
3705 return self.fail("TODO implement airCmpVector for {}", .{self.target.cpu.arch});
3706}
3707
3702fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {3708fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
3703 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;3709 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
3704 const payload = try self.addExtra(Mir.DbgLineColumn{3710 const payload = try self.addExtra(Mir.DbgLineColumn{
src/codegen/c.zig+2
...@@ -1715,6 +1715,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -1715,6 +1715,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
1715 .cmp_eq => try airEquality(f, inst, "((", "=="),1715 .cmp_eq => try airEquality(f, inst, "((", "=="),
1716 .cmp_neq => try airEquality(f, inst, "!((", "!="),1716 .cmp_neq => try airEquality(f, inst, "!((", "!="),
17171717
1718 .cmp_vector => return f.fail("TODO: C backend: implement binary op for tag '{s}'", .{@tagName(Air.Inst.Tag.cmp_vector)}),
1719
1718 // bool_and and bool_or are non-short-circuit operations1720 // bool_and and bool_or are non-short-circuit operations
1719 .bool_and => try airBinOp(f, inst, " & "),1721 .bool_and => try airBinOp(f, inst, " & "),
1720 .bool_or => try airBinOp(f, inst, " | "),1722 .bool_or => try airBinOp(f, inst, " | "),
src/codegen/llvm.zig+6
...@@ -3375,6 +3375,7 @@ pub const FuncGen = struct {...@@ -3375,6 +3375,7 @@ pub const FuncGen = struct {
3375 .cmp_lt => try self.airCmp(inst, .lt),3375 .cmp_lt => try self.airCmp(inst, .lt),
3376 .cmp_lte => try self.airCmp(inst, .lte),3376 .cmp_lte => try self.airCmp(inst, .lte),
3377 .cmp_neq => try self.airCmp(inst, .neq),3377 .cmp_neq => try self.airCmp(inst, .neq),
3378 .cmp_vector => try self.airCmpVector(inst),
33783379
3379 .is_non_null => try self.airIsNonNull(inst, false, false, .NE),3380 .is_non_null => try self.airIsNonNull(inst, false, false, .NE),
3380 .is_non_null_ptr => try self.airIsNonNull(inst, true , false, .NE),3381 .is_non_null_ptr => try self.airIsNonNull(inst, true , false, .NE),
...@@ -3640,6 +3641,11 @@ pub const FuncGen = struct {...@@ -3640,6 +3641,11 @@ pub const FuncGen = struct {
3640 return self.cmp(lhs, rhs, operand_ty, op);3641 return self.cmp(lhs, rhs, operand_ty, op);
3641 }3642 }
36423643
3644 fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
3645 _ = inst;
3646 return self.todo("implement airCmpVector");
3647 }
3648
3643 fn cmp(3649 fn cmp(
3644 self: *FuncGen,3650 self: *FuncGen,
3645 lhs: *const llvm.Value,3651 lhs: *const llvm.Value,
src/print_air.zig+11
...@@ -266,6 +266,7 @@ const Writer = struct {...@@ -266,6 +266,7 @@ const Writer = struct {
266 .mul_add => try w.writeMulAdd(s, inst),266 .mul_add => try w.writeMulAdd(s, inst),
267 .shuffle => try w.writeShuffle(s, inst),267 .shuffle => try w.writeShuffle(s, inst),
268 .reduce => try w.writeReduce(s, inst),268 .reduce => try w.writeReduce(s, inst),
269 .cmp_vector => try w.writeCmpVector(s, inst),
269270
270 .add_with_overflow,271 .add_with_overflow,
271 .sub_with_overflow,272 .sub_with_overflow,
...@@ -402,6 +403,16 @@ const Writer = struct {...@@ -402,6 +403,16 @@ const Writer = struct {
402 try s.print(", {s}", .{@tagName(reduce.operation)});403 try s.print(", {s}", .{@tagName(reduce.operation)});
403 }404 }
404405
406 fn writeCmpVector(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
407 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
408 const extra = w.air.extraData(Air.VectorCmp, ty_pl.payload).data;
409
410 try s.print("{s}, ", .{@tagName(extra.compareOperator())});
411 try w.writeOperand(s, inst, 0, extra.lhs);
412 try s.writeAll(", ");
413 try w.writeOperand(s, inst, 1, extra.rhs);
414 }
415
405 fn writeFence(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {416 fn writeFence(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
406 const atomic_order = w.air.instructions.items(.data)[inst].fence;417 const atomic_order = w.air.instructions.items(.data)[inst].fence;
407418