| ... | ... | @@ -3083,7 +3083,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 3083 | 3083 | }; |
| 3084 | 3084 | defer if (mat_src_lock) |lock| self.register_manager.unlockReg(lock); |
| 3085 | 3085 | |
| 3086 | | const dst_reg = try self.register_manager.allocReg(null, gp); |
| 3086 | const dst_reg = try self.register_manager.allocReg(inst, gp); |
| 3087 | 3087 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 3088 | 3088 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 3089 | 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 | 3098 | } |
| 3099 | 3099 | |
| 3100 | 3100 | const src_bits = src_ty.bitSize(self.target.*); |
| 3101 | | const width_mcv = |
| 3102 | | try self.copyToRegisterWithInstTracking(inst, dst_ty, .{ .immediate = src_bits }); |
| 3103 | | try self.genBinOpMir(.bsr, src_ty, dst_mcv, mat_src_mcv); |
| 3101 | if (math.isPowerOfTwo(src_bits)) { |
| 3102 | const imm_reg = try self.copyToTmpRegister(dst_ty, .{ |
| 3103 | .immediate = src_bits ^ (src_bits - 1), |
| 3104 | }); |
| 3105 | try self.genBinOpMir(.bsf, src_ty, dst_mcv, mat_src_mcv); |
| 3104 | 3106 | |
| 3105 | | const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2); |
| 3106 | | try self.asmCmovccRegisterRegister( |
| 3107 | | registerAlias(dst_reg, cmov_abi_size), |
| 3108 | | registerAlias(width_mcv.register, cmov_abi_size), |
| 3109 | | .z, |
| 3110 | | ); |
| 3107 | const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2); |
| 3108 | try self.asmCmovccRegisterRegister( |
| 3109 | registerAlias(dst_reg, cmov_abi_size), |
| 3110 | registerAlias(imm_reg, cmov_abi_size), |
| 3111 | .z, |
| 3112 | ); |
| 3111 | 3113 | |
| 3112 | | try self.genBinOpMir(.sub, dst_ty, width_mcv, dst_mcv); |
| 3113 | | break :result width_mcv; |
| 3114 | try self.genBinOpMir(.xor, dst_ty, dst_mcv, .{ .immediate = src_bits - 1 }); |
| 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 | 3133 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 3116 | 3134 | } |