Commit 76ad7af4d8

Jakub Konka <kubkon@jakubkonka.com>
2022-06-07 19:10:26
x64: pull common codepath between store and genSetStack into a helper
1 parent 03068ce
Changed files (1)
src
arch
src/arch/x86_64/CodeGen.zig
@@ -2738,46 +2738,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
                     }
                 },
                 .register => |src_reg| {
-                    const src_reg_lock = self.register_manager.lockReg(src_reg);
-                    defer if (src_reg_lock) |lock| self.register_manager.unlockReg(lock);
-
-                    // TODO common code-path with genSetStack, refactor!
-                    if (!math.isPowerOfTwo(abi_size)) {
-                        const tmp_reg = try self.copyToTmpRegister(value_ty, value);
-
-                        var next_offset: i32 = 0;
-                        var remainder = abi_size;
-                        while (remainder > 0) {
-                            const nearest_power_of_two = @as(u6, 1) << math.log2_int(u3, @intCast(u3, remainder));
-
-                            _ = try self.addInst(.{
-                                .tag = .mov,
-                                .ops = Mir.Inst.Ops.encode(.{
-                                    .reg1 = reg.to64(),
-                                    .reg2 = registerAlias(tmp_reg, nearest_power_of_two),
-                                    .flags = 0b10,
-                                }),
-                                .data = .{ .imm = @bitCast(u32, -next_offset) },
-                            });
-
-                            if (nearest_power_of_two > 1) {
-                                try self.genShiftBinOpMir(.shr, value_ty, tmp_reg, .{ .immediate = nearest_power_of_two * 8 });
-                            }
-
-                            remainder -= nearest_power_of_two;
-                            next_offset -= nearest_power_of_two;
-                        }
-                    } else {
-                        _ = try self.addInst(.{
-                            .tag = .mov,
-                            .ops = Mir.Inst.Ops.encode(.{
-                                .reg1 = reg.to64(),
-                                .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)),
-                                .flags = 0b10,
-                            }),
-                            .data = .{ .imm = 0 },
-                        });
-                    }
+                    try self.genInlineMemcpyRegisterRegister(value_ty, reg, src_reg, 0);
                 },
                 .got_load,
                 .direct_load,
@@ -5638,45 +5599,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
                     return self.fail("TODO genSetStack for register for type float with no intrinsics", .{});
                 },
                 else => {
-                    if (!math.isPowerOfTwo(abi_size)) {
-                        const reg_lock = self.register_manager.lockReg(reg);
-                        defer if (reg_lock) |lock| self.register_manager.unlockReg(lock);
-
-                        const tmp_reg = try self.copyToTmpRegister(ty, mcv);
-
-                        var next_offset = stack_offset;
-                        var remainder = abi_size;
-                        while (remainder > 0) {
-                            const nearest_power_of_two = @as(u6, 1) << math.log2_int(u3, @intCast(u3, remainder));
-
-                            _ = try self.addInst(.{
-                                .tag = .mov,
-                                .ops = Mir.Inst.Ops.encode(.{
-                                    .reg1 = base_reg,
-                                    .reg2 = registerAlias(tmp_reg, nearest_power_of_two),
-                                    .flags = 0b10,
-                                }),
-                                .data = .{ .imm = @bitCast(u32, -next_offset) },
-                            });
-
-                            if (nearest_power_of_two > 1) {
-                                try self.genShiftBinOpMir(.shr, ty, tmp_reg, .{ .immediate = nearest_power_of_two * 8 });
-                            }
-
-                            remainder -= nearest_power_of_two;
-                            next_offset -= nearest_power_of_two;
-                        }
-                    } else {
-                        _ = try self.addInst(.{
-                            .tag = .mov,
-                            .ops = Mir.Inst.Ops.encode(.{
-                                .reg1 = base_reg,
-                                .reg2 = registerAlias(reg, @intCast(u32, abi_size)),
-                                .flags = 0b10,
-                            }),
-                            .data = .{ .imm = @bitCast(u32, -stack_offset) },
-                        });
-                    }
+                    try self.genInlineMemcpyRegisterRegister(ty, base_reg, reg, stack_offset);
                 },
             }
         },
@@ -5711,6 +5634,67 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
     }
 }
 
+/// Like `genInlineMemcpy` but copies value from a register to an address via dereferencing
+/// of destination register.
+/// Boils down to MOV r/m64, r64.
+fn genInlineMemcpyRegisterRegister(
+    self: *Self,
+    ty: Type,
+    dst_reg: Register,
+    src_reg: Register,
+    offset: i32,
+) InnerError!void {
+    assert(dst_reg.size() == 64);
+
+    const dst_reg_lock = self.register_manager.lockReg(dst_reg);
+    defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);
+
+    const src_reg_lock = self.register_manager.lockReg(src_reg);
+    defer if (src_reg_lock) |lock| self.register_manager.unlockReg(lock);
+
+    const abi_size = @intCast(u32, ty.abiSize(self.target.*));
+
+    // TODO common code-path with genSetStack, refactor!
+    if (!math.isPowerOfTwo(abi_size)) {
+        const tmp_reg = try self.copyToTmpRegister(ty, .{ .register = src_reg });
+
+        var next_offset = offset;
+        var remainder = abi_size;
+        while (remainder > 0) {
+            const nearest_power_of_two = @as(u6, 1) << math.log2_int(u3, @intCast(u3, remainder));
+
+            _ = try self.addInst(.{
+                .tag = .mov,
+                .ops = Mir.Inst.Ops.encode(.{
+                    .reg1 = dst_reg,
+                    .reg2 = registerAlias(tmp_reg, nearest_power_of_two),
+                    .flags = 0b10,
+                }),
+                .data = .{ .imm = @bitCast(u32, -next_offset) },
+            });
+
+            if (nearest_power_of_two > 1) {
+                try self.genShiftBinOpMir(.shr, ty, tmp_reg, .{
+                    .immediate = nearest_power_of_two * 8,
+                });
+            }
+
+            remainder -= nearest_power_of_two;
+            next_offset -= nearest_power_of_two;
+        }
+    } else {
+        _ = try self.addInst(.{
+            .tag = .mov,
+            .ops = Mir.Inst.Ops.encode(.{
+                .reg1 = dst_reg,
+                .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)),
+                .flags = 0b10,
+            }),
+            .data = .{ .imm = @bitCast(u32, -offset) },
+        });
+    }
+}
+
 const InlineMemcpyOpts = struct {
     source_stack_base: ?Register = null,
     dest_stack_base: ?Register = null,