mirror of
https://github.com/ziglang/zig.git
synced 2025-12-21 21:53:08 +00:00
stage2 ARM: change binOp lowering mechanism to use Mir tags
The Air -> Mir correspondence is not 1:1, so this better represents what Mir insruction we actually want to generate.
This commit is contained in:
parent
8b5d5f44e2
commit
e2e69803dc
@ -1196,7 +1196,7 @@ fn minMax(
|
|||||||
// register.
|
// register.
|
||||||
assert(lhs_reg != rhs_reg); // see note above
|
assert(lhs_reg != rhs_reg); // see note above
|
||||||
|
|
||||||
_ = try self.binOpRegister(.cmp_eq, null, .{ .register = lhs_reg }, .{ .register = rhs_reg }, lhs_ty, rhs_ty);
|
_ = try self.binOpRegister(.cmp, null, .{ .register = lhs_reg }, .{ .register = rhs_reg }, lhs_ty, rhs_ty);
|
||||||
|
|
||||||
const cond_choose_lhs: Condition = switch (tag) {
|
const cond_choose_lhs: Condition = switch (tag) {
|
||||||
.max => switch (int_info.signedness) {
|
.max => switch (int_info.signedness) {
|
||||||
@ -2067,7 +2067,7 @@ fn airFieldParentPtr(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,
|
||||||
@ -2112,8 +2112,8 @@ fn binOpRegister(
|
|||||||
};
|
};
|
||||||
defer self.register_manager.unfreezeRegs(&.{rhs_reg});
|
defer self.register_manager.unfreezeRegs(&.{rhs_reg});
|
||||||
|
|
||||||
const dest_reg = switch (tag) {
|
const dest_reg = switch (mir_tag) {
|
||||||
.cmp_eq => .r0, // cmp has no destination regardless
|
.cmp => .r0, // cmp has no destination regardless
|
||||||
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;
|
||||||
|
|
||||||
@ -2130,41 +2130,21 @@ 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,
|
|
||||||
.sub => .sub,
|
|
||||||
.cmp_eq => .cmp,
|
|
||||||
.mul => .mul,
|
|
||||||
.bit_and,
|
|
||||||
.bool_and,
|
|
||||||
=> .@"and",
|
|
||||||
.bit_or,
|
|
||||||
.bool_or,
|
|
||||||
=> .orr,
|
|
||||||
.shl_exact => .lsl,
|
|
||||||
.shr_exact => switch (lhs_ty.intInfo(self.target.*).signedness) {
|
|
||||||
.signed => Mir.Inst.Tag.asr,
|
|
||||||
.unsigned => Mir.Inst.Tag.lsr,
|
|
||||||
},
|
|
||||||
.xor => .eor,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
const mir_data: Mir.Inst.Data = switch (tag) {
|
|
||||||
.add,
|
.add,
|
||||||
.sub,
|
.sub,
|
||||||
.cmp_eq,
|
.cmp,
|
||||||
.bit_and,
|
.@"and",
|
||||||
.bool_and,
|
.orr,
|
||||||
.bit_or,
|
.eor,
|
||||||
.bool_or,
|
|
||||||
.xor,
|
|
||||||
=> .{ .rr_op = .{
|
=> .{ .rr_op = .{
|
||||||
.rd = dest_reg,
|
.rd = dest_reg,
|
||||||
.rn = lhs_reg,
|
.rn = lhs_reg,
|
||||||
.op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none),
|
.op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none),
|
||||||
} },
|
} },
|
||||||
.shl_exact,
|
.lsl,
|
||||||
.shr_exact,
|
.asr,
|
||||||
|
.lsr,
|
||||||
=> .{ .rr_shift = .{
|
=> .{ .rr_shift = .{
|
||||||
.rd = dest_reg,
|
.rd = dest_reg,
|
||||||
.rm = lhs_reg,
|
.rm = lhs_reg,
|
||||||
@ -2200,7 +2180,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,
|
||||||
@ -2230,8 +2210,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 => .r0, // cmp has no destination reg
|
.cmp => .r0, // cmp has no destination reg
|
||||||
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;
|
||||||
|
|
||||||
@ -2250,40 +2230,21 @@ 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,
|
|
||||||
.sub => .sub,
|
|
||||||
.cmp_eq => .cmp,
|
|
||||||
.bit_and,
|
|
||||||
.bool_and,
|
|
||||||
=> .@"and",
|
|
||||||
.bit_or,
|
|
||||||
.bool_or,
|
|
||||||
=> .orr,
|
|
||||||
.shl_exact => .lsl,
|
|
||||||
.shr_exact => switch (lhs_ty.intInfo(self.target.*).signedness) {
|
|
||||||
.signed => Mir.Inst.Tag.asr,
|
|
||||||
.unsigned => Mir.Inst.Tag.lsr,
|
|
||||||
},
|
|
||||||
.xor => .eor,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
const mir_data: Mir.Inst.Data = switch (tag) {
|
|
||||||
.add,
|
.add,
|
||||||
.sub,
|
.sub,
|
||||||
.cmp_eq,
|
.cmp,
|
||||||
.bit_and,
|
.@"and",
|
||||||
.bool_and,
|
.orr,
|
||||||
.bit_or,
|
.eor,
|
||||||
.bool_or,
|
|
||||||
.xor,
|
|
||||||
=> .{ .rr_op = .{
|
=> .{ .rr_op = .{
|
||||||
.rd = dest_reg,
|
.rd = dest_reg,
|
||||||
.rn = lhs_reg,
|
.rn = lhs_reg,
|
||||||
.op = Instruction.Operand.fromU32(rhs.immediate).?,
|
.op = Instruction.Operand.fromU32(rhs.immediate).?,
|
||||||
} },
|
} },
|
||||||
.shl_exact,
|
.lsl,
|
||||||
.shr_exact,
|
.asr,
|
||||||
|
.lsr,
|
||||||
=> .{ .rr_shift = .{
|
=> .{ .rr_shift = .{
|
||||||
.rd = dest_reg,
|
.rd = dest_reg,
|
||||||
.rm = lhs_reg,
|
.rm = lhs_reg,
|
||||||
@ -2352,13 +2313,20 @@ fn binOp(
|
|||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const mir_tag: Mir.Inst.Tag = switch (tag) {
|
||||||
|
.add => .add,
|
||||||
|
.sub => .sub,
|
||||||
|
.cmp_eq => .cmp,
|
||||||
|
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, 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, 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, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
|
return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
|
||||||
@ -2378,7 +2346,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 ARM binary operations on integers > u32/i32", .{});
|
return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
|
||||||
}
|
}
|
||||||
@ -2432,13 +2400,20 @@ fn binOp(
|
|||||||
const lhs_immediate_ok = lhs == .immediate and Instruction.Operand.fromU32(lhs.immediate) != null;
|
const lhs_immediate_ok = lhs == .immediate and Instruction.Operand.fromU32(lhs.immediate) != null;
|
||||||
const rhs_immediate_ok = rhs == .immediate and Instruction.Operand.fromU32(rhs.immediate) != null;
|
const rhs_immediate_ok = rhs == .immediate and Instruction.Operand.fromU32(rhs.immediate) != null;
|
||||||
|
|
||||||
|
const mir_tag: Mir.Inst.Tag = switch (tag) {
|
||||||
|
.bit_and => .@"and",
|
||||||
|
.bit_or => .orr,
|
||||||
|
.xor => .eor,
|
||||||
|
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, 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, 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, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
|
return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
|
||||||
@ -2457,10 +2432,19 @@ fn binOp(
|
|||||||
if (int_info.bits <= 32) {
|
if (int_info.bits <= 32) {
|
||||||
const rhs_immediate_ok = rhs == .immediate;
|
const rhs_immediate_ok = rhs == .immediate;
|
||||||
|
|
||||||
|
const mir_tag: Mir.Inst.Tag = switch (tag) {
|
||||||
|
.shl_exact => .lsl,
|
||||||
|
.shr_exact => switch (lhs_ty.intInfo(self.target.*).signedness) {
|
||||||
|
.signed => Mir.Inst.Tag.asr,
|
||||||
|
.unsigned => Mir.Inst.Tag.lsr,
|
||||||
|
},
|
||||||
|
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, 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, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
|
return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
|
||||||
@ -2512,13 +2496,19 @@ fn binOp(
|
|||||||
const lhs_immediate_ok = lhs == .immediate;
|
const lhs_immediate_ok = lhs == .immediate;
|
||||||
const rhs_immediate_ok = rhs == .immediate;
|
const rhs_immediate_ok = rhs == .immediate;
|
||||||
|
|
||||||
|
const mir_tag: Mir.Inst.Tag = switch (tag) {
|
||||||
|
.bool_and => .@"and",
|
||||||
|
.bool_or => .orr,
|
||||||
|
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, 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, 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, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
@ -2537,7 +2527,7 @@ fn binOp(
|
|||||||
const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
|
const elem_size = @intCast(u32, 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,
|
||||||
.ptr_sub => .sub,
|
.ptr_sub => .sub,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user