| ... | @@ -4226,9 +4226,18 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4226,9 +4226,18 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4226 | | 4226 | |
| 4227 | const src_bits = src_ty.bitSize(self.target.*); | 4227 | const src_bits = src_ty.bitSize(self.target.*); |
| 4228 | if (self.hasFeature(.lzcnt)) { | 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 | try self.genBinOpMir(.{ ._, .lzcnt }, src_ty, dst_mcv, mat_src_mcv); | 4240 | try self.genBinOpMir(.{ ._, .lzcnt }, src_ty, dst_mcv, mat_src_mcv); |
| 4231 | | | |
| 4232 | const extra_bits = self.regExtraBits(src_ty); | 4241 | const extra_bits = self.regExtraBits(src_ty); |
| 4233 | if (extra_bits > 0) { | 4242 | if (extra_bits > 0) { |
| 4234 | try self.genBinOpMir(.{ ._, .sub }, dst_ty, dst_mcv, .{ .immediate = extra_bits }); | 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,7 +4276,17 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4267 | const imm_reg = try self.copyToTmpRegister(dst_ty, .{ | 4276 | const imm_reg = try self.copyToTmpRegister(dst_ty, .{ |
| 4268 | .immediate = src_bits ^ (src_bits - 1), | 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 | const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2); | 4291 | const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2); |
| 4273 | try self.asmCmovccRegisterRegister( | 4292 | try self.asmCmovccRegisterRegister( |
| ... | @@ -4281,7 +4300,20 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4281,7 +4300,20 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4281 | const imm_reg = try self.copyToTmpRegister(dst_ty, .{ | 4300 | const imm_reg = try self.copyToTmpRegister(dst_ty, .{ |
| 4282 | .immediate = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - self.regBitSize(dst_ty)), | 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 | const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2); | 4318 | const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2); |
| 4287 | try self.asmCmovccRegisterRegister( | 4319 | try self.asmCmovccRegisterRegister( |
| ... | @@ -4323,24 +4355,25 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4323,24 +4355,25 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 4323 | | 4355 | |
| 4324 | if (self.hasFeature(.bmi)) { | 4356 | if (self.hasFeature(.bmi)) { |
| 4325 | if (src_bits <= 64) { | 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 | const masked_mcv = if (extra_bits > 0) masked: { | 4360 | const masked_mcv = if (extra_bits > 0) masked: { |
| 4328 | const tmp_mcv = tmp: { | 4361 | const tmp_mcv = tmp: { |
| 4329 | if (src_mcv.isImmediate() or self.liveness.operandDies(inst, 0)) | 4362 | if (src_mcv.isImmediate() or self.liveness.operandDies(inst, 0)) |
| 4330 | break :tmp src_mcv; | 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 | break :tmp dst_mcv; | 4365 | break :tmp dst_mcv; |
| 4333 | }; | 4366 | }; |
| 4334 | try self.genBinOpMir( | 4367 | try self.genBinOpMir( |
| 4335 | .{ ._, .@"or" }, | 4368 | .{ ._, .@"or" }, |
| 4336 | src_ty, | 4369 | wide_ty, |
| 4337 | tmp_mcv, | 4370 | tmp_mcv, |
| 4338 | .{ .immediate = (@as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - extra_bits)) << | 4371 | .{ .immediate = (@as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - extra_bits)) << |
| 4339 | @intCast(u6, src_bits) }, | 4372 | @intCast(u6, src_bits) }, |
| 4340 | ); | 4373 | ); |
| 4341 | break :masked tmp_mcv; | 4374 | break :masked tmp_mcv; |
| 4342 | } else mat_src_mcv; | 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 | } else if (src_bits <= 128) { | 4377 | } else if (src_bits <= 128) { |
| 4345 | const tmp_reg = try self.register_manager.allocReg(null, gp); | 4378 | const tmp_reg = try self.register_manager.allocReg(null, gp); |
| 4346 | const tmp_mcv = MCValue{ .register = tmp_reg }; | 4379 | const tmp_mcv = MCValue{ .register = tmp_reg }; |
| ... | @@ -4369,7 +4402,17 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4369,7 +4402,17 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 4369 | return self.fail("TODO airCtz of {}", .{src_ty.fmt(self.bin_file.options.module.?)}); | 4402 | return self.fail("TODO airCtz of {}", .{src_ty.fmt(self.bin_file.options.module.?)}); |
| 4370 | | 4403 | |
| 4371 | const width_reg = try self.copyToTmpRegister(dst_ty, .{ .immediate = src_bits }); | 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 | const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2); | 4417 | const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2); |
| 4375 | try self.asmCmovccRegisterRegister( | 4418 | try self.asmCmovccRegisterRegister( |