mirror of
https://github.com/ziglang/zig.git
synced 2025-12-17 19:53:06 +00:00
stage2 AArch64: replace genMulConstant with binOp
This commit is contained in:
parent
19c683fab0
commit
ec62e76455
@ -1040,6 +1040,7 @@ fn binOpRegister(
|
|||||||
const mir_tag: Mir.Inst.Tag = switch (tag) {
|
const mir_tag: Mir.Inst.Tag = switch (tag) {
|
||||||
.add, .ptr_add => .add_shifted_register,
|
.add, .ptr_add => .add_shifted_register,
|
||||||
.sub, .ptr_sub => .sub_shifted_register,
|
.sub, .ptr_sub => .sub_shifted_register,
|
||||||
|
.mul => .mul,
|
||||||
.xor => .eor_shifted_register,
|
.xor => .eor_shifted_register,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
@ -1055,6 +1056,11 @@ fn binOpRegister(
|
|||||||
.imm6 = 0,
|
.imm6 = 0,
|
||||||
.shift = .lsl,
|
.shift = .lsl,
|
||||||
} },
|
} },
|
||||||
|
.mul => .{ .rrr = .{
|
||||||
|
.rd = dest_reg,
|
||||||
|
.rn = lhs_reg,
|
||||||
|
.rm = rhs_reg,
|
||||||
|
} },
|
||||||
.xor => .{ .rrr_imm6_logical_shift = .{
|
.xor => .{ .rrr_imm6_logical_shift = .{
|
||||||
.rd = dest_reg,
|
.rd = dest_reg,
|
||||||
.rn = lhs_reg,
|
.rn = lhs_reg,
|
||||||
@ -1221,6 +1227,24 @@ fn binOp(
|
|||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.mul => {
|
||||||
|
switch (lhs_ty.zigTypeTag()) {
|
||||||
|
.Vector => return self.fail("TODO binary operations on vectors", .{}),
|
||||||
|
.Int => {
|
||||||
|
assert(lhs_ty.eql(rhs_ty));
|
||||||
|
const int_info = lhs_ty.intInfo(self.target.*);
|
||||||
|
if (int_info.bits <= 64) {
|
||||||
|
// TODO add optimisations for multiplication
|
||||||
|
// with immediates, for example a * 2 can be
|
||||||
|
// lowered to a << 1
|
||||||
|
return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
|
||||||
|
} else {
|
||||||
|
return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
},
|
||||||
// Bitwise operations on integers
|
// Bitwise operations on integers
|
||||||
.xor => {
|
.xor => {
|
||||||
switch (lhs_ty.zigTypeTag()) {
|
switch (lhs_ty.zigTypeTag()) {
|
||||||
@ -1544,88 +1568,37 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
};
|
};
|
||||||
self.register_manager.freezeRegs(&.{base_mcv.register});
|
self.register_manager.freezeRegs(&.{base_mcv.register});
|
||||||
|
|
||||||
// TODO implement optimized ldr for airSliceElemVal
|
switch (elem_size) {
|
||||||
const dst_mcv = try self.allocRegOrMem(inst, true);
|
else => {
|
||||||
|
const dst_mcv = try self.allocRegOrMem(inst, true);
|
||||||
|
|
||||||
const offset_mcv = try self.genMulConstant(bin_op.rhs, @intCast(u32, elem_size));
|
const offset_mcv = try self.binOp(
|
||||||
assert(offset_mcv == .register); // result of multiplication should always be register
|
.mul,
|
||||||
self.register_manager.freezeRegs(&.{offset_mcv.register});
|
null,
|
||||||
|
index_mcv,
|
||||||
|
.{ .immediate = elem_size },
|
||||||
|
Type.usize,
|
||||||
|
Type.usize,
|
||||||
|
);
|
||||||
|
assert(offset_mcv == .register); // result of multiplication should always be register
|
||||||
|
self.register_manager.freezeRegs(&.{offset_mcv.register});
|
||||||
|
|
||||||
const addr_reg = try self.register_manager.allocReg(null);
|
const addr_mcv = try self.binOp(.add, null, base_mcv, offset_mcv, Type.usize, Type.usize);
|
||||||
self.register_manager.freezeRegs(&.{addr_reg});
|
|
||||||
defer self.register_manager.unfreezeRegs(&.{addr_reg});
|
|
||||||
|
|
||||||
_ = try self.addInst(.{
|
// At this point in time, neither the base register
|
||||||
.tag = .add_shifted_register,
|
// nor the offset register contains any valuable data
|
||||||
.data = .{ .rrr_imm6_shift = .{
|
// anymore.
|
||||||
.rd = addr_reg,
|
self.register_manager.unfreezeRegs(&.{ base_mcv.register, offset_mcv.register });
|
||||||
.rn = base_mcv.register,
|
|
||||||
.rm = offset_mcv.register,
|
|
||||||
.imm6 = 0,
|
|
||||||
.shift = .lsl,
|
|
||||||
} },
|
|
||||||
});
|
|
||||||
|
|
||||||
// At this point in time, neither the base register
|
try self.load(dst_mcv, addr_mcv, slice_ptr_field_type);
|
||||||
// nor the offset register contains any valuable data
|
|
||||||
// anymore.
|
|
||||||
self.register_manager.unfreezeRegs(&.{ base_mcv.register, offset_mcv.register });
|
|
||||||
|
|
||||||
try self.load(dst_mcv, .{ .register = addr_reg }, slice_ptr_field_type);
|
break :result dst_mcv;
|
||||||
|
},
|
||||||
break :result dst_mcv;
|
}
|
||||||
};
|
};
|
||||||
return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
|
return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn genMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue {
|
|
||||||
const lhs = try self.resolveInst(op);
|
|
||||||
const rhs = MCValue{ .immediate = imm };
|
|
||||||
|
|
||||||
const lhs_is_register = lhs == .register;
|
|
||||||
|
|
||||||
if (lhs_is_register) self.register_manager.freezeRegs(&.{lhs.register});
|
|
||||||
defer if (lhs_is_register) self.register_manager.unfreezeRegs(&.{lhs.register});
|
|
||||||
|
|
||||||
// Destination must be a register
|
|
||||||
// LHS must be a register
|
|
||||||
// RHS must be a register
|
|
||||||
var dst_mcv: MCValue = undefined;
|
|
||||||
var lhs_mcv: MCValue = lhs;
|
|
||||||
var rhs_mcv: MCValue = rhs;
|
|
||||||
|
|
||||||
// Allocate registers for operands and/or destination
|
|
||||||
// Allocate 1 or 2 registers
|
|
||||||
if (lhs_is_register) {
|
|
||||||
// Move RHS to register
|
|
||||||
dst_mcv = MCValue{ .register = try self.register_manager.allocReg(null) };
|
|
||||||
rhs_mcv = dst_mcv;
|
|
||||||
} else {
|
|
||||||
// Move LHS and RHS to register
|
|
||||||
const regs = try self.register_manager.allocRegs(2, .{ null, null });
|
|
||||||
lhs_mcv = MCValue{ .register = regs[0] };
|
|
||||||
rhs_mcv = MCValue{ .register = regs[1] };
|
|
||||||
dst_mcv = lhs_mcv;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move the operands to the newly allocated registers
|
|
||||||
if (!lhs_is_register) {
|
|
||||||
try self.genSetReg(self.air.typeOf(op), lhs_mcv.register, lhs);
|
|
||||||
}
|
|
||||||
try self.genSetReg(Type.initTag(.usize), rhs_mcv.register, rhs);
|
|
||||||
|
|
||||||
_ = try self.addInst(.{
|
|
||||||
.tag = .mul,
|
|
||||||
.data = .{ .rrr = .{
|
|
||||||
.rd = dst_mcv.register,
|
|
||||||
.rn = lhs_mcv.register,
|
|
||||||
.rm = rhs_mcv.register,
|
|
||||||
} },
|
|
||||||
});
|
|
||||||
|
|
||||||
return dst_mcv;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {
|
fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
|
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
|
||||||
const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
|
const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
|
||||||
|
|||||||
@ -8,7 +8,6 @@ test "@bitReverse large exotic integer" {
|
|||||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
||||||
// Currently failing on stage1 for big-endian targets
|
// Currently failing on stage1 for big-endian targets
|
||||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ const ptr = &global;
|
|||||||
var global: usize = 123;
|
var global: usize = 123;
|
||||||
|
|
||||||
test "constant pointer to global variable causes runtime load" {
|
test "constant pointer to global variable causes runtime load" {
|
||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
|
||||||
global = 1234;
|
global = 1234;
|
||||||
try expect(&global == ptr);
|
try expect(&global == ptr);
|
||||||
try expect(ptr.* == 1234);
|
try expect(ptr.* == 1234);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user