mirror of
https://github.com/ziglang/zig.git
synced 2026-02-09 19:10:48 +00:00
stage2 ARM: correct spilling in genArmMul as well
This commit is contained in:
parent
b7eab32f42
commit
65cee0b3fd
@ -1563,28 +1563,63 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
||||
const lhs = try self.resolveInst(op_lhs);
|
||||
const rhs = try self.resolveInst(op_rhs);
|
||||
|
||||
const lhs_is_register = lhs == .register;
|
||||
const rhs_is_register = rhs == .register;
|
||||
const reuse_lhs = lhs_is_register and self.reuseOperand(inst, 0, lhs);
|
||||
const reuse_rhs = !reuse_lhs and rhs_is_register and self.reuseOperand(inst, 1, rhs);
|
||||
|
||||
// Destination must be a register
|
||||
// LHS must be a register
|
||||
// RHS must be a register
|
||||
var dst_mcv: MCValue = undefined;
|
||||
var lhs_mcv: MCValue = undefined;
|
||||
var rhs_mcv: MCValue = undefined;
|
||||
if (self.reuseOperand(inst, 0, lhs)) {
|
||||
// LHS is the destination
|
||||
lhs_mcv = if (lhs != .register) try self.copyToNewRegister(inst, lhs) else lhs;
|
||||
rhs_mcv = if (rhs != .register) try self.copyToNewRegister(inst, rhs) else rhs;
|
||||
dst_mcv = lhs_mcv;
|
||||
} else if (self.reuseOperand(inst, 1, rhs)) {
|
||||
// RHS is the destination
|
||||
lhs_mcv = if (lhs != .register) try self.copyToNewRegister(inst, lhs) else lhs;
|
||||
rhs_mcv = if (rhs != .register) try self.copyToNewRegister(inst, rhs) else rhs;
|
||||
dst_mcv = rhs_mcv;
|
||||
var lhs_mcv: MCValue = lhs;
|
||||
var rhs_mcv: MCValue = rhs;
|
||||
|
||||
// Allocate registers for operands and/or destination
|
||||
const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
|
||||
if (reuse_lhs) {
|
||||
// Allocate 0 or 1 registers
|
||||
if (!rhs_is_register) {
|
||||
rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(op_rhs, &.{lhs.register}) };
|
||||
branch.inst_table.putAssumeCapacity(op_rhs, rhs_mcv);
|
||||
}
|
||||
dst_mcv = lhs;
|
||||
} else if (reuse_rhs) {
|
||||
// Allocate 0 or 1 registers
|
||||
if (!lhs_is_register) {
|
||||
lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(op_lhs, &.{rhs.register}) };
|
||||
branch.inst_table.putAssumeCapacity(op_lhs, lhs_mcv);
|
||||
}
|
||||
dst_mcv = rhs;
|
||||
} else {
|
||||
// TODO save 1 copy instruction by directly allocating the destination register
|
||||
// LHS is the destination
|
||||
lhs_mcv = try self.copyToNewRegister(inst, lhs);
|
||||
rhs_mcv = if (rhs != .register) try self.copyToNewRegister(inst, rhs) else rhs;
|
||||
dst_mcv = lhs_mcv;
|
||||
// Allocate 1 or 2 registers
|
||||
if (lhs_is_register and rhs_is_register) {
|
||||
dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{ lhs.register, rhs.register }) };
|
||||
} else if (lhs_is_register) {
|
||||
// Move RHS to register
|
||||
dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{lhs.register}) };
|
||||
rhs_mcv = dst_mcv;
|
||||
} else if (rhs_is_register) {
|
||||
// Move LHS to register
|
||||
dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{rhs.register}) };
|
||||
lhs_mcv = dst_mcv;
|
||||
} else {
|
||||
// Move LHS and RHS to register
|
||||
const regs = try self.register_manager.allocRegs(2, .{ inst, op_rhs }, &.{});
|
||||
lhs_mcv = MCValue{ .register = regs[0] };
|
||||
rhs_mcv = MCValue{ .register = regs[1] };
|
||||
dst_mcv = lhs_mcv;
|
||||
|
||||
branch.inst_table.putAssumeCapacity(op_rhs, rhs_mcv);
|
||||
}
|
||||
}
|
||||
|
||||
// Move the operands to the newly allocated registers
|
||||
if (!lhs_is_register) {
|
||||
try self.genSetReg(op_lhs.src, op_lhs.ty, lhs_mcv.register, lhs);
|
||||
}
|
||||
if (!rhs_is_register) {
|
||||
try self.genSetReg(op_rhs.src, op_rhs.ty, rhs_mcv.register, rhs);
|
||||
}
|
||||
|
||||
writeInt(u32, try self.code.addManyAsArray(4), Instruction.mul(.al, dst_mcv.register, lhs_mcv.register, rhs_mcv.register).toU32());
|
||||
|
||||
@ -510,5 +510,54 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
,
|
||||
"",
|
||||
);
|
||||
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() noreturn {
|
||||
\\ assert(addMul(3, 4) == 357747496);
|
||||
\\ exit();
|
||||
\\}
|
||||
\\
|
||||
\\fn addMul(a: u32, b: u32) u32 {
|
||||
\\ const x: u32 = blk: {
|
||||
\\ const c = a + b; // 7
|
||||
\\ const d = a + c; // 10
|
||||
\\ const e = d + b; // 14
|
||||
\\ const f = d + e; // 24
|
||||
\\ const g = e + f; // 38
|
||||
\\ const h = f + g; // 62
|
||||
\\ const i = g + h; // 100
|
||||
\\ const j = i + d; // 110
|
||||
\\ const k = i + j; // 210
|
||||
\\ const l = k + c; // 217
|
||||
\\ const m = l * d; // 2170
|
||||
\\ const n = m + e; // 2184
|
||||
\\ const o = n * f; // 52416
|
||||
\\ const p = o + g; // 52454
|
||||
\\ const q = p * h; // 3252148
|
||||
\\ const r = q + i; // 3252248
|
||||
\\ const s = r * j; // 357747280
|
||||
\\ const t = s + k; // 357747490
|
||||
\\ break :blk t;
|
||||
\\ };
|
||||
\\ const y = x + a; // 357747493
|
||||
\\ const z = y + a; // 357747496
|
||||
\\ return z;
|
||||
\\}
|
||||
\\
|
||||
\\fn assert(ok: bool) void {
|
||||
\\ if (!ok) unreachable;
|
||||
\\}
|
||||
\\
|
||||
\\fn exit() noreturn {
|
||||
\\ asm volatile ("svc #0"
|
||||
\\ :
|
||||
\\ : [number] "{r7}" (1),
|
||||
\\ [arg1] "{r0}" (0)
|
||||
\\ : "memory"
|
||||
\\ );
|
||||
\\ unreachable;
|
||||
\\}
|
||||
,
|
||||
"",);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user