| ... | ... | @@ -4226,9 +4226,18 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4226 | 4226 | |
| 4227 | 4227 | const src_bits = src_ty.bitSize(self.target.*); |
| 4228 | 4228 | if (self.hasFeature(.lzcnt)) { |
| 4229 | | if (src_bits <= 64) { |
| 4229 | if (src_bits <= 8) { |
| 4230 | const wide_reg = try self.copyToTmpRegister(src_ty, mat_src_mcv); |
| 4231 | try self.truncateRegister(src_ty, wide_reg); |
| 4232 | try self.genBinOpMir(.{ ._, .lzcnt }, Type.u32, dst_mcv, .{ .register = wide_reg }); |
| 4233 | try self.genBinOpMir( |
| 4234 | .{ ._, .sub }, |
| 4235 | dst_ty, |
| 4236 | dst_mcv, |
| 4237 | .{ .immediate = 8 + self.regExtraBits(src_ty) }, |
| 4238 | ); |
| 4239 | } else if (src_bits <= 64) { |
| 4230 | 4240 | try self.genBinOpMir(.{ ._, .lzcnt }, src_ty, dst_mcv, mat_src_mcv); |
| 4231 | | |
| 4232 | 4241 | const extra_bits = self.regExtraBits(src_ty); |
| 4233 | 4242 | if (extra_bits > 0) { |
| 4234 | 4243 | try self.genBinOpMir(.{ ._, .sub }, dst_ty, dst_mcv, .{ .immediate = extra_bits }); |
| ... | ... | @@ -4267,7 +4276,17 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4267 | 4276 | const imm_reg = try self.copyToTmpRegister(dst_ty, .{ |
| 4268 | 4277 | .immediate = src_bits ^ (src_bits - 1), |
| 4269 | 4278 | }); |
| 4270 | | try self.genBinOpMir(.{ ._, .bsr }, src_ty, dst_mcv, mat_src_mcv); |
| 4279 | const imm_lock = self.register_manager.lockRegAssumeUnused(imm_reg); |
| 4280 | defer self.register_manager.unlockReg(imm_lock); |
| 4281 | |
| 4282 | if (src_bits <= 8) { |
| 4283 | const wide_reg = try self.copyToTmpRegister(src_ty, mat_src_mcv); |
| 4284 | const wide_lock = self.register_manager.lockRegAssumeUnused(wide_reg); |
| 4285 | defer self.register_manager.unlockReg(wide_lock); |
| 4286 | |
| 4287 | try self.truncateRegister(src_ty, wide_reg); |
| 4288 | try self.genBinOpMir(.{ ._, .bsr }, Type.u16, dst_mcv, .{ .register = wide_reg }); |
| 4289 | } else try self.genBinOpMir(.{ ._, .bsr }, src_ty, dst_mcv, mat_src_mcv); |
| 4271 | 4290 | |
| 4272 | 4291 | const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2); |
| 4273 | 4292 | try self.asmCmovccRegisterRegister( |
| ... | ... | @@ -4281,7 +4300,20 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4281 | 4300 | const imm_reg = try self.copyToTmpRegister(dst_ty, .{ |
| 4282 | 4301 | .immediate = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - self.regBitSize(dst_ty)), |
| 4283 | 4302 | }); |
| 4284 | | try self.genBinOpMir(.{ ._, .bsr }, src_ty, dst_mcv, mat_src_mcv); |
| 4303 | const imm_lock = self.register_manager.lockRegAssumeUnused(imm_reg); |
| 4304 | defer self.register_manager.unlockReg(imm_lock); |
| 4305 | |
| 4306 | const wide_reg = try self.copyToTmpRegister(src_ty, mat_src_mcv); |
| 4307 | const wide_lock = self.register_manager.lockRegAssumeUnused(wide_reg); |
| 4308 | defer self.register_manager.unlockReg(wide_lock); |
| 4309 | |
| 4310 | try self.truncateRegister(src_ty, wide_reg); |
| 4311 | try self.genBinOpMir( |
| 4312 | .{ ._, .bsr }, |
| 4313 | if (src_bits <= 8) Type.u16 else src_ty, |
| 4314 | dst_mcv, |
| 4315 | .{ .register = wide_reg }, |
| 4316 | ); |
| 4285 | 4317 | |
| 4286 | 4318 | const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2); |
| 4287 | 4319 | try self.asmCmovccRegisterRegister( |
| ... | ... | @@ -4323,24 +4355,25 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 4323 | 4355 | |
| 4324 | 4356 | if (self.hasFeature(.bmi)) { |
| 4325 | 4357 | if (src_bits <= 64) { |
| 4326 | | const extra_bits = self.regExtraBits(src_ty); |
| 4358 | const extra_bits = self.regExtraBits(src_ty) + @as(u64, if (src_bits <= 8) 8 else 0); |
| 4359 | const wide_ty = if (src_bits <= 8) Type.u16 else src_ty; |
| 4327 | 4360 | const masked_mcv = if (extra_bits > 0) masked: { |
| 4328 | 4361 | const tmp_mcv = tmp: { |
| 4329 | 4362 | if (src_mcv.isImmediate() or self.liveness.operandDies(inst, 0)) |
| 4330 | 4363 | break :tmp src_mcv; |
| 4331 | | try self.genSetReg(dst_reg, src_ty, src_mcv); |
| 4364 | try self.genSetReg(dst_reg, wide_ty, src_mcv); |
| 4332 | 4365 | break :tmp dst_mcv; |
| 4333 | 4366 | }; |
| 4334 | 4367 | try self.genBinOpMir( |
| 4335 | 4368 | .{ ._, .@"or" }, |
| 4336 | | src_ty, |
| 4369 | wide_ty, |
| 4337 | 4370 | tmp_mcv, |
| 4338 | 4371 | .{ .immediate = (@as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - extra_bits)) << |
| 4339 | 4372 | @intCast(u6, src_bits) }, |
| 4340 | 4373 | ); |
| 4341 | 4374 | break :masked tmp_mcv; |
| 4342 | 4375 | } else mat_src_mcv; |
| 4343 | | try self.genBinOpMir(.{ ._, .tzcnt }, src_ty, dst_mcv, masked_mcv); |
| 4376 | try self.genBinOpMir(.{ ._, .tzcnt }, wide_ty, dst_mcv, masked_mcv); |
| 4344 | 4377 | } else if (src_bits <= 128) { |
| 4345 | 4378 | const tmp_reg = try self.register_manager.allocReg(null, gp); |
| 4346 | 4379 | const tmp_mcv = MCValue{ .register = tmp_reg }; |
| ... | ... | @@ -4369,7 +4402,17 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 4369 | 4402 | return self.fail("TODO airCtz of {}", .{src_ty.fmt(self.bin_file.options.module.?)}); |
| 4370 | 4403 | |
| 4371 | 4404 | const width_reg = try self.copyToTmpRegister(dst_ty, .{ .immediate = src_bits }); |
| 4372 | | try self.genBinOpMir(.{ ._, .bsf }, src_ty, dst_mcv, mat_src_mcv); |
| 4405 | const width_lock = self.register_manager.lockRegAssumeUnused(width_reg); |
| 4406 | defer self.register_manager.unlockReg(width_lock); |
| 4407 | |
| 4408 | if (src_bits <= 8 or !math.isPowerOfTwo(src_bits)) { |
| 4409 | const wide_reg = try self.copyToTmpRegister(src_ty, mat_src_mcv); |
| 4410 | const wide_lock = self.register_manager.lockRegAssumeUnused(wide_reg); |
| 4411 | defer self.register_manager.unlockReg(wide_lock); |
| 4412 | |
| 4413 | try self.truncateRegister(src_ty, wide_reg); |
| 4414 | try self.genBinOpMir(.{ ._, .bsf }, Type.u16, dst_mcv, .{ .register = wide_reg }); |
| 4415 | } else try self.genBinOpMir(.{ ._, .bsf }, src_ty, dst_mcv, mat_src_mcv); |
| 4373 | 4416 | |
| 4374 | 4417 | const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2); |
| 4375 | 4418 | try self.asmCmovccRegisterRegister( |