authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-09-27 11:18:33+01:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-09-27 18:30:52-04:00
log611c38e6daffc18bc044ebb1e20d161b4ef757f2
treef825f464e0bfcfdaf3d4894a7006af8edfb62dfd
parent77fca1652fce295fe0dd7c97432c23b0c4483724

x86_64: fix unencodable `rem` lowerings

The memory operand might use one of the extended GPRs R8 through R15 and hence require a REX prefix, but having a REX prefix makes the high-byte register AH unencodeable as the src operand. This latent bug was exposed by this branch, presumably because `select` now happens to be putting something in an extended GPR instead of a legacy GPR. In theory this could be fixed with minimal cost by introducing a way to communicate to `select` that neither the destination memory nor the other temporary can be in an extended GPR. However, I just went for the simple solution which comes at a cost of one trivial instruction: copy the remainder from AH to AL, and *then* copy AL to the destination.

1 files changed, 8 insertions(+), 4 deletions(-)

src/codegen/x86_64/CodeGen.zig+8-4
...@@ -37912,7 +37912,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -37912,7 +37912,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
37912 .{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },37912 .{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
37913 .{ .@"0:", ._, .movsx, .tmp1d, .memia(.src0b, .tmp0, .add_unaligned_size), ._, ._ },37913 .{ .@"0:", ._, .movsx, .tmp1d, .memia(.src0b, .tmp0, .add_unaligned_size), ._, ._ },
37914 .{ ._, .i_, .div, .memia(.src1b, .tmp0, .add_unaligned_size), ._, ._, ._ },37914 .{ ._, .i_, .div, .memia(.src1b, .tmp0, .add_unaligned_size), ._, ._, ._ },
37915 .{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1h, ._, ._ },37915 .{ ._, ._, .movsx, .tmp1d, .tmp1h, ._, ._ },
37916 .{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1l, ._, ._ },
37916 .{ ._, ._, .add, .tmp0p, .si(1), ._, ._ },37917 .{ ._, ._, .add, .tmp0p, .si(1), ._, ._ },
37917 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },37918 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
37918 } },37919 } },
...@@ -37944,7 +37945,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -37944,7 +37945,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
37944 .{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },37945 .{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
37945 .{ .@"0:", ._, .movsx, .tmp1d, .memia(.src0b, .tmp0, .add_unaligned_size), ._, ._ },37946 .{ .@"0:", ._, .movsx, .tmp1d, .memia(.src0b, .tmp0, .add_unaligned_size), ._, ._ },
37946 .{ ._, .i_, .div, .memia(.src1b, .tmp0, .add_unaligned_size), ._, ._, ._ },37947 .{ ._, .i_, .div, .memia(.src1b, .tmp0, .add_unaligned_size), ._, ._, ._ },
37947 .{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1h, ._, ._ },37948 .{ ._, ._, .movsx, .tmp1d, .tmp1h, ._, ._ },
37949 .{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1l, ._, ._ },
37948 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },37950 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
37949 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },37951 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
37950 } },37952 } },
...@@ -37977,7 +37979,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -37977,7 +37979,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
37977 .{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },37979 .{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
37978 .{ .@"0:", ._, .movzx, .tmp1d, .memia(.src0b, .tmp0, .add_unaligned_size), ._, ._ },37980 .{ .@"0:", ._, .movzx, .tmp1d, .memia(.src0b, .tmp0, .add_unaligned_size), ._, ._ },
37979 .{ ._, ._, .div, .memia(.src1b, .tmp0, .add_unaligned_size), ._, ._, ._ },37981 .{ ._, ._, .div, .memia(.src1b, .tmp0, .add_unaligned_size), ._, ._, ._ },
37980 .{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1h, ._, ._ },37982 .{ ._, ._, .movzx, .tmp1d, .tmp1h, ._, ._ },
37983 .{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1l, ._, ._ },
37981 .{ ._, ._, .add, .tmp0p, .si(1), ._, ._ },37984 .{ ._, ._, .add, .tmp0p, .si(1), ._, ._ },
37982 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },37985 .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
37983 } },37986 } },
...@@ -38009,7 +38012,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -38009,7 +38012,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
38009 .{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },38012 .{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
38010 .{ .@"0:", ._, .movzx, .tmp1d, .memia(.src0b, .tmp0, .add_unaligned_size), ._, ._ },38013 .{ .@"0:", ._, .movzx, .tmp1d, .memia(.src0b, .tmp0, .add_unaligned_size), ._, ._ },
38011 .{ ._, ._, .div, .memia(.src1b, .tmp0, .add_unaligned_size), ._, ._, ._ },38014 .{ ._, ._, .div, .memia(.src1b, .tmp0, .add_unaligned_size), ._, ._, ._ },
38012 .{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1h, ._, ._ },38015 .{ ._, ._, .movzx, .tmp1d, .tmp1h, ._, ._ },
38016 .{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1l, ._, ._ },
38013 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },38017 .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
38014 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },38018 .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
38015 } },38019 } },