| ... | ... | @@ -4328,7 +4328,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4328 | 4328 | }; |
| 4329 | 4329 | var cond_mat: ?Value.Materialize = null; |
| 4330 | 4330 | var cond_reg: Register = undefined; |
| 4331 | | var temp_reg: Register = undefined; |
| 4332 | 4331 | var cases_it = switch_br.iterateCases(); |
| 4333 | 4332 | while (cases_it.next()) |case| { |
| 4334 | 4333 | const next_label = isel.instructions.items.len; |
| ... | ... | @@ -4342,11 +4341,10 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4342 | 4341 | if (cond_mat == null) { |
| 4343 | 4342 | var cond_vi = try isel.use(switch_br.operand); |
| 4344 | 4343 | cond_mat = try cond_vi.matReg(isel); |
| 4345 | | const temp_ra = try isel.allocIntReg(); |
| 4346 | | cond_reg, temp_reg = switch (cond_int_info.bits) { |
| 4344 | cond_reg = switch (cond_int_info.bits) { |
| 4347 | 4345 | else => unreachable, |
| 4348 | | 1...32 => .{ cond_mat.?.ra.w(), temp_ra.w() }, |
| 4349 | | 33...64 => .{ cond_mat.?.ra.x(), temp_ra.x() }, |
| 4346 | 1...32 => cond_mat.?.ra.w(), |
| 4347 | 33...64 => cond_mat.?.ra.x(), |
| 4350 | 4348 | }; |
| 4351 | 4349 | } |
| 4352 | 4350 | if (case.ranges.len == 0 and case.items.len == 1 and Constant.fromInterned( |
| ... | ... | @@ -4387,17 +4385,45 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4387 | 4385 | ) else high_bigint.toInt(i64) catch |
| 4388 | 4386 | return isel.fail("too big case range end: {f}", .{isel.fmtConstant(high_val)}); |
| 4389 | 4387 | |
| 4388 | const adjusted_ra = switch (low_int) { |
| 4389 | 0 => cond_mat.?.ra, |
| 4390 | else => try isel.allocIntReg(), |
| 4391 | }; |
| 4392 | defer if (adjusted_ra != cond_mat.?.ra) isel.freeReg(adjusted_ra); |
| 4393 | const adjusted_reg = switch (cond_int_info.bits) { |
| 4394 | else => unreachable, |
| 4395 | 1...32 => adjusted_ra.w(), |
| 4396 | 33...64 => adjusted_ra.x(), |
| 4397 | }; |
| 4390 | 4398 | const delta_int = high_int -% low_int; |
| 4391 | | if (case_range_index > 0) { |
| 4392 | | return isel.fail("case range", .{}); |
| 4393 | | } else if (case.items.len > 0) { |
| 4394 | | return isel.fail("case range", .{}); |
| 4399 | if (case_range_index | case.items.len > 0) { |
| 4400 | if (std.math.cast(u5, delta_int)) |pos_imm| try isel.emit(.ccmp( |
| 4401 | adjusted_reg, |
| 4402 | .{ .immediate = pos_imm }, |
| 4403 | .{ .n = false, .z = true, .c = false, .v = false }, |
| 4404 | if (case_range_index > 0) .hi else .ne, |
| 4405 | )) else if (std.math.cast(u5, -delta_int)) |neg_imm| try isel.emit(.ccmn( |
| 4406 | adjusted_reg, |
| 4407 | .{ .immediate = neg_imm }, |
| 4408 | .{ .n = false, .z = true, .c = false, .v = false }, |
| 4409 | if (case_range_index > 0) .hi else .ne, |
| 4410 | )) else { |
| 4411 | const imm_ra = try isel.allocIntReg(); |
| 4412 | defer isel.freeReg(imm_ra); |
| 4413 | const imm_reg = switch (cond_int_info.bits) { |
| 4414 | else => unreachable, |
| 4415 | 1...32 => imm_ra.w(), |
| 4416 | 33...64 => imm_ra.x(), |
| 4417 | }; |
| 4418 | try isel.emit(.ccmp( |
| 4419 | cond_reg, |
| 4420 | .{ .register = imm_reg }, |
| 4421 | .{ .n = false, .z = true, .c = false, .v = false }, |
| 4422 | if (case_range_index > 0) .hi else .ne, |
| 4423 | )); |
| 4424 | try isel.movImmediate(imm_reg, @bitCast(delta_int)); |
| 4425 | } |
| 4395 | 4426 | } else { |
| 4396 | | const adjusted_reg = switch (low_int) { |
| 4397 | | 0 => cond_reg, |
| 4398 | | else => temp_reg, |
| 4399 | | }; |
| 4400 | | |
| 4401 | 4427 | if (std.math.cast(u12, delta_int)) |pos_imm| try isel.emit(.subs( |
| 4402 | 4428 | zero_reg, |
| 4403 | 4429 | adjusted_reg, |
| ... | ... | @@ -4421,41 +4447,55 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4421 | 4447 | adjusted_reg, |
| 4422 | 4448 | .{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } }, |
| 4423 | 4449 | )) else { |
| 4424 | | try isel.movImmediate(temp_reg, @bitCast(delta_int)); |
| 4425 | | try isel.emit(.subs(zero_reg, adjusted_reg, .{ .register = temp_reg })); |
| 4450 | const imm_ra = try isel.allocIntReg(); |
| 4451 | defer isel.freeReg(imm_ra); |
| 4452 | const imm_reg = switch (cond_int_info.bits) { |
| 4453 | else => unreachable, |
| 4454 | 1...32 => imm_ra.w(), |
| 4455 | 33...64 => imm_ra.x(), |
| 4456 | }; |
| 4457 | try isel.emit(.subs(zero_reg, adjusted_reg, .{ .register = imm_reg })); |
| 4458 | try isel.movImmediate(imm_reg, @bitCast(delta_int)); |
| 4426 | 4459 | } |
| 4460 | } |
| 4427 | 4461 | |
| 4428 | | switch (low_int) { |
| 4429 | | 0 => {}, |
| 4430 | | else => { |
| 4431 | | if (std.math.cast(u12, low_int)) |pos_imm| try isel.emit(.sub( |
| 4432 | | adjusted_reg, |
| 4433 | | cond_reg, |
| 4434 | | .{ .immediate = pos_imm }, |
| 4435 | | )) else if (std.math.cast(u12, -low_int)) |neg_imm| try isel.emit(.add( |
| 4436 | | adjusted_reg, |
| 4437 | | cond_reg, |
| 4438 | | .{ .immediate = neg_imm }, |
| 4439 | | )) else if (if (@as(i12, @truncate(low_int)) == 0) |
| 4440 | | std.math.cast(u12, low_int >> 12) |
| 4441 | | else |
| 4442 | | null) |pos_imm_lsr_12| try isel.emit(.sub( |
| 4443 | | adjusted_reg, |
| 4444 | | cond_reg, |
| 4445 | | .{ .shifted_immediate = .{ .immediate = pos_imm_lsr_12, .lsl = .@"12" } }, |
| 4446 | | )) else if (if (@as(i12, @truncate(-low_int)) == 0) |
| 4447 | | std.math.cast(u12, -low_int >> 12) |
| 4448 | | else |
| 4449 | | null) |neg_imm_lsr_12| try isel.emit(.add( |
| 4450 | | adjusted_reg, |
| 4451 | | cond_reg, |
| 4452 | | .{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } }, |
| 4453 | | )) else { |
| 4454 | | try isel.movImmediate(temp_reg, @bitCast(low_int)); |
| 4455 | | try isel.emit(.subs(adjusted_reg, cond_reg, .{ .register = temp_reg })); |
| 4456 | | } |
| 4457 | | }, |
| 4458 | | } |
| 4462 | switch (low_int) { |
| 4463 | 0 => {}, |
| 4464 | else => { |
| 4465 | if (std.math.cast(u12, low_int)) |pos_imm| try isel.emit(.sub( |
| 4466 | adjusted_reg, |
| 4467 | cond_reg, |
| 4468 | .{ .immediate = pos_imm }, |
| 4469 | )) else if (std.math.cast(u12, -low_int)) |neg_imm| try isel.emit(.add( |
| 4470 | adjusted_reg, |
| 4471 | cond_reg, |
| 4472 | .{ .immediate = neg_imm }, |
| 4473 | )) else if (if (@as(i12, @truncate(low_int)) == 0) |
| 4474 | std.math.cast(u12, low_int >> 12) |
| 4475 | else |
| 4476 | null) |pos_imm_lsr_12| try isel.emit(.sub( |
| 4477 | adjusted_reg, |
| 4478 | cond_reg, |
| 4479 | .{ .shifted_immediate = .{ .immediate = pos_imm_lsr_12, .lsl = .@"12" } }, |
| 4480 | )) else if (if (@as(i12, @truncate(-low_int)) == 0) |
| 4481 | std.math.cast(u12, -low_int >> 12) |
| 4482 | else |
| 4483 | null) |neg_imm_lsr_12| try isel.emit(.add( |
| 4484 | adjusted_reg, |
| 4485 | cond_reg, |
| 4486 | .{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } }, |
| 4487 | )) else { |
| 4488 | const imm_ra = try isel.allocIntReg(); |
| 4489 | defer isel.freeReg(imm_ra); |
| 4490 | const imm_reg = switch (cond_int_info.bits) { |
| 4491 | else => unreachable, |
| 4492 | 1...32 => imm_ra.w(), |
| 4493 | 33...64 => imm_ra.x(), |
| 4494 | }; |
| 4495 | try isel.emit(.sub(adjusted_reg, cond_reg, .{ .register = imm_reg })); |
| 4496 | try isel.movImmediate(imm_reg, @bitCast(low_int)); |
| 4497 | } |
| 4498 | }, |
| 4459 | 4499 | } |
| 4460 | 4500 | } |
| 4461 | 4501 | var case_item_index = case.items.len; |
| ... | ... | @@ -4483,13 +4523,20 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4483 | 4523 | .{ .n = false, .z = true, .c = false, .v = false }, |
| 4484 | 4524 | .ne, |
| 4485 | 4525 | )) else { |
| 4486 | | try isel.movImmediate(temp_reg, @bitCast(item_int)); |
| 4526 | const imm_ra = try isel.allocIntReg(); |
| 4527 | defer isel.freeReg(imm_ra); |
| 4528 | const imm_reg = switch (cond_int_info.bits) { |
| 4529 | else => unreachable, |
| 4530 | 1...32 => imm_ra.w(), |
| 4531 | 33...64 => imm_ra.x(), |
| 4532 | }; |
| 4487 | 4533 | try isel.emit(.ccmp( |
| 4488 | 4534 | cond_reg, |
| 4489 | | .{ .register = temp_reg }, |
| 4535 | .{ .register = imm_reg }, |
| 4490 | 4536 | .{ .n = false, .z = true, .c = false, .v = false }, |
| 4491 | 4537 | .ne, |
| 4492 | 4538 | )); |
| 4539 | try isel.movImmediate(imm_reg, @bitCast(item_int)); |
| 4493 | 4540 | } |
| 4494 | 4541 | } else { |
| 4495 | 4542 | if (std.math.cast(u12, item_int)) |pos_imm| try isel.emit(.subs( |
| ... | ... | @@ -4515,16 +4562,20 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4515 | 4562 | cond_reg, |
| 4516 | 4563 | .{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } }, |
| 4517 | 4564 | )) else { |
| 4518 | | try isel.movImmediate(temp_reg, @bitCast(item_int)); |
| 4519 | | try isel.emit(.subs(zero_reg, cond_reg, .{ .register = temp_reg })); |
| 4565 | const imm_ra = try isel.allocIntReg(); |
| 4566 | defer isel.freeReg(imm_ra); |
| 4567 | const imm_reg = switch (cond_int_info.bits) { |
| 4568 | else => unreachable, |
| 4569 | 1...32 => imm_ra.w(), |
| 4570 | 33...64 => imm_ra.x(), |
| 4571 | }; |
| 4572 | try isel.emit(.subs(zero_reg, cond_reg, .{ .register = imm_reg })); |
| 4573 | try isel.movImmediate(imm_reg, @bitCast(item_int)); |
| 4520 | 4574 | } |
| 4521 | 4575 | } |
| 4522 | 4576 | } |
| 4523 | 4577 | } |
| 4524 | | if (cond_mat) |mat| { |
| 4525 | | try mat.finish(isel); |
| 4526 | | isel.freeReg(temp_reg.alias); |
| 4527 | | } |
| 4578 | if (cond_mat) |mat| try mat.finish(isel); |
| 4528 | 4579 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 4529 | 4580 | }, |
| 4530 | 4581 | .@"try", .try_cold => { |