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