stage2 ARM: improve Mir representation of mov and cmp

This commit is contained in:
joachimschmidt557 2022-08-13 17:42:11 +02:00
parent 9e070b653c
commit 28cc363947
No known key found for this signature in database
GPG Key ID: E0B575BE2884ACC5
3 changed files with 82 additions and 61 deletions

View File

@ -438,9 +438,8 @@ fn gen(self: *Self) !void {
// mov fp, sp
_ = try self.addInst(.{
.tag = .mov,
.data = .{ .rr_op = .{
.data = .{ .r_op_mov = .{
.rd = .fp,
.rn = .r0,
.op = Instruction.Operand.reg(.sp, Instruction.Operand.Shift.none),
} },
});
@ -531,9 +530,8 @@ fn gen(self: *Self) !void {
// mov sp, fp
_ = try self.addInst(.{
.tag = .mov,
.data = .{ .rr_op = .{
.data = .{ .r_op_mov = .{
.rd = .sp,
.rn = .r0,
.op = Instruction.Operand.reg(.fp, Instruction.Operand.Shift.none),
} },
});
@ -1240,9 +1238,8 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
_ = try self.addInst(.{
.tag = .mvn,
.data = .{ .rr_op = .{
.data = .{ .r_op_mov = .{
.rd = dest_reg,
.rn = undefined,
.op = Instruction.Operand.reg(op_reg, Instruction.Operand.Shift.none),
} },
});
@ -1337,9 +1334,8 @@ fn minMax(
_ = try self.addInst(.{
.tag = .mov,
.cond = cond_choose_lhs,
.data = .{ .rr_op = .{
.data = .{ .r_op_mov = .{
.rd = dest_reg,
.rn = .r0,
.op = Instruction.Operand.reg(lhs_reg, Instruction.Operand.Shift.none),
} },
});
@ -1348,9 +1344,8 @@ fn minMax(
_ = try self.addInst(.{
.tag = .mov,
.cond = cond_choose_rhs,
.data = .{ .rr_op = .{
.data = .{ .r_op_mov = .{
.rd = dest_reg,
.rn = .r0,
.op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none),
} },
});
@ -1682,9 +1677,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
// mov rdlo, #0
_ = try self.addInst(.{
.tag = .mov,
.data = .{ .rr_op = .{
.data = .{ .r_op_mov = .{
.rd = rdlo,
.rn = .r0,
.op = Instruction.Operand.fromU32(0).?,
} },
});
@ -1693,9 +1687,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
_ = try self.addInst(.{
.tag = .mov,
.cond = .ne,
.data = .{ .rr_op = .{
.data = .{ .r_op_mov = .{
.rd = rdlo,
.rn = .r0,
.op = Instruction.Operand.fromU32(1).?,
} },
});
@ -1707,9 +1700,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
_ = try self.addInst(.{
.tag = .mov,
.cond = .ne,
.data = .{ .rr_op = .{
.data = .{ .r_op_mov = .{
.rd = rdlo,
.rn = .r0,
.op = Instruction.Operand.fromU32(1).?,
} },
});
@ -2670,7 +2662,7 @@ fn binOpRegister(
defer if (new_rhs_lock) |reg| self.register_manager.unlockReg(reg);
const dest_reg = switch (mir_tag) {
.cmp => .r0, // cmp has no destination regardless
.cmp => undefined, // cmp has no destination regardless
else => if (metadata) |md| blk: {
if (lhs_is_register and self.reuseOperand(md.inst, md.lhs, 0, lhs)) {
break :blk lhs_reg;
@ -2690,7 +2682,6 @@ fn binOpRegister(
.adds,
.sub,
.subs,
.cmp,
.@"and",
.orr,
.eor,
@ -2699,6 +2690,10 @@ fn binOpRegister(
.rn = lhs_reg,
.op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none),
} },
.cmp => .{ .r_op_cmp = .{
.rn = lhs_reg,
.op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none),
} },
.lsl,
.asr,
.lsr,
@ -2767,7 +2762,7 @@ fn binOpImmediate(
defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);
const dest_reg = switch (mir_tag) {
.cmp => .r0, // cmp has no destination reg
.cmp => undefined, // cmp has no destination reg
else => if (metadata) |md| blk: {
if (lhs_is_register and self.reuseOperand(
md.inst,
@ -2789,7 +2784,6 @@ fn binOpImmediate(
.adds,
.sub,
.subs,
.cmp,
.@"and",
.orr,
.eor,
@ -2798,6 +2792,10 @@ fn binOpImmediate(
.rn = lhs_reg,
.op = Instruction.Operand.fromU32(rhs.immediate).?,
} },
.cmp => .{ .r_op_cmp = .{
.rn = lhs_reg,
.op = Instruction.Operand.fromU32(rhs.immediate).?,
} },
.lsl,
.asr,
.lsr,
@ -3312,9 +3310,8 @@ fn genInlineMemcpy(
// mov count, #0
_ = try self.addInst(.{
.tag = .mov,
.data = .{ .rr_op = .{
.data = .{ .r_op_mov = .{
.rd = count,
.rn = .r0,
.op = Instruction.Operand.imm(0, 0),
} },
});
@ -3323,8 +3320,7 @@ fn genInlineMemcpy(
// cmp count, len
_ = try self.addInst(.{
.tag = .cmp,
.data = .{ .rr_op = .{
.rd = .r0,
.data = .{ .r_op_cmp = .{
.rn = count,
.op = Instruction.Operand.reg(len, Instruction.Operand.Shift.none),
} },
@ -3418,9 +3414,8 @@ fn genInlineMemsetCode(
// mov count, #0
_ = try self.addInst(.{
.tag = .mov,
.data = .{ .rr_op = .{
.data = .{ .r_op_mov = .{
.rd = count,
.rn = .r0,
.op = Instruction.Operand.imm(0, 0),
} },
});
@ -3429,8 +3424,7 @@ fn genInlineMemsetCode(
// cmp count, len
_ = try self.addInst(.{
.tag = .cmp,
.data = .{ .rr_op = .{
.rd = .r0,
.data = .{ .r_op_cmp = .{
.rn = count,
.op = Instruction.Operand.reg(len, Instruction.Operand.Shift.none),
} },
@ -4020,9 +4014,7 @@ fn condBr(self: *Self, condition: MCValue) !Mir.Inst.Index {
// bne ...
_ = try self.addInst(.{
.tag = .cmp,
.cond = .al,
.data = .{ .rr_op = .{
.rd = .r0,
.data = .{ .r_op_cmp = .{
.rn = reg,
.op = Instruction.Operand.imm(1, 0),
} },
@ -4196,8 +4188,7 @@ fn isNull(self: *Self, ty: Type, operand: MCValue) !MCValue {
_ = try self.addInst(.{
.tag = .cmp,
.data = .{ .rr_op = .{
.rd = undefined,
.data = .{ .r_op_cmp = .{
.rn = reg_mcv.register,
.op = Instruction.Operand.fromU32(0).?,
} },
@ -4832,9 +4823,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
.register_v_flag => .vs,
else => unreachable,
},
.data = .{ .rr_op = .{
.data = .{ .r_op_mov = .{
.rd = cond_reg,
.rn = .r0,
.op = Instruction.Operand.fromU32(1).?,
} },
});
@ -4935,9 +4925,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
// mov reg, 0
_ = try self.addInst(.{
.tag = .mov,
.data = .{ .rr_op = .{
.data = .{ .r_op_mov = .{
.rd = reg,
.rn = .r0,
.op = zero,
} },
});
@ -4946,9 +4935,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
_ = try self.addInst(.{
.tag = .mov,
.cond = condition,
.data = .{ .rr_op = .{
.data = .{ .r_op_mov = .{
.rd = reg,
.rn = .r0,
.op = one,
} },
});
@ -4957,18 +4945,16 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
if (Instruction.Operand.fromU32(x)) |op| {
_ = try self.addInst(.{
.tag = .mov,
.data = .{ .rr_op = .{
.data = .{ .r_op_mov = .{
.rd = reg,
.rn = .r0,
.op = op,
} },
});
} else if (Instruction.Operand.fromU32(~x)) |op| {
_ = try self.addInst(.{
.tag = .mvn,
.data = .{ .rr_op = .{
.data = .{ .r_op_mov = .{
.rd = reg,
.rn = .r0,
.op = op,
} },
});
@ -4984,9 +4970,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
} else {
_ = try self.addInst(.{
.tag = .mov,
.data = .{ .rr_op = .{
.data = .{ .r_op_mov = .{
.rd = reg,
.rn = .r0,
.op = Instruction.Operand.imm(@truncate(u8, x), 0),
} },
});
@ -5028,9 +5013,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
// orr reg, reg, #0xdd, 8
_ = try self.addInst(.{
.tag = .mov,
.data = .{ .rr_op = .{
.data = .{ .r_op_mov = .{
.rd = reg,
.rn = .r0,
.op = Instruction.Operand.imm(@truncate(u8, x), 0),
} },
});
@ -5069,9 +5053,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
// mov reg, src_reg
_ = try self.addInst(.{
.tag = .mov,
.data = .{ .rr_op = .{
.data = .{ .r_op_mov = .{
.rd = reg,
.rn = .r0,
.op = Instruction.Operand.reg(src_reg, Instruction.Operand.Shift.none),
} },
});

View File

@ -385,20 +385,44 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
fn mirDataProcessing(emit: *Emit, inst: Mir.Inst.Index) !void {
const tag = emit.mir.instructions.items(.tag)[inst];
const cond = emit.mir.instructions.items(.cond)[inst];
const rr_op = emit.mir.instructions.items(.data)[inst].rr_op;
switch (tag) {
.add => try emit.writeInstruction(Instruction.add(cond, rr_op.rd, rr_op.rn, rr_op.op)),
.adds => try emit.writeInstruction(Instruction.adds(cond, rr_op.rd, rr_op.rn, rr_op.op)),
.@"and" => try emit.writeInstruction(Instruction.@"and"(cond, rr_op.rd, rr_op.rn, rr_op.op)),
.cmp => try emit.writeInstruction(Instruction.cmp(cond, rr_op.rn, rr_op.op)),
.eor => try emit.writeInstruction(Instruction.eor(cond, rr_op.rd, rr_op.rn, rr_op.op)),
.mov => try emit.writeInstruction(Instruction.mov(cond, rr_op.rd, rr_op.op)),
.mvn => try emit.writeInstruction(Instruction.mvn(cond, rr_op.rd, rr_op.op)),
.orr => try emit.writeInstruction(Instruction.orr(cond, rr_op.rd, rr_op.rn, rr_op.op)),
.rsb => try emit.writeInstruction(Instruction.rsb(cond, rr_op.rd, rr_op.rn, rr_op.op)),
.sub => try emit.writeInstruction(Instruction.sub(cond, rr_op.rd, rr_op.rn, rr_op.op)),
.subs => try emit.writeInstruction(Instruction.subs(cond, rr_op.rd, rr_op.rn, rr_op.op)),
.add,
.adds,
.@"and",
.eor,
.orr,
.rsb,
.sub,
.subs,
=> {
const rr_op = emit.mir.instructions.items(.data)[inst].rr_op;
switch (tag) {
.add => try emit.writeInstruction(Instruction.add(cond, rr_op.rd, rr_op.rn, rr_op.op)),
.adds => try emit.writeInstruction(Instruction.adds(cond, rr_op.rd, rr_op.rn, rr_op.op)),
.@"and" => try emit.writeInstruction(Instruction.@"and"(cond, rr_op.rd, rr_op.rn, rr_op.op)),
.eor => try emit.writeInstruction(Instruction.eor(cond, rr_op.rd, rr_op.rn, rr_op.op)),
.orr => try emit.writeInstruction(Instruction.orr(cond, rr_op.rd, rr_op.rn, rr_op.op)),
.rsb => try emit.writeInstruction(Instruction.rsb(cond, rr_op.rd, rr_op.rn, rr_op.op)),
.sub => try emit.writeInstruction(Instruction.sub(cond, rr_op.rd, rr_op.rn, rr_op.op)),
.subs => try emit.writeInstruction(Instruction.subs(cond, rr_op.rd, rr_op.rn, rr_op.op)),
else => unreachable,
}
},
.cmp => {
const r_op_cmp = emit.mir.instructions.items(.data)[inst].r_op_cmp;
try emit.writeInstruction(Instruction.cmp(cond, r_op_cmp.rn, r_op_cmp.op));
},
.mov,
.mvn,
=> {
const r_op_mov = emit.mir.instructions.items(.data)[inst].r_op_mov;
switch (tag) {
.mov => try emit.writeInstruction(Instruction.mov(cond, r_op_mov.rd, r_op_mov.op)),
.mvn => try emit.writeInstruction(Instruction.mvn(cond, r_op_mov.rd, r_op_mov.op)),
else => unreachable,
}
},
else => unreachable,
}
}

View File

@ -166,6 +166,20 @@ pub const Inst = struct {
rd: Register,
imm16: u16,
},
/// A register and an operand
///
/// Used by mov and mvn
r_op_mov: struct {
rd: Register,
op: bits.Instruction.Operand,
},
/// A register and an operand
///
/// Used by cmp
r_op_cmp: struct {
rn: Register,
op: bits.Instruction.Operand,
},
/// Two registers and a shift amount
///
/// Used by e.g. lsl