authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-20 19:14:04+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-21 22:54:09+01:00
logec62e764551557bfaef2bc0daa0398307420257e
tree55e6f21612e1e99a3beb61373d7a056b9b6813ad
parent19c683fab01f6f7141166b7fea2c5932a819a727
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: replace genMulConstant with binOp


3 files changed, 47 insertions(+), 75 deletions(-)

src/arch/aarch64/CodeGen.zig+46-73
...@@ -1040,6 +1040,7 @@ fn binOpRegister(...@@ -1040,6 +1040,7 @@ fn binOpRegister(
1040 const mir_tag: Mir.Inst.Tag = switch (tag) {1040 const mir_tag: Mir.Inst.Tag = switch (tag) {
1041 .add, .ptr_add => .add_shifted_register,1041 .add, .ptr_add => .add_shifted_register,
1042 .sub, .ptr_sub => .sub_shifted_register,1042 .sub, .ptr_sub => .sub_shifted_register,
1043 .mul => .mul,
1043 .xor => .eor_shifted_register,1044 .xor => .eor_shifted_register,
1044 else => unreachable,1045 else => unreachable,
1045 };1046 };
...@@ -1055,6 +1056,11 @@ fn binOpRegister(...@@ -1055,6 +1056,11 @@ fn binOpRegister(
1055 .imm6 = 0,1056 .imm6 = 0,
1056 .shift = .lsl,1057 .shift = .lsl,
1057 } },1058 } },
1059 .mul => .{ .rrr = .{
1060 .rd = dest_reg,
1061 .rn = lhs_reg,
1062 .rm = rhs_reg,
1063 } },
1058 .xor => .{ .rrr_imm6_logical_shift = .{1064 .xor => .{ .rrr_imm6_logical_shift = .{
1059 .rd = dest_reg,1065 .rd = dest_reg,
1060 .rn = lhs_reg,1066 .rn = lhs_reg,
...@@ -1221,6 +1227,24 @@ fn binOp(...@@ -1221,6 +1227,24 @@ fn binOp(
1221 else => unreachable,1227 else => unreachable,
1222 }1228 }
1223 },1229 },
1230 .mul => {
1231 switch (lhs_ty.zigTypeTag()) {
1232 .Vector => return self.fail("TODO binary operations on vectors", .{}),
1233 .Int => {
1234 assert(lhs_ty.eql(rhs_ty));
1235 const int_info = lhs_ty.intInfo(self.target.*);
1236 if (int_info.bits <= 64) {
1237 // TODO add optimisations for multiplication
1238 // with immediates, for example a * 2 can be
1239 // lowered to a << 1
1240 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
1241 } else {
1242 return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
1243 }
1244 },
1245 else => unreachable,
1246 }
1247 },
1224 // Bitwise operations on integers1248 // Bitwise operations on integers
1225 .xor => {1249 .xor => {
1226 switch (lhs_ty.zigTypeTag()) {1250 switch (lhs_ty.zigTypeTag()) {
...@@ -1544,88 +1568,37 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1544,88 +1568,37 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
1544 };1568 };
1545 self.register_manager.freezeRegs(&.{base_mcv.register});1569 self.register_manager.freezeRegs(&.{base_mcv.register});
15461570
1547 // TODO implement optimized ldr for airSliceElemVal1571 switch (elem_size) {
1548 const dst_mcv = try self.allocRegOrMem(inst, true);1572 else => {
1573 const dst_mcv = try self.allocRegOrMem(inst, true);
15491574
1550 const offset_mcv = try self.genMulConstant(bin_op.rhs, @intCast(u32, elem_size));1575 const offset_mcv = try self.binOp(
1551 assert(offset_mcv == .register); // result of multiplication should always be register1576 .mul,
1552 self.register_manager.freezeRegs(&.{offset_mcv.register});1577 null,
1578 index_mcv,
1579 .{ .immediate = elem_size },
1580 Type.usize,
1581 Type.usize,
1582 );
1583 assert(offset_mcv == .register); // result of multiplication should always be register
1584 self.register_manager.freezeRegs(&.{offset_mcv.register});
15531585
1554 const addr_reg = try self.register_manager.allocReg(null);1586 const addr_mcv = try self.binOp(.add, null, base_mcv, offset_mcv, Type.usize, Type.usize);
1555 self.register_manager.freezeRegs(&.{addr_reg});
1556 defer self.register_manager.unfreezeRegs(&.{addr_reg});
15571587
1558 _ = try self.addInst(.{1588 // At this point in time, neither the base register
1559 .tag = .add_shifted_register,1589 // nor the offset register contains any valuable data
1560 .data = .{ .rrr_imm6_shift = .{1590 // anymore.
1561 .rd = addr_reg,1591 self.register_manager.unfreezeRegs(&.{ base_mcv.register, offset_mcv.register });
1562 .rn = base_mcv.register,
1563 .rm = offset_mcv.register,
1564 .imm6 = 0,
1565 .shift = .lsl,
1566 } },
1567 });
15681592
1569 // At this point in time, neither the base register1593 try self.load(dst_mcv, addr_mcv, slice_ptr_field_type);
1570 // nor the offset register contains any valuable data
1571 // anymore.
1572 self.register_manager.unfreezeRegs(&.{ base_mcv.register, offset_mcv.register });
15731594
1574 try self.load(dst_mcv, .{ .register = addr_reg }, slice_ptr_field_type);1595 break :result dst_mcv;
15751596 },
1576 break :result dst_mcv;1597 }
1577 };1598 };
1578 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1599 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1579}1600}
15801601
1581fn genMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue {
1582 const lhs = try self.resolveInst(op);
1583 const rhs = MCValue{ .immediate = imm };
1584
1585 const lhs_is_register = lhs == .register;
1586
1587 if (lhs_is_register) self.register_manager.freezeRegs(&.{lhs.register});
1588 defer if (lhs_is_register) self.register_manager.unfreezeRegs(&.{lhs.register});
1589
1590 // Destination must be a register
1591 // LHS must be a register
1592 // RHS must be a register
1593 var dst_mcv: MCValue = undefined;
1594 var lhs_mcv: MCValue = lhs;
1595 var rhs_mcv: MCValue = rhs;
1596
1597 // Allocate registers for operands and/or destination
1598 // Allocate 1 or 2 registers
1599 if (lhs_is_register) {
1600 // Move RHS to register
1601 dst_mcv = MCValue{ .register = try self.register_manager.allocReg(null) };
1602 rhs_mcv = dst_mcv;
1603 } else {
1604 // Move LHS and RHS to register
1605 const regs = try self.register_manager.allocRegs(2, .{ null, null });
1606 lhs_mcv = MCValue{ .register = regs[0] };
1607 rhs_mcv = MCValue{ .register = regs[1] };
1608 dst_mcv = lhs_mcv;
1609 }
1610
1611 // Move the operands to the newly allocated registers
1612 if (!lhs_is_register) {
1613 try self.genSetReg(self.air.typeOf(op), lhs_mcv.register, lhs);
1614 }
1615 try self.genSetReg(Type.initTag(.usize), rhs_mcv.register, rhs);
1616
1617 _ = try self.addInst(.{
1618 .tag = .mul,
1619 .data = .{ .rrr = .{
1620 .rd = dst_mcv.register,
1621 .rn = lhs_mcv.register,
1622 .rm = rhs_mcv.register,
1623 } },
1624 });
1625
1626 return dst_mcv;
1627}
1628
1629fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {1602fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {
1630 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1603 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1631 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;1604 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
test/behavior/bitreverse.zig-1
...@@ -8,7 +8,6 @@ test "@bitReverse large exotic integer" {...@@ -8,7 +8,6 @@ test "@bitReverse large exotic integer" {
8 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;8 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
11 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
12 // Currently failing on stage1 for big-endian targets11 // Currently failing on stage1 for big-endian targets
13 if (builtin.zig_backend == .stage1) return error.SkipZigTest;12 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
1413
test/behavior/bugs/1486.zig+1-1
...@@ -6,7 +6,7 @@ const ptr = &global;...@@ -6,7 +6,7 @@ const ptr = &global;
6var global: usize = 123;6var global: usize = 123;
77
8test "constant pointer to global variable causes runtime load" {8test "constant pointer to global variable causes runtime load" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
10 global = 1234;10 global = 1234;
11 try expect(&global == ptr);11 try expect(&global == ptr);
12 try expect(ptr.* == 1234);12 try expect(ptr.* == 1234);