| ... | @@ -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); |
| 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 | 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 | } |
| 3099 | | 3099 | |
| 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); |
| 3104 | | 3106 | |
| 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 | ); |
| 3111 | | 3113 | |
| 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 | } |