authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-04-13 04:06:17-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-04-13 04:17:54-04:00
loge72c41a32af41c15f4f73b46c902c01ed838462f
tree6613ba68b7236f1fa3d3def5b854ffeba2677694
parentcaa3d6a4f4413c1cace517b073476780168f24cf

x86_64: fix clz miscompile


1 files changed, 30 insertions(+), 12 deletions(-)

src/arch/x86_64/CodeGen.zig+30-12
...@@ -3083,7 +3083,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {...@@ -3083,7 +3083,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
3083 };3083 };
3084 defer if (mat_src_lock) |lock| self.register_manager.unlockReg(lock);3084 defer if (mat_src_lock) |lock| self.register_manager.unlockReg(lock);
30853085
3086 const dst_reg = try self.register_manager.allocReg(null, gp);3086 const dst_reg = try self.register_manager.allocReg(inst, gp);
3087 const dst_mcv = MCValue{ .register = dst_reg };3087 const dst_mcv = MCValue{ .register = dst_reg };
3088 const dst_lock = self.register_manager.lockReg(dst_reg);3088 const dst_lock = self.register_manager.lockReg(dst_reg);
3089 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);3089 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
...@@ -3098,19 +3098,37 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {...@@ -3098,19 +3098,37 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
3098 }3098 }
30993099
3100 const src_bits = src_ty.bitSize(self.target.*);3100 const src_bits = src_ty.bitSize(self.target.*);
3101 const width_mcv =3101 if (math.isPowerOfTwo(src_bits)) {
3102 try self.copyToRegisterWithInstTracking(inst, dst_ty, .{ .immediate = src_bits });3102 const imm_reg = try self.copyToTmpRegister(dst_ty, .{
3103 try self.genBinOpMir(.bsr, src_ty, dst_mcv, mat_src_mcv);3103 .immediate = src_bits ^ (src_bits - 1),
3104 });
3105 try self.genBinOpMir(.bsf, src_ty, dst_mcv, mat_src_mcv);
31043106
3105 const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2);3107 const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2);
3106 try self.asmCmovccRegisterRegister(3108 try self.asmCmovccRegisterRegister(
3107 registerAlias(dst_reg, cmov_abi_size),3109 registerAlias(dst_reg, cmov_abi_size),
3108 registerAlias(width_mcv.register, cmov_abi_size),3110 registerAlias(imm_reg, cmov_abi_size),
3109 .z,3111 .z,
3110 );3112 );
31113113
3112 try self.genBinOpMir(.sub, dst_ty, width_mcv, dst_mcv);3114 try self.genBinOpMir(.xor, dst_ty, dst_mcv, .{ .immediate = src_bits - 1 });
3113 break :result width_mcv;3115 } else {
3116 const imm_reg = try self.copyToTmpRegister(dst_ty, .{
3117 .immediate = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - self.regBitSize(dst_ty)),
3118 });
3119 try self.genBinOpMir(.bsf, src_ty, dst_mcv, mat_src_mcv);
3120
3121 const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2);
3122 try self.asmCmovccRegisterRegister(
3123 registerAlias(imm_reg, cmov_abi_size),
3124 registerAlias(dst_reg, cmov_abi_size),
3125 .nz,
3126 );
3127
3128 try self.genSetReg(dst_ty, dst_reg, .{ .immediate = src_bits - 1 });
3129 try self.genBinOpMir(.sub, dst_ty, dst_mcv, .{ .register = imm_reg });
3130 }
3131 break :result dst_mcv;
3114 };3132 };
3115 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });3133 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
3116}3134}