authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2021-05-16 12:54:51+08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-17 17:18:01-04:00
log65cee0b3fd5f9b3f83b79cc8fd1b64d13f4dd0c4
tree64dddd5f20fe5811dd929313991bb318900d7f7a
parentb7eab32f42040ecb80501111adb05bc8369625e8

stage2 ARM: correct spilling in genArmMul as well


2 files changed, 101 insertions(+), 17 deletions(-)

src/codegen.zig+52-17
...@@ -1563,28 +1563,63 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1563,28 +1563,63 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1563 const lhs = try self.resolveInst(op_lhs);1563 const lhs = try self.resolveInst(op_lhs);
1564 const rhs = try self.resolveInst(op_rhs);1564 const rhs = try self.resolveInst(op_rhs);
15651565
1566 const lhs_is_register = lhs == .register;
1567 const rhs_is_register = rhs == .register;
1568 const reuse_lhs = lhs_is_register and self.reuseOperand(inst, 0, lhs);
1569 const reuse_rhs = !reuse_lhs and rhs_is_register and self.reuseOperand(inst, 1, rhs);
1570
1566 // Destination must be a register1571 // Destination must be a register
1567 // LHS must be a register1572 // LHS must be a register
1568 // RHS must be a register1573 // RHS must be a register
1569 var dst_mcv: MCValue = undefined;1574 var dst_mcv: MCValue = undefined;
1570 var lhs_mcv: MCValue = undefined;1575 var lhs_mcv: MCValue = lhs;
1571 var rhs_mcv: MCValue = undefined;1576 var rhs_mcv: MCValue = rhs;
1572 if (self.reuseOperand(inst, 0, lhs)) {1577
1573 // LHS is the destination1578 // Allocate registers for operands and/or destination
1574 lhs_mcv = if (lhs != .register) try self.copyToNewRegister(inst, lhs) else lhs;1579 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
1575 rhs_mcv = if (rhs != .register) try self.copyToNewRegister(inst, rhs) else rhs;1580 if (reuse_lhs) {
1576 dst_mcv = lhs_mcv;1581 // Allocate 0 or 1 registers
1577 } else if (self.reuseOperand(inst, 1, rhs)) {1582 if (!rhs_is_register) {
1578 // RHS is the destination1583 rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(op_rhs, &.{lhs.register}) };
1579 lhs_mcv = if (lhs != .register) try self.copyToNewRegister(inst, lhs) else lhs;1584 branch.inst_table.putAssumeCapacity(op_rhs, rhs_mcv);
1580 rhs_mcv = if (rhs != .register) try self.copyToNewRegister(inst, rhs) else rhs;1585 }
1581 dst_mcv = rhs_mcv;1586 dst_mcv = lhs;
1587 } else if (reuse_rhs) {
1588 // Allocate 0 or 1 registers
1589 if (!lhs_is_register) {
1590 lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(op_lhs, &.{rhs.register}) };
1591 branch.inst_table.putAssumeCapacity(op_lhs, lhs_mcv);
1592 }
1593 dst_mcv = rhs;
1582 } else {1594 } else {
1583 // TODO save 1 copy instruction by directly allocating the destination register1595 // Allocate 1 or 2 registers
1584 // LHS is the destination1596 if (lhs_is_register and rhs_is_register) {
1585 lhs_mcv = try self.copyToNewRegister(inst, lhs);1597 dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{ lhs.register, rhs.register }) };
1586 rhs_mcv = if (rhs != .register) try self.copyToNewRegister(inst, rhs) else rhs;1598 } else if (lhs_is_register) {
1587 dst_mcv = lhs_mcv;1599 // Move RHS to register
1600 dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{lhs.register}) };
1601 rhs_mcv = dst_mcv;
1602 } else if (rhs_is_register) {
1603 // Move LHS to register
1604 dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{rhs.register}) };
1605 lhs_mcv = dst_mcv;
1606 } else {
1607 // Move LHS and RHS to register
1608 const regs = try self.register_manager.allocRegs(2, .{ inst, op_rhs }, &.{});
1609 lhs_mcv = MCValue{ .register = regs[0] };
1610 rhs_mcv = MCValue{ .register = regs[1] };
1611 dst_mcv = lhs_mcv;
1612
1613 branch.inst_table.putAssumeCapacity(op_rhs, rhs_mcv);
1614 }
1615 }
1616
1617 // Move the operands to the newly allocated registers
1618 if (!lhs_is_register) {
1619 try self.genSetReg(op_lhs.src, op_lhs.ty, lhs_mcv.register, lhs);
1620 }
1621 if (!rhs_is_register) {
1622 try self.genSetReg(op_rhs.src, op_rhs.ty, rhs_mcv.register, rhs);
1588 }1623 }
15891624
1590 writeInt(u32, try self.code.addManyAsArray(4), Instruction.mul(.al, dst_mcv.register, lhs_mcv.register, rhs_mcv.register).toU32());1625 writeInt(u32, try self.code.addManyAsArray(4), Instruction.mul(.al, dst_mcv.register, lhs_mcv.register, rhs_mcv.register).toU32());
test/stage2/arm.zig+49
...@@ -510,5 +510,54 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -510,5 +510,54 @@ pub fn addCases(ctx: *TestContext) !void {
510 ,510 ,
511 "",511 "",
512 );512 );
513
514 case.addCompareOutput(
515 \\export fn _start() noreturn {
516 \\ assert(addMul(3, 4) == 357747496);
517 \\ exit();
518 \\}
519 \\
520 \\fn addMul(a: u32, b: u32) u32 {
521 \\ const x: u32 = blk: {
522 \\ const c = a + b; // 7
523 \\ const d = a + c; // 10
524 \\ const e = d + b; // 14
525 \\ const f = d + e; // 24
526 \\ const g = e + f; // 38
527 \\ const h = f + g; // 62
528 \\ const i = g + h; // 100
529 \\ const j = i + d; // 110
530 \\ const k = i + j; // 210
531 \\ const l = k + c; // 217
532 \\ const m = l * d; // 2170
533 \\ const n = m + e; // 2184
534 \\ const o = n * f; // 52416
535 \\ const p = o + g; // 52454
536 \\ const q = p * h; // 3252148
537 \\ const r = q + i; // 3252248
538 \\ const s = r * j; // 357747280
539 \\ const t = s + k; // 357747490
540 \\ break :blk t;
541 \\ };
542 \\ const y = x + a; // 357747493
543 \\ const z = y + a; // 357747496
544 \\ return z;
545 \\}
546 \\
547 \\fn assert(ok: bool) void {
548 \\ if (!ok) unreachable;
549 \\}
550 \\
551 \\fn exit() noreturn {
552 \\ asm volatile ("svc #0"
553 \\ :
554 \\ : [number] "{r7}" (1),
555 \\ [arg1] "{r0}" (0)
556 \\ : "memory"
557 \\ );
558 \\ unreachable;
559 \\}
560 ,
561 "",);
513 }562 }
514}563}