authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-05-29 18:10:00-07:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-07-14 23:02:32-07:00
log27ceb4ae3719522e2eb519ba1cd67303ae2e7259
treed9711f307447e7145cee7c4abac2a800f1079d24
parent0460572899482f7aa7ec6d9d177ed48984802c80
signaturelock-open Commit is signed but in an unrecognized format.

riscv implement `@sqrt` for f32/f64


3 files changed, 59 insertions(+), 9 deletions(-)

src/arch/riscv64/CodeGen.zig+59-7
...@@ -1275,7 +1275,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1275,7 +1275,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1275 .round,1275 .round,
1276 .trunc_float,1276 .trunc_float,
1277 .neg,1277 .neg,
1278 => try func.airUnaryMath(inst),1278 => try func.airUnaryMath(inst, tag),
12791279
1280 .add_with_overflow => try func.airAddWithOverflow(inst),1280 .add_with_overflow => try func.airAddWithOverflow(inst),
1281 .sub_with_overflow => try func.airSubWithOverflow(inst),1281 .sub_with_overflow => try func.airSubWithOverflow(inst),
...@@ -3741,13 +3741,65 @@ fn airBitReverse(func: *Func, inst: Air.Inst.Index) !void {...@@ -3741,13 +3741,65 @@ fn airBitReverse(func: *Func, inst: Air.Inst.Index) !void {
3741 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });3741 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3742}3742}
37433743
3744fn airUnaryMath(func: *Func, inst: Air.Inst.Index) !void {3744fn airUnaryMath(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
3745 const tag = func.air.instructions.items(.tag)[@intFromEnum(inst)];3745 const zcu = func.bin_file.comp.module.?;
3746 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;3746 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
3747 const result: MCValue = if (func.liveness.isUnused(inst))3747 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3748 .unreach3748 const ty = func.typeOf(un_op);
3749 else3749
3750 return func.fail("TODO implementairUnaryMath {s} for {}", .{ @tagName(tag), func.target.cpu.arch });3750 const operand = try func.resolveInst(un_op);
3751 const operand_bit_size = ty.bitSize(zcu);
3752
3753 if (!math.isPowerOfTwo(operand_bit_size))
3754 return func.fail("TODO: airUnaryMath non-pow 2", .{});
3755
3756 const operand_reg, const operand_lock = try func.promoteReg(ty, operand);
3757 defer if (operand_lock) |lock| func.register_manager.unlockReg(lock);
3758
3759 const dst_class = func.typeRegClass(ty);
3760 const dst_reg, const dst_lock = try func.allocReg(dst_class);
3761 defer func.register_manager.unlockReg(dst_lock);
3762
3763 switch (ty.zigTypeTag(zcu)) {
3764 .Float => {
3765 assert(dst_class == .float);
3766
3767 switch (operand_bit_size) {
3768 16, 80, 128 => return func.fail("TODO: airUnaryMath Float bit-size {}", .{operand_bit_size}),
3769 32, 64 => {},
3770 else => unreachable,
3771 }
3772
3773 switch (tag) {
3774 .sqrt => {
3775 _ = try func.addInst(.{
3776 .tag = if (operand_bit_size == 64) .fsqrtd else .fsqrts,
3777 .ops = .rrr,
3778 .data = .{
3779 .r_type = .{
3780 .rd = dst_reg,
3781 .rs1 = operand_reg,
3782 .rs2 = .f0, // unused, spec says it's 0
3783 },
3784 },
3785 });
3786 },
3787 else => return func.fail("TODO: airUnaryMath Float {s}", .{@tagName(tag)}),
3788 }
3789 },
3790 .Int => {
3791 assert(dst_class == .int);
3792
3793 switch (tag) {
3794 else => return func.fail("TODO: airUnaryMath Float {s}", .{@tagName(tag)}),
3795 }
3796 },
3797 else => return func.fail("TODO: airUnaryMath ty: {}", .{ty.fmt(zcu)}),
3798 }
3799
3800 break :result MCValue{ .register = dst_reg };
3801 };
3802
3751 return func.finishAir(inst, result, .{ un_op, .none, .none });3803 return func.finishAir(inst, result, .{ un_op, .none, .none });
3752}3804}
37533805
test/behavior/eval.zig-1
...@@ -446,7 +446,6 @@ test "binary math operator in partially inlined function" {...@@ -446,7 +446,6 @@ test "binary math operator in partially inlined function" {
446 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO446 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
447 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO447 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
448 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO448 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
449 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
450449
451 var s: [4]u32 = undefined;450 var s: [4]u32 = undefined;
452 var b: [16]u8 = undefined;451 var b: [16]u8 = undefined;
test/behavior/floatop.zig-1
...@@ -281,7 +281,6 @@ test "@sqrt f32/f64" {...@@ -281,7 +281,6 @@ test "@sqrt f32/f64" {
281 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO281 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
282 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO282 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
283 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;283 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
284 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
285284
286 try testSqrt(f32);285 try testSqrt(f32);
287 try comptime testSqrt(f32);286 try comptime testSqrt(f32);