mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
x86_64: rewrite scalar @truncate
This commit is contained in:
parent
b0ed602d5d
commit
c58e60a042
@ -1793,9 +1793,13 @@ pub const Mutable = struct {
|
|||||||
/// The upper bound is `calcTwosCompLimbCount(a.len)`.
|
/// The upper bound is `calcTwosCompLimbCount(a.len)`.
|
||||||
pub fn truncate(r: *Mutable, a: Const, signedness: Signedness, bit_count: usize) void {
|
pub fn truncate(r: *Mutable, a: Const, signedness: Signedness, bit_count: usize) void {
|
||||||
const req_limbs = calcTwosCompLimbCount(bit_count);
|
const req_limbs = calcTwosCompLimbCount(bit_count);
|
||||||
|
const abs_trunc_a: Const = .{
|
||||||
|
.positive = true,
|
||||||
|
.limbs = a.limbs[0..@min(a.limbs.len, req_limbs)],
|
||||||
|
};
|
||||||
|
|
||||||
// Handle 0-bit integers.
|
// Handle 0-bit integers.
|
||||||
if (req_limbs == 0 or a.eqlZero()) {
|
if (req_limbs == 0 or abs_trunc_a.eqlZero()) {
|
||||||
r.set(0);
|
r.set(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1810,15 +1814,10 @@ pub const Mutable = struct {
|
|||||||
// Note, we simply take req_limbs * @bitSizeOf(Limb) as the
|
// Note, we simply take req_limbs * @bitSizeOf(Limb) as the
|
||||||
// target bit count.
|
// target bit count.
|
||||||
|
|
||||||
r.addScalar(a.abs(), -1);
|
r.addScalar(abs_trunc_a, -1);
|
||||||
|
|
||||||
// Zero-extend the result
|
// Zero-extend the result
|
||||||
if (req_limbs > r.len) {
|
|
||||||
@memset(r.limbs[r.len..req_limbs], 0);
|
@memset(r.limbs[r.len..req_limbs], 0);
|
||||||
}
|
|
||||||
|
|
||||||
// Truncate to required number of limbs.
|
|
||||||
assert(r.limbs.len >= req_limbs);
|
|
||||||
r.len = req_limbs;
|
r.len = req_limbs;
|
||||||
|
|
||||||
// Without truncating, we can already peek at the sign bit of the result here.
|
// Without truncating, we can already peek at the sign bit of the result here.
|
||||||
@ -1846,16 +1845,10 @@ pub const Mutable = struct {
|
|||||||
r.normalize(r.len);
|
r.normalize(r.len);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (a.limbs.len < req_limbs) {
|
r.copy(abs_trunc_a);
|
||||||
// Integer fits within target bits, no wrapping required.
|
// If the integer fits within target bits, no wrapping is required.
|
||||||
r.copy(a);
|
if (r.len < req_limbs) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
r.copy(.{
|
|
||||||
.positive = a.positive,
|
|
||||||
.limbs = a.limbs[0..req_limbs],
|
|
||||||
});
|
|
||||||
r.limbs[r.len - 1] &= mask;
|
r.limbs[r.len - 1] &= mask;
|
||||||
r.normalize(r.len);
|
r.normalize(r.len);
|
||||||
|
|
||||||
|
|||||||
@ -1934,6 +1934,31 @@ test "truncate multi unsigned many" {
|
|||||||
try testing.expect((try b.toInt(i1)) == 0);
|
try testing.expect((try b.toInt(i1)) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "truncate to mutable with fewer limbs" {
|
||||||
|
var res_limbs: [1]Limb = undefined;
|
||||||
|
var res: Mutable = .{
|
||||||
|
.limbs = &res_limbs,
|
||||||
|
.len = undefined,
|
||||||
|
.positive = undefined,
|
||||||
|
};
|
||||||
|
res.truncate(.{ .positive = true, .limbs = &.{ 0, 1 } }, .unsigned, @bitSizeOf(Limb));
|
||||||
|
try testing.expect(res.eqlZero());
|
||||||
|
res.truncate(.{ .positive = true, .limbs = &.{ 0, 1 } }, .signed, @bitSizeOf(Limb));
|
||||||
|
try testing.expect(res.eqlZero());
|
||||||
|
res.truncate(.{ .positive = false, .limbs = &.{ 0, 1 } }, .unsigned, @bitSizeOf(Limb));
|
||||||
|
try testing.expect(res.eqlZero());
|
||||||
|
res.truncate(.{ .positive = false, .limbs = &.{ 0, 1 } }, .signed, @bitSizeOf(Limb));
|
||||||
|
try testing.expect(res.eqlZero());
|
||||||
|
res.truncate(.{ .positive = true, .limbs = &.{ std.math.maxInt(Limb), 1 } }, .unsigned, @bitSizeOf(Limb));
|
||||||
|
try testing.expect(res.toConst().orderAgainstScalar(std.math.maxInt(Limb)).compare(.eq));
|
||||||
|
res.truncate(.{ .positive = true, .limbs = &.{ std.math.maxInt(Limb), 1 } }, .signed, @bitSizeOf(Limb));
|
||||||
|
try testing.expect(res.toConst().orderAgainstScalar(-1).compare(.eq));
|
||||||
|
res.truncate(.{ .positive = false, .limbs = &.{ std.math.maxInt(Limb), 1 } }, .unsigned, @bitSizeOf(Limb));
|
||||||
|
try testing.expect(res.toConst().orderAgainstScalar(1).compare(.eq));
|
||||||
|
res.truncate(.{ .positive = false, .limbs = &.{ std.math.maxInt(Limb), 1 } }, .signed, @bitSizeOf(Limb));
|
||||||
|
try testing.expect(res.toConst().orderAgainstScalar(1).compare(.eq));
|
||||||
|
}
|
||||||
|
|
||||||
test "saturate single signed positive" {
|
test "saturate single signed positive" {
|
||||||
var a = try Managed.initSet(testing.allocator, 0xBBBB_BBBB);
|
var a = try Managed.initSet(testing.allocator, 0xBBBB_BBBB);
|
||||||
defer a.deinit();
|
defer a.deinit();
|
||||||
|
|||||||
@ -573,7 +573,7 @@ pub const Inst = struct {
|
|||||||
/// and the operand is not a valid value of this type; i.e. equivalent to
|
/// and the operand is not a valid value of this type; i.e. equivalent to
|
||||||
/// a safety check based on `.is_named_enum_value`
|
/// a safety check based on `.is_named_enum_value`
|
||||||
intcast_safe,
|
intcast_safe,
|
||||||
/// Truncate higher bits from an integer, resulting in an integer with the same
|
/// Truncate higher bits from an integer, resulting in an integer type with the same
|
||||||
/// sign but an equal or smaller number of bits.
|
/// sign but an equal or smaller number of bits.
|
||||||
/// Uses the `ty_op` field.
|
/// Uses the `ty_op` field.
|
||||||
trunc,
|
trunc,
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -702,6 +702,7 @@ pub const Memory = struct {
|
|||||||
pub const Size = enum(u4) {
|
pub const Size = enum(u4) {
|
||||||
none,
|
none,
|
||||||
ptr,
|
ptr,
|
||||||
|
gpr,
|
||||||
byte,
|
byte,
|
||||||
word,
|
word,
|
||||||
dword,
|
dword,
|
||||||
@ -742,6 +743,11 @@ pub const Memory = struct {
|
|||||||
return switch (s) {
|
return switch (s) {
|
||||||
.none => 0,
|
.none => 0,
|
||||||
.ptr => target.ptrBitWidth(),
|
.ptr => target.ptrBitWidth(),
|
||||||
|
.gpr => switch (target.cpu.arch) {
|
||||||
|
else => unreachable,
|
||||||
|
.x86 => 32,
|
||||||
|
.x86_64 => 64,
|
||||||
|
},
|
||||||
.byte => 8,
|
.byte => 8,
|
||||||
.word => 16,
|
.word => 16,
|
||||||
.dword => 32,
|
.dword => 32,
|
||||||
@ -763,7 +769,7 @@ pub const Memory = struct {
|
|||||||
try writer.writeAll(@tagName(s));
|
try writer.writeAll(@tagName(s));
|
||||||
switch (s) {
|
switch (s) {
|
||||||
.none => unreachable,
|
.none => unreachable,
|
||||||
.ptr => {},
|
.ptr, .gpr => {},
|
||||||
else => {
|
else => {
|
||||||
try writer.writeByte(' ');
|
try writer.writeByte(' ');
|
||||||
try writer.writeAll("ptr");
|
try writer.writeAll("ptr");
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user