stage2 AArch64: change binOp lowering mechanism to use Mir tags

Mirrors e2e69803dc16efe11a6d42c6c49853e16a41fd0c for AArch64
This commit is contained in:
joachimschmidt557 2022-04-17 20:47:01 +02:00
parent 0a909a6712
commit cbb13c023e
No known key found for this signature in database
GPG Key ID: E0B575BE2884ACC5

View File

@ -1193,7 +1193,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
/// Asserts that generating an instruction of that form is possible. /// Asserts that generating an instruction of that form is possible.
fn binOpRegister( fn binOpRegister(
self: *Self, self: *Self,
tag: Air.Inst.Tag, mir_tag: Mir.Inst.Tag,
maybe_inst: ?Air.Inst.Index, maybe_inst: ?Air.Inst.Index,
lhs: MCValue, lhs: MCValue,
rhs: MCValue, rhs: MCValue,
@ -1256,38 +1256,9 @@ fn binOpRegister(
if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs); if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs); if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
const mir_tag: Mir.Inst.Tag = switch (tag) { const mir_data: Mir.Inst.Data = switch (mir_tag) {
.add, .add_shifted_register,
.ptr_add, .sub_shifted_register,
=> .add_shifted_register,
.sub,
.ptr_sub,
=> .sub_shifted_register,
.cmp_eq => .cmp_shifted_register,
.mul => .mul,
.bit_and,
.bool_and,
=> .and_shifted_register,
.bit_or,
.bool_or,
=> .orr_shifted_register,
.shl,
.shl_exact,
=> .lsl_register,
.shr,
.shr_exact,
=> switch (lhs_ty.intInfo(self.target.*).signedness) {
.signed => Mir.Inst.Tag.asr_register,
.unsigned => Mir.Inst.Tag.lsr_register,
},
.xor => .eor_shifted_register,
else => unreachable,
};
const mir_data: Mir.Inst.Data = switch (tag) {
.add,
.sub,
.ptr_add,
.ptr_sub,
=> .{ .rrr_imm6_shift = .{ => .{ .rrr_imm6_shift = .{
.rd = dest_reg, .rd = dest_reg,
.rn = lhs_reg, .rn = lhs_reg,
@ -1295,27 +1266,24 @@ fn binOpRegister(
.imm6 = 0, .imm6 = 0,
.shift = .lsl, .shift = .lsl,
} }, } },
.cmp_eq => .{ .rr_imm6_shift = .{ .cmp_shifted_register => .{ .rr_imm6_shift = .{
.rn = lhs_reg, .rn = lhs_reg,
.rm = rhs_reg, .rm = rhs_reg,
.imm6 = 0, .imm6 = 0,
.shift = .lsl, .shift = .lsl,
} }, } },
.mul, .mul,
.shl, .lsl_register,
.shl_exact, .asr_register,
.shr, .lsr_register,
.shr_exact,
=> .{ .rrr = .{ => .{ .rrr = .{
.rd = dest_reg, .rd = dest_reg,
.rn = lhs_reg, .rn = lhs_reg,
.rm = rhs_reg, .rm = rhs_reg,
} }, } },
.bit_and, .and_shifted_register,
.bool_and, .orr_shifted_register,
.bit_or, .eor_shifted_register,
.bool_or,
.xor,
=> .{ .rrr_imm6_logical_shift = .{ => .{ .rrr_imm6_logical_shift = .{
.rd = dest_reg, .rd = dest_reg,
.rn = lhs_reg, .rn = lhs_reg,
@ -1348,7 +1316,7 @@ fn binOpRegister(
/// Asserts that generating an instruction of that form is possible. /// Asserts that generating an instruction of that form is possible.
fn binOpImmediate( fn binOpImmediate(
self: *Self, self: *Self,
tag: Air.Inst.Tag, mir_tag: Mir.Inst.Tag,
maybe_inst: ?Air.Inst.Index, maybe_inst: ?Air.Inst.Index,
lhs: MCValue, lhs: MCValue,
rhs: MCValue, rhs: MCValue,
@ -1379,8 +1347,8 @@ fn binOpImmediate(
}; };
defer self.register_manager.unfreezeRegs(&.{lhs_reg}); defer self.register_manager.unfreezeRegs(&.{lhs_reg});
const dest_reg = switch (tag) { const dest_reg = switch (mir_tag) {
.cmp_eq => undefined, // cmp has no destination register .cmp_immediate => undefined, // cmp has no destination register
else => if (maybe_inst) |inst| blk: { else => if (maybe_inst) |inst| blk: {
const bin_op = self.air.instructions.items(.data)[inst].bin_op; const bin_op = self.air.instructions.items(.data)[inst].bin_op;
@ -1400,39 +1368,23 @@ fn binOpImmediate(
if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs); if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
const mir_tag: Mir.Inst.Tag = switch (tag) { const mir_data: Mir.Inst.Data = switch (mir_tag) {
.add => .add_immediate, .add_immediate,
.sub => .sub_immediate, .sub_immediate,
.shl,
.shl_exact,
=> .lsl_immediate,
.shr,
.shr_exact,
=> switch (lhs_ty.intInfo(self.target.*).signedness) {
.signed => Mir.Inst.Tag.asr_immediate,
.unsigned => Mir.Inst.Tag.lsr_immediate,
},
.cmp_eq => .cmp_immediate,
else => unreachable,
};
const mir_data: Mir.Inst.Data = switch (tag) {
.add,
.sub,
=> .{ .rr_imm12_sh = .{ => .{ .rr_imm12_sh = .{
.rd = dest_reg, .rd = dest_reg,
.rn = lhs_reg, .rn = lhs_reg,
.imm12 = @intCast(u12, rhs.immediate), .imm12 = @intCast(u12, rhs.immediate),
} }, } },
.shl, .lsl_immediate,
.shl_exact, .asr_immediate,
.shr, .lsr_immediate,
.shr_exact,
=> .{ .rr_shift = .{ => .{ .rr_shift = .{
.rd = dest_reg, .rd = dest_reg,
.rn = lhs_reg, .rn = lhs_reg,
.shift = @intCast(u6, rhs.immediate), .shift = @intCast(u6, rhs.immediate),
} }, } },
.cmp_eq => .{ .r_imm12_sh = .{ .cmp_immediate => .{ .r_imm12_sh = .{
.rn = lhs_reg, .rn = lhs_reg,
.imm12 = @intCast(u12, rhs.immediate), .imm12 = @intCast(u12, rhs.immediate),
} }, } },
@ -1470,7 +1422,6 @@ fn binOp(
) InnerError!MCValue { ) InnerError!MCValue {
const target = self.target.*; const target = self.target.*;
switch (tag) { switch (tag) {
// Arithmetic operations on integers and floats
.add, .add,
.sub, .sub,
.cmp_eq, .cmp_eq,
@ -1498,13 +1449,26 @@ fn binOp(
else => unreachable, else => unreachable,
}; };
const mir_tag_register: Mir.Inst.Tag = switch (tag) {
.add => .add_shifted_register,
.sub => .sub_shifted_register,
.cmp_eq => .cmp_shifted_register,
else => unreachable,
};
const mir_tag_immediate: Mir.Inst.Tag = switch (tag) {
.add => .add_immediate,
.sub => .sub_immediate,
.cmp_eq => .cmp_immediate,
else => unreachable,
};
if (rhs_immediate_ok) { if (rhs_immediate_ok) {
return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false); return try self.binOpImmediate(mir_tag_immediate, maybe_inst, lhs, rhs, lhs_ty, false);
} else if (lhs_immediate_ok) { } else if (lhs_immediate_ok) {
// swap lhs and rhs // swap lhs and rhs
return try self.binOpImmediate(tag, maybe_inst, rhs, lhs, rhs_ty, true); return try self.binOpImmediate(mir_tag_immediate, maybe_inst, rhs, lhs, rhs_ty, true);
} else { } else {
return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); return try self.binOpRegister(mir_tag_register, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
} }
} else { } else {
return self.fail("TODO binary operations on int with bits > 64", .{}); return self.fail("TODO binary operations on int with bits > 64", .{});
@ -1523,7 +1487,7 @@ fn binOp(
// TODO add optimisations for multiplication // TODO add optimisations for multiplication
// with immediates, for example a * 2 can be // with immediates, for example a * 2 can be
// lowered to a << 1 // lowered to a << 1
return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); return try self.binOpRegister(.mul, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
} else { } else {
return self.fail("TODO binary operations on int with bits > 64", .{}); return self.fail("TODO binary operations on int with bits > 64", .{});
} }
@ -1564,7 +1528,6 @@ fn binOp(
else => unreachable, else => unreachable,
} }
}, },
// Bitwise operations on integers
.bit_and, .bit_and,
.bit_or, .bit_or,
.xor, .xor,
@ -1576,7 +1539,14 @@ fn binOp(
const int_info = lhs_ty.intInfo(self.target.*); const int_info = lhs_ty.intInfo(self.target.*);
if (int_info.bits <= 64) { if (int_info.bits <= 64) {
// TODO implement bitwise operations with immediates // TODO implement bitwise operations with immediates
return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); const mir_tag: Mir.Inst.Tag = switch (tag) {
.bit_and => .and_shifted_register,
.bit_or => .orr_shifted_register,
.xor => .eor_shifted_register,
else => unreachable,
};
return try self.binOpRegister(mir_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
} else { } else {
return self.fail("TODO binary operations on int with bits > 64", .{}); return self.fail("TODO binary operations on int with bits > 64", .{});
} }
@ -1594,10 +1564,27 @@ fn binOp(
if (int_info.bits <= 64) { if (int_info.bits <= 64) {
const rhs_immediate_ok = rhs == .immediate; const rhs_immediate_ok = rhs == .immediate;
const mir_tag_register: Mir.Inst.Tag = switch (tag) {
.shl => .lsl_register,
.shr => switch (lhs_ty.intInfo(self.target.*).signedness) {
.signed => Mir.Inst.Tag.asr_register,
.unsigned => Mir.Inst.Tag.lsr_register,
},
else => unreachable,
};
const mir_tag_immediate: Mir.Inst.Tag = switch (tag) {
.shl => .lsl_immediate,
.shr => switch (lhs_ty.intInfo(self.target.*).signedness) {
.signed => Mir.Inst.Tag.asr_immediate,
.unsigned => Mir.Inst.Tag.lsr_immediate,
},
else => unreachable,
};
if (rhs_immediate_ok) { if (rhs_immediate_ok) {
return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false); return try self.binOpImmediate(mir_tag_immediate, maybe_inst, lhs, rhs, lhs_ty, false);
} else { } else {
return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); return try self.binOpRegister(mir_tag_register, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
} }
} else { } else {
return self.fail("TODO binary operations on int with bits > 64", .{}); return self.fail("TODO binary operations on int with bits > 64", .{});
@ -1614,7 +1601,13 @@ fn binOp(
assert(lhs != .immediate); // should have been handled by Sema assert(lhs != .immediate); // should have been handled by Sema
assert(rhs != .immediate); // should have been handled by Sema assert(rhs != .immediate); // should have been handled by Sema
return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); const mir_tag_register: Mir.Inst.Tag = switch (tag) {
.bool_and => .and_shifted_register,
.bool_or => .orr_shifted_register,
else => unreachable,
};
return try self.binOpRegister(mir_tag_register, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
}, },
else => unreachable, else => unreachable,
} }
@ -1632,9 +1625,9 @@ fn binOp(
const elem_size = elem_ty.abiSize(self.target.*); const elem_size = elem_ty.abiSize(self.target.*);
if (elem_size == 1) { if (elem_size == 1) {
const base_tag: Air.Inst.Tag = switch (tag) { const base_tag: Mir.Inst.Tag = switch (tag) {
.ptr_add => .add, .ptr_add => .add_shifted_register,
.ptr_sub => .sub, .ptr_sub => .sub_shifted_register,
else => unreachable, else => unreachable,
}; };