@@ -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 => {
0 commit comments