From 0b0298aff27a31a7f45828d96d95adfdde61a085 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sun, 5 Mar 2023 02:06:53 -0500 Subject: [PATCH] CBE: implement select and shuffle --- src/codegen/c.zig | 79 +++++++++++++++++++++++++++++++++++++-- test/behavior/select.zig | 2 - test/behavior/shuffle.zig | 2 - test/behavior/vector.zig | 2 - 4 files changed, 75 insertions(+), 10 deletions(-) diff --git a/src/codegen/c.zig b/src/codegen/c.zig index f5309918bf..5e64823a0d 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -6584,15 +6584,86 @@ fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue { } fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue { - if (f.liveness.isUnused(inst)) return .none; + const pl_op = f.air.instructions.items(.data)[inst].pl_op; + const extra = f.air.extraData(Air.Bin, pl_op.payload).data; - return f.fail("TODO: C backend: implement airSelect", .{}); + if (f.liveness.isUnused(inst)) { + try reap(f, inst, &.{ pl_op.operand, extra.lhs, extra.rhs }); + return .none; + } + + const pred = try f.resolveInst(pl_op.operand); + const lhs = try f.resolveInst(extra.lhs); + const rhs = try f.resolveInst(extra.rhs); + try reap(f, inst, &.{ pl_op.operand, extra.lhs, extra.rhs }); + + const inst_ty = f.air.typeOfIndex(inst); + + const writer = f.object.writer(); + const local = try f.allocLocal(inst, inst_ty); + const v = try Vectorizer.start(f, inst, writer, inst_ty); + try f.writeCValue(writer, local, .Other); + try v.elem(f, writer); + try writer.writeAll(" = "); + try f.writeCValue(writer, pred, .Other); + try v.elem(f, writer); + try writer.writeAll(" ? "); + try f.writeCValue(writer, lhs, .Other); + try v.elem(f, writer); + try writer.writeAll(" : "); + try f.writeCValue(writer, rhs, .Other); + try v.elem(f, writer); + try writer.writeAll(";\n"); + try v.end(f, inst, writer); + + return local; } fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { - if (f.liveness.isUnused(inst)) return .none; + const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; + const extra = f.air.extraData(Air.Shuffle, ty_pl.payload).data; - return f.fail("TODO: C backend: implement airShuffle", .{}); + if (f.liveness.isUnused(inst)) { + try reap(f, inst, &.{ extra.a, extra.b }); + return .none; + } + + const mask = f.air.values[extra.mask]; + const lhs = try f.resolveInst(extra.a); + const rhs = try f.resolveInst(extra.b); + + const module = f.object.dg.module; + const target = module.getTarget(); + const inst_ty = f.air.typeOfIndex(inst); + + const writer = f.object.writer(); + const local = try f.allocLocal(inst, inst_ty); + try reap(f, inst, &.{ extra.a, extra.b }); // local cannot alias operands + for (0..extra.mask_len) |index| { + var dst_pl = Value.Payload.U64{ + .base = .{ .tag = .int_u64 }, + .data = @intCast(u64, index), + }; + + try f.writeCValue(writer, local, .Other); + try writer.writeByte('['); + try f.object.dg.renderValue(writer, Type.usize, Value.initPayload(&dst_pl.base), .Other); + try writer.writeAll("] = "); + + var buf: Value.ElemValueBuffer = undefined; + const mask_elem = mask.elemValueBuffer(module, index, &buf).toSignedInt(target); + var src_pl = Value.Payload.U64{ + .base = .{ .tag = .int_u64 }, + .data = @intCast(u64, mask_elem ^ mask_elem >> 63), + }; + + try f.writeCValue(writer, if (mask_elem >= 0) lhs else rhs, .Other); + try writer.writeByte('['); + try f.object.dg.renderValue(writer, Type.usize, Value.initPayload(&src_pl.base), .Other); + try writer.writeAll("];\n"); + } + + return local; } fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { diff --git a/test/behavior/select.zig b/test/behavior/select.zig index d09683b67c..73d69c6530 100644 --- a/test/behavior/select.zig +++ b/test/behavior/select.zig @@ -4,7 +4,6 @@ const mem = std.mem; const expect = std.testing.expect; test "@select vectors" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO @@ -33,7 +32,6 @@ fn selectVectors() !void { } test "@select arrays" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO diff --git a/test/behavior/shuffle.zig b/test/behavior/shuffle.zig index bcc4618aee..b591aee2e2 100644 --- a/test/behavior/shuffle.zig +++ b/test/behavior/shuffle.zig @@ -8,7 +8,6 @@ test "@shuffle int" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { @@ -50,7 +49,6 @@ test "@shuffle bool 1" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index 5d569bd815..816bd6c23a 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -804,7 +804,6 @@ test "vector @reduce comptime" { test "mask parameter of @shuffle is comptime scope" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO @@ -1212,7 +1211,6 @@ test "modRem with zero divisor" { test "array operands to shuffle are coerced to vectors" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO