authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-05-25 14:15:21-07:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-06-13 02:22:06-07:00
logd69c48370a0381c7dce463c68b2097dd8fa67eb7
treea5f2fc954e7bd6b73164c8ef1c8742b5f2827649
parent206e66858c69cd667aad3779837493968bfcd228
signaturelock-open Commit is signed but in an unrecognized format.

riscv: integer + float `@abs`


8 files changed, 112 insertions(+), 11 deletions(-)

src/arch/riscv64/CodeGen.zig+68-3
...@@ -3377,18 +3377,83 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {...@@ -3377,18 +3377,83 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {
3377 const ty = func.typeOf(ty_op.operand);3377 const ty = func.typeOf(ty_op.operand);
3378 const scalar_ty = ty.scalarType(zcu);3378 const scalar_ty = ty.scalarType(zcu);
3379 const operand = try func.resolveInst(ty_op.operand);3379 const operand = try func.resolveInst(ty_op.operand);
3380 _ = operand;
33813380
3382 switch (scalar_ty.zigTypeTag(zcu)) {3381 switch (scalar_ty.zigTypeTag(zcu)) {
3383 .Int => if (ty.zigTypeTag(zcu) == .Vector) {3382 .Int => if (ty.zigTypeTag(zcu) == .Vector) {
3384 return func.fail("TODO implement airAbs for {}", .{ty.fmt(zcu)});3383 return func.fail("TODO implement airAbs for {}", .{ty.fmt(zcu)});
3385 } else {3384 } else {
3386 return func.fail("TODO: implement airAbs for Int", .{});3385 const return_mcv = try func.copyToNewRegister(inst, operand);
3386 const operand_reg = return_mcv.register;
3387
3388 const temp_reg, const temp_lock = try func.allocReg(.int);
3389 defer func.register_manager.unlockReg(temp_lock);
3390
3391 _ = try func.addInst(.{
3392 .tag = .srai,
3393 .ops = .rri,
3394 .data = .{ .i_type = .{
3395 .rd = temp_reg,
3396 .rs1 = operand_reg,
3397 .imm12 = Immediate.s(63),
3398 } },
3399 });
3400
3401 _ = try func.addInst(.{
3402 .tag = .xor,
3403 .ops = .rrr,
3404 .data = .{ .r_type = .{
3405 .rd = operand_reg,
3406 .rs1 = operand_reg,
3407 .rs2 = temp_reg,
3408 } },
3409 });
3410
3411 _ = try func.addInst(.{
3412 .tag = .sub,
3413 .ops = .rrr,
3414 .data = .{ .r_type = .{
3415 .rd = operand_reg,
3416 .rs1 = operand_reg,
3417 .rs2 = temp_reg,
3418 } },
3419 });
3420
3421 break :result return_mcv;
3422 },
3423 .Float => {
3424 const float_bits = scalar_ty.floatBits(zcu.getTarget());
3425 switch (float_bits) {
3426 16 => return func.fail("TODO: airAbs 16-bit float", .{}),
3427 32 => {},
3428 64 => {},
3429 80 => return func.fail("TODO: airAbs 80-bit float", .{}),
3430 128 => return func.fail("TODO: airAbs 128-bit float", .{}),
3431 else => unreachable,
3432 }
3433
3434 const return_mcv = try func.copyToNewRegister(inst, operand);
3435 const operand_reg = return_mcv.register;
3436
3437 assert(operand_reg.class() == .float);
3438
3439 _ = try func.addInst(.{
3440 .tag = .pseudo,
3441 .ops = .pseudo_fabs,
3442 .data = .{
3443 .fabs = .{
3444 .rd = operand_reg,
3445 .rs = operand_reg,
3446 .bits = float_bits,
3447 },
3448 },
3449 });
3450
3451 break :result return_mcv;
3387 },3452 },
3388 else => return func.fail("TODO: implement airAbs {}", .{scalar_ty.fmt(zcu)}),3453 else => return func.fail("TODO: implement airAbs {}", .{scalar_ty.fmt(zcu)}),
3389 }3454 }
33903455
3391 break :result .{.unreach};3456 break :result .unreach;
3392 };3457 };
3393 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });3458 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3394}3459}
src/arch/riscv64/Encoding.zig+8
...@@ -130,6 +130,7 @@ pub const Mnemonic = enum {...@@ -130,6 +130,7 @@ pub const Mnemonic = enum {
130 fles,130 fles,
131131
132 fsgnjns,132 fsgnjns,
133 fsgnjxs,
133134
134 // D extension (64-bit float)135 // D extension (64-bit float)
135 faddd,136 faddd,
...@@ -150,6 +151,7 @@ pub const Mnemonic = enum {...@@ -150,6 +151,7 @@ pub const Mnemonic = enum {
150 fled,151 fled,
151152
152 fsgnjnd,153 fsgnjnd,
154 fsgnjxd,
153155
154 pub fn encoding(mnem: Mnemonic) Enc {156 pub fn encoding(mnem: Mnemonic) Enc {
155 return switch (mnem) {157 return switch (mnem) {
...@@ -218,6 +220,9 @@ pub const Mnemonic = enum {...@@ -218,6 +220,9 @@ pub const Mnemonic = enum {
218 .fsgnjns => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b000 } } },220 .fsgnjns => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b000 } } },
219 .fsgnjnd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b000 } } },221 .fsgnjnd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b000 } } },
220222
223 .fsgnjxs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b0010} } },
224 .fsgnjxd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b0010} } },
225
221226
222 // LOAD227 // LOAD
223228
...@@ -392,6 +397,9 @@ pub const InstEnc = enum {...@@ -392,6 +397,9 @@ pub const InstEnc = enum {
392397
393 .fsgnjns,398 .fsgnjns,
394 .fsgnjnd,399 .fsgnjnd,
400
401 .fsgnjxs,
402 .fsgnjxd,
395 => .R,403 => .R,
396404
397 .ecall,405 .ecall,
src/arch/riscv64/Lower.zig+20
...@@ -208,6 +208,26 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -208,6 +208,26 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
208 });208 });
209 },209 },
210210
211 .pseudo_fabs => {
212 const fabs = inst.data.fabs;
213 assert(fabs.rs.class() == .float and fabs.rd.class() == .float);
214
215 const mnem: Encoding.Mnemonic = switch (fabs.bits) {
216 16 => return lower.fail("TODO: airAbs Float 16", .{}),
217 32 => .fsgnjxs,
218 64 => .fsgnjxd,
219 80 => return lower.fail("TODO: airAbs Float 80", .{}),
220 128 => return lower.fail("TODO: airAbs Float 128", .{}),
221 else => unreachable,
222 };
223
224 try lower.emit(mnem, &.{
225 .{ .reg = fabs.rs },
226 .{ .reg = fabs.rd },
227 .{ .reg = fabs.rd },
228 });
229 },
230
211 .pseudo_compare => {231 .pseudo_compare => {
212 const compare = inst.data.compare;232 const compare = inst.data.compare;
213 const op = compare.op;233 const op = compare.op;
src/arch/riscv64/Mir.zig+13
...@@ -76,6 +76,8 @@ pub const Inst = struct {...@@ -76,6 +76,8 @@ pub const Inst = struct {
76 fmuls,76 fmuls,
77 fdivs,77 fdivs,
7878
79 fabss,
80
79 fmins,81 fmins,
80 fmaxs,82 fmaxs,
8183
...@@ -94,6 +96,8 @@ pub const Inst = struct {...@@ -94,6 +96,8 @@ pub const Inst = struct {
94 fmuld,96 fmuld,
95 fdivd,97 fdivd,
9698
99 fabsd,
100
97 fmind,101 fmind,
98 fmaxd,102 fmaxd,
99103
...@@ -194,6 +198,12 @@ pub const Inst = struct {...@@ -194,6 +198,12 @@ pub const Inst = struct {
194 rs: Register,198 rs: Register,
195 },199 },
196200
201 fabs: struct {
202 rd: Register,
203 rs: Register,
204 bits: u16,
205 },
206
197 compare: struct {207 compare: struct {
198 rd: Register,208 rd: Register,
199 rs1: Register,209 rs1: Register,
...@@ -273,6 +283,9 @@ pub const Inst = struct {...@@ -273,6 +283,9 @@ pub const Inst = struct {
273 /// Jumps. Uses `inst` payload.283 /// Jumps. Uses `inst` payload.
274 pseudo_j,284 pseudo_j,
275285
286 /// Floating point absolute value.
287 pseudo_fabs,
288
276 /// Dead inst, ignored by the emitter.289 /// Dead inst, ignored by the emitter.
277 pseudo_dead,290 pseudo_dead,
278291
test/behavior/abs.zig+3-5
...@@ -6,7 +6,6 @@ test "@abs integers" {...@@ -6,7 +6,6 @@ test "@abs integers" {
6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
109
11 try comptime testAbsIntegers();10 try comptime testAbsIntegers();
12 try testAbsIntegers();11 try testAbsIntegers();
...@@ -93,18 +92,17 @@ test "@abs floats" {...@@ -93,18 +92,17 @@ test "@abs floats" {
93 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO92 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
94 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO93 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
95 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;94 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
96 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
9795
98 try comptime testAbsFloats(f16);96 try comptime testAbsFloats(f16);
99 try testAbsFloats(f16);97 if (builtin.zig_backend != .stage2_riscv64) try testAbsFloats(f16);
100 try comptime testAbsFloats(f32);98 try comptime testAbsFloats(f32);
101 try testAbsFloats(f32);99 try testAbsFloats(f32);
102 try comptime testAbsFloats(f64);100 try comptime testAbsFloats(f64);
103 try testAbsFloats(f64);101 try testAbsFloats(f64);
104 try comptime testAbsFloats(f80);102 try comptime testAbsFloats(f80);
105 if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64) try testAbsFloats(f80);103 if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64 and builtin.zig_backend != .stage2_riscv64) try testAbsFloats(f80);
106 try comptime testAbsFloats(f128);104 try comptime testAbsFloats(f128);
107 if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64) try testAbsFloats(f128);105 if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64 and builtin.zig_backend != .stage2_riscv64) try testAbsFloats(f128);
108}106}
109107
110fn testAbsFloats(comptime T: type) !void {108fn testAbsFloats(comptime T: type) !void {
test/behavior/cast.zig-1
...@@ -2608,7 +2608,6 @@ test "@as does not corrupt values with incompatible representations" {...@@ -2608,7 +2608,6 @@ test "@as does not corrupt values with incompatible representations" {
2608 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2608 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2609 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2609 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2610 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;2610 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
2611 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
26122611
2613 const x: f32 = @as(f16, blk: {2612 const x: f32 = @as(f16, blk: {
2614 if (false) {2613 if (false) {
test/behavior/floatop.zig-1
...@@ -999,7 +999,6 @@ test "@abs f32/f64" {...@@ -999,7 +999,6 @@ test "@abs f32/f64" {
999 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO999 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1000 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1000 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1001 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1001 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1002 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10031002
1004 try testFabs(f32);1003 try testFabs(f32);
1005 try comptime testFabs(f32);1004 try comptime testFabs(f32);
test/behavior/math.zig-1
...@@ -1814,7 +1814,6 @@ test "absFloat" {...@@ -1814,7 +1814,6 @@ test "absFloat" {
1814 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1814 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1815 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1815 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1816 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1816 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1817 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
18181817
1819 try testAbsFloat();1818 try testAbsFloat();
1820 try comptime testAbsFloat();1819 try comptime testAbsFloat();