| author | |
| committer | |
| log | 0f4830704171b734bb4a0235fc14809282457dc3 |
| tree | f14d426793b2878db30315195c068e6d28ca608d |
| parent | 862e63f535ec8d65e33ed7ea67eb9cf03bfc7d6a |
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, | ||
| 311 | 315 | ||
| 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 | }; |
| 783 | 787 | ||
| 788 | pub 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_len | 803 | /// 0. `Inst.Ref` for every outputs_len |
| 786 | /// 1. `Inst.Ref` for every inputs_len | 804 | /// 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), |
| 946 | 965 | ||
| 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 | } |
| 399 | 399 | ||
| 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), | ||
| 580 | 581 | ||
| 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 | } |
| 2715 | 2716 | ||
| 2717 | fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void { | ||
| 2718 | _ = inst; | ||
| 2719 | return self.fail("TODO implement airCmpVector for {}", .{self.target.cpu.arch}); | ||
| 2720 | } | ||
| 2721 | |||
| 2716 | fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { | 2722 | fn 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; |
| 2718 | 2724 |
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), | ||
| 570 | 571 | ||
| 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); |
| 2895 | 2896 | ||
| 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 | } |
| 2931 | 2931 | ||
| 2932 | fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void { | ||
| 2933 | _ = inst; | ||
| 2934 | return self.fail("TODO implement airCmpVector for {}", .{self.target.cpu.arch}); | ||
| 2935 | } | ||
| 2936 | |||
| 2932 | fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { | 2937 | fn 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; |
| 2934 | 2939 |
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), | ||
| 540 | 541 | ||
| 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 | } |
| 1793 | 1794 | ||
| 1795 | fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void { | ||
| 1796 | _ = inst; | ||
| 1797 | return self.fail("TODO implement airCmpVector for {}", .{self.target.cpu.arch}); | ||
| 1798 | } | ||
| 1799 | |||
| 1794 | fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { | 1800 | fn 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; |
| 1796 | 1802 |
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), | ||
| 1312 | 1313 | ||
| 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 | } |
| 2224 | 2225 | ||
| 2226 | fn airCmpVector(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ||
| 2227 | _ = inst; | ||
| 2228 | return self.fail("TODO implement airCmpVector for wasm", .{}); | ||
| 2229 | } | ||
| 2230 | |||
| 2225 | fn airBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | 2231 | fn 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), | ||
| 661 | 662 | ||
| 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 | } |
| 3701 | 3702 | ||
| 3703 | fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void { | ||
| 3704 | _ = inst; | ||
| 3705 | return self.fail("TODO implement airCmpVector for {}", .{self.target.cpu.arch}); | ||
| 3706 | } | ||
| 3707 | |||
| 3702 | fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { | 3708 | fn 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, "!((", "!="), |
| 1717 | 1717 | ||
| 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 operations | 1720 | // 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), | ||
| 3378 | 3379 | ||
| 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 | } |
| 3642 | 3643 | ||
| 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), | ||
| 269 | 270 | ||
| 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 | } |
| 404 | 405 | ||
| 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; |
| 407 | 418 |