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.
This commit is contained in:
committed by
Andrew Kelley
parent
862e63f535
commit
0f48307041
19
src/Air.zig
19
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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
14
src/Sema.zig
14
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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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).?;
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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, " | "),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user