stage2 AArch64: fix shl, shr, shl_exact, shr_exact

Introduces the necessary truncation after shift
This commit is contained in:
joachimschmidt557 2022-04-18 13:50:54 +02:00
parent cbb13c023e
commit fa85a739d9
No known key found for this signature in database
GPG Key ID: E0B575BE2884ACC5
2 changed files with 42 additions and 17 deletions

View File

@ -1138,6 +1138,8 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
} },
});
try self.truncRegister(dest_reg, dest_reg, int_info.signedness, int_info.bits);
break :result MCValue{ .register = dest_reg };
} else {
return self.fail("TODO AArch64 not on integers > u64/i64", .{});
@ -1516,11 +1518,8 @@ fn binOp(
const int_info = lhs_ty.intInfo(self.target.*);
if (int_info.bits <= 64) {
const result_reg = result.register;
if (int_info.bits < 64) {
try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
return result;
} else return result;
try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
return result;
} else {
return self.fail("TODO binary operations on integers > u64/i64", .{});
}
@ -1554,8 +1553,8 @@ fn binOp(
else => unreachable,
}
},
.shl,
.shr,
.shl_exact,
.shr_exact,
=> {
switch (lhs_ty.zigTypeTag()) {
.Vector => return self.fail("TODO binary operations on vectors", .{}),
@ -1565,16 +1564,16 @@ fn binOp(
const rhs_immediate_ok = rhs == .immediate;
const mir_tag_register: Mir.Inst.Tag = switch (tag) {
.shl => .lsl_register,
.shr => switch (lhs_ty.intInfo(self.target.*).signedness) {
.shl_exact => .lsl_register,
.shr_exact => switch (int_info.signedness) {
.signed => Mir.Inst.Tag.asr_register,
.unsigned => Mir.Inst.Tag.lsr_register,
},
else => unreachable,
};
const mir_tag_immediate: Mir.Inst.Tag = switch (tag) {
.shl => .lsl_immediate,
.shr => switch (lhs_ty.intInfo(self.target.*).signedness) {
.shl_exact => .lsl_immediate,
.shr_exact => switch (int_info.signedness) {
.signed => Mir.Inst.Tag.asr_immediate,
.unsigned => Mir.Inst.Tag.lsr_immediate,
},
@ -1593,6 +1592,38 @@ fn binOp(
else => unreachable,
}
},
.shl,
.shr,
=> {
const base_tag: Air.Inst.Tag = switch (tag) {
.shl => .shl_exact,
.shr => .shr_exact,
else => unreachable,
};
// Generate a shl_exact/shr_exact
const result = try self.binOp(base_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
// Truncate if necessary
switch (tag) {
.shr => return result,
.shl => switch (lhs_ty.zigTypeTag()) {
.Vector => return self.fail("TODO binary operations on vectors", .{}),
.Int => {
const int_info = lhs_ty.intInfo(self.target.*);
if (int_info.bits <= 64) {
const result_reg = result.register;
try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
return result;
} else {
return self.fail("TODO binary operations on integers > u64/i64", .{});
}
},
else => unreachable,
},
else => unreachable,
}
},
.bool_and,
.bool_or,
=> {

View File

@ -363,7 +363,6 @@ fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int
test "binary not" {
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_aarch64) return error.SkipZigTest; // TODO
try expect(comptime x: {
break :x ~@as(u16, 0b1010101010101010) == 0b0101010101010101;
@ -851,8 +850,6 @@ test "quad hex float literal parsing accurate" {
}
test "truncating shift left" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
try testShlTrunc(maxInt(u16));
comptime try testShlTrunc(maxInt(u16));
}
@ -863,7 +860,6 @@ fn testShlTrunc(x: u16) !void {
test "exact shift left" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
try testShlExact(0b00110101);
comptime try testShlExact(0b00110101);
@ -875,7 +871,6 @@ fn testShlExact(x: u8) !void {
test "exact shift right" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
try testShrExact(0b10110100);
comptime try testShrExact(0b10110100);
@ -887,7 +882,6 @@ fn testShrExact(x: u8) !void {
test "shift left/right on u0 operand" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
const S = struct {
fn doTheTest() !void {