aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWilliam Sengir <william@sengir.com>2022-03-19 23:44:55 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-03-21 16:54:19 -0700
commit0f4830704171b734bb4a0235fc14809282457dc3 (patch)
treef14d426793b2878db30315195c068e6d28ca608d /src
parent862e63f535ec8d65e33ed7ea67eb9cf03bfc7d6a (diff)
downloadzig-0f4830704171b734bb4a0235fc14809282457dc3.tar.gz
zig-0f4830704171b734bb4a0235fc14809282457dc3.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/Air.zig19
-rw-r--r--src/Liveness.zig4
-rw-r--r--src/Sema.zig14
-rw-r--r--src/arch/aarch64/CodeGen.zig6
-rw-r--r--src/arch/arm/CodeGen.zig7
-rw-r--r--src/arch/riscv64/CodeGen.zig6
-rw-r--r--src/arch/wasm/CodeGen.zig6
-rw-r--r--src/arch/x86_64/CodeGen.zig6
-rw-r--r--src/codegen/c.zig2
-rw-r--r--src/codegen/llvm.zig6
-rw-r--r--src/print_air.zig11
11 files changed, 86 insertions, 1 deletions
diff --git a/src/Air.zig b/src/Air.zig
index 2d717f442d..8c24108abd 100644
--- a/src/Air.zig
+++ b/src/Air.zig
@@ -308,6 +308,10 @@ pub const Inst = struct {
/// `!=`. Result type is always bool.
/// Uses the `bin_op` field.
cmp_neq,
+ /// Conditional between two vectors.
+ /// Result type is always a vector of bools.
+ /// Uses the `ty_pl` field, payload is `VectorCmp`.
+ cmp_vector,
/// Conditional branch.
/// Result type is always noreturn; no instructions in a block follow this one.
@@ -781,6 +785,20 @@ pub const Shuffle = struct {
mask_len: u32,
};
+pub const VectorCmp = struct {
+ lhs: Inst.Ref,
+ rhs: Inst.Ref,
+ op: u32,
+
+ pub fn compareOperator(self: VectorCmp) std.math.CompareOperator {
+ return @intToEnum(std.math.CompareOperator, @truncate(u3, self.op));
+ }
+
+ pub fn encodeOp(compare_operator: std.math.CompareOperator) u32 {
+ return @enumToInt(compare_operator);
+ }
+};
+
/// Trailing:
/// 0. `Inst.Ref` for every outputs_len
/// 1. `Inst.Ref` for every inputs_len
@@ -942,6 +960,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
.aggregate_init,
.union_init,
.field_parent_ptr,
+ .cmp_vector,
=> return air.getRefType(datas[inst].ty_pl.ty),
.not,
diff --git a/src/Liveness.zig b/src/Liveness.zig
index dd93d44f72..79521e7a94 100644
--- a/src/Liveness.zig
+++ b/src/Liveness.zig
@@ -441,6 +441,10 @@ fn analyzeInst(
const reduce = inst_datas[inst].reduce;
return trackOperands(a, new_set, inst, main_tomb, .{ reduce.operand, .none, .none });
},
+ .cmp_vector => {
+ const extra = a.air.extraData(Air.VectorCmp, inst_datas[inst].ty_pl.payload).data;
+ return trackOperands(a, new_set, inst, main_tomb, .{ extra.lhs, extra.rhs, .none });
+ },
.aggregate_init => {
const ty_pl = inst_datas[inst].ty_pl;
const aggregate_ty = a.air.getRefType(ty_pl.ty);
diff --git a/src/Sema.zig b/src/Sema.zig
index 7674121ba6..20622cb98a 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -397,6 +397,20 @@ pub const Block = struct {
});
}
+ 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 {
+ return block.addInst(.{
+ .tag = .cmp_vector,
+ .data = .{ .ty_pl = .{
+ .ty = vector_ty,
+ .payload = try block.sema.addExtra(Air.VectorCmp{
+ .lhs = lhs,
+ .rhs = rhs,
+ .op = Air.VectorCmp.encodeOp(cmp_op),
+ }),
+ } },
+ });
+ }
+
fn addAggregateInit(
block: *Block,
aggregate_ty: Type,
diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig
index c9121c8859..9c2d5890a7 100644
--- a/src/arch/aarch64/CodeGen.zig
+++ b/src/arch/aarch64/CodeGen.zig
@@ -577,6 +577,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.cmp_gte => try self.airCmp(inst, .gte),
.cmp_gt => try self.airCmp(inst, .gt),
.cmp_neq => try self.airCmp(inst, .neq),
+ .cmp_vector => try self.airCmpVector(inst),
.bool_and => try self.airBinOp(inst),
.bool_or => try self.airBinOp(inst),
@@ -2713,6 +2714,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
}
+fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {
+ _ = inst;
+ return self.fail("TODO implement airCmpVector for {}", .{self.target.cpu.arch});
+}
+
fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig
index 921bc92c72..0b9f9eb2e2 100644
--- a/src/arch/arm/CodeGen.zig
+++ b/src/arch/arm/CodeGen.zig
@@ -567,6 +567,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.cmp_gte => try self.airCmp(inst, .gte),
.cmp_gt => try self.airCmp(inst, .gt),
.cmp_neq => try self.airCmp(inst, .neq),
+ .cmp_vector => try self.airCmpVector(inst),
.bool_and => try self.airBinOp(inst),
.bool_or => try self.airBinOp(inst),
@@ -2894,7 +2895,6 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
const lhs_ty = self.air.typeOf(bin_op.lhs);
switch (lhs_ty.zigTypeTag()) {
- .Vector => return self.fail("TODO ARM cmp vectors", .{}),
.Optional => return self.fail("TODO ARM cmp optionals", .{}),
.Float => return self.fail("TODO ARM cmp floats", .{}),
.Int, .Bool, .Pointer, .ErrorSet, .Enum => {
@@ -2929,6 +2929,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
}
+fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {
+ _ = inst;
+ return self.fail("TODO implement airCmpVector for {}", .{self.target.cpu.arch});
+}
+
fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig
index 14beedd2a9..3b73fef51f 100644
--- a/src/arch/riscv64/CodeGen.zig
+++ b/src/arch/riscv64/CodeGen.zig
@@ -537,6 +537,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.cmp_gte => try self.airCmp(inst, .gte),
.cmp_gt => try self.airCmp(inst, .gt),
.cmp_neq => try self.airCmp(inst, .neq),
+ .cmp_vector => try self.airCmpVector(inst),
.bool_and => try self.airBoolOp(inst),
.bool_or => try self.airBoolOp(inst),
@@ -1791,6 +1792,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
// return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
}
+fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {
+ _ = inst;
+ return self.fail("TODO implement airCmpVector for {}", .{self.target.cpu.arch});
+}
+
fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig
index c60c321572..8d515e9365 100644
--- a/src/arch/wasm/CodeGen.zig
+++ b/src/arch/wasm/CodeGen.zig
@@ -1309,6 +1309,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.cmp_lte => self.airCmp(inst, .lte),
.cmp_lt => self.airCmp(inst, .lt),
.cmp_neq => self.airCmp(inst, .neq),
+ .cmp_vector => self.airCmpVector(inst),
.array_elem_val => self.airArrayElemVal(inst),
.array_to_slice => self.airArrayToSlice(inst),
@@ -2222,6 +2223,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: std.math.CompareOperator) Inner
return cmp_tmp;
}
+fn airCmpVector(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
+ _ = inst;
+ return self.fail("TODO implement airCmpVector for wasm", .{});
+}
+
fn airBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const br = self.air.instructions.items(.data)[inst].br;
const block = self.blocks.get(br.block_inst).?;
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index 72f12cf4e9..598511a631 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -658,6 +658,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.cmp_gte => try self.airCmp(inst, .gte),
.cmp_gt => try self.airCmp(inst, .gt),
.cmp_neq => try self.airCmp(inst, .neq),
+ .cmp_vector => try self.airCmpVector(inst),
.bool_and => try self.airBoolOp(inst),
.bool_or => try self.airBoolOp(inst),
@@ -3699,6 +3700,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
}
+fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {
+ _ = inst;
+ return self.fail("TODO implement airCmpVector for {}", .{self.target.cpu.arch});
+}
+
fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
const payload = try self.addExtra(Mir.DbgLineColumn{
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 23ccdc007b..f5a1036479 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -1715,6 +1715,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
.cmp_eq => try airEquality(f, inst, "((", "=="),
.cmp_neq => try airEquality(f, inst, "!((", "!="),
+ .cmp_vector => return f.fail("TODO: C backend: implement binary op for tag '{s}'", .{@tagName(Air.Inst.Tag.cmp_vector)}),
+
// bool_and and bool_or are non-short-circuit operations
.bool_and => try airBinOp(f, inst, " & "),
.bool_or => try airBinOp(f, inst, " | "),
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 139c1f25cb..edf8992c56 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -3375,6 +3375,7 @@ pub const FuncGen = struct {
.cmp_lt => try self.airCmp(inst, .lt),
.cmp_lte => try self.airCmp(inst, .lte),
.cmp_neq => try self.airCmp(inst, .neq),
+ .cmp_vector => try self.airCmpVector(inst),
.is_non_null => try self.airIsNonNull(inst, false, false, .NE),
.is_non_null_ptr => try self.airIsNonNull(inst, true , false, .NE),
@@ -3640,6 +3641,11 @@ pub const FuncGen = struct {
return self.cmp(lhs, rhs, operand_ty, op);
}
+ fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ _ = inst;
+ return self.todo("implement airCmpVector");
+ }
+
fn cmp(
self: *FuncGen,
lhs: *const llvm.Value,
diff --git a/src/print_air.zig b/src/print_air.zig
index f3ccc70a46..c6b27a6cd6 100644
--- a/src/print_air.zig
+++ b/src/print_air.zig
@@ -266,6 +266,7 @@ const Writer = struct {
.mul_add => try w.writeMulAdd(s, inst),
.shuffle => try w.writeShuffle(s, inst),
.reduce => try w.writeReduce(s, inst),
+ .cmp_vector => try w.writeCmpVector(s, inst),
.add_with_overflow,
.sub_with_overflow,
@@ -402,6 +403,16 @@ const Writer = struct {
try s.print(", {s}", .{@tagName(reduce.operation)});
}
+ fn writeCmpVector(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
+ const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
+ const extra = w.air.extraData(Air.VectorCmp, ty_pl.payload).data;
+
+ try s.print("{s}, ", .{@tagName(extra.compareOperator())});
+ try w.writeOperand(s, inst, 0, extra.lhs);
+ try s.writeAll(", ");
+ try w.writeOperand(s, inst, 1, extra.rhs);
+ }
+
fn writeFence(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
const atomic_order = w.air.instructions.items(.data)[inst].fence;