authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-10-04 17:27:54+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-10-20 16:14:52+02:00
logea7a60116d2ddb30a1684b67d892cb72f631a9f3
treee40f7fccef8488fd9a89dfd1b61053c473946e33
parentd8fddb535ca425be8db42e3d86e3715cc6ebad56
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: move add+sub to new allocRegs mechanism


1 files changed, 108 insertions(+), 90 deletions(-)

src/arch/aarch64/CodeGen.zig+108-90
......@@ -1582,7 +1582,7 @@ fn binOpImmediateNew(
15821582 self: *Self,
15831583 mir_tag: Mir.Inst.Tag,
15841584 lhs_bind: ReadArg.Bind,
1585 rhs_immediate: u32,
1585 rhs_immediate: u64,
15861586 lhs_ty: Type,
15871587 lhs_and_rhs_swapped: bool,
15881588 maybe_inst: ?Air.Inst.Index,
......@@ -1910,57 +1910,6 @@ fn binOp(
19101910) InnerError!MCValue {
19111911 const mod = self.bin_file.options.module.?;
19121912 switch (tag) {
1913 .add,
1914 .sub,
1915 => {
1916 switch (lhs_ty.zigTypeTag()) {
1917 .Float => return self.fail("TODO binary operations on floats", .{}),
1918 .Vector => return self.fail("TODO binary operations on vectors", .{}),
1919 .Int => {
1920 assert(lhs_ty.eql(rhs_ty, mod));
1921 const int_info = lhs_ty.intInfo(self.target.*);
1922 if (int_info.bits <= 64) {
1923 // Only say yes if the operation is
1924 // commutative, i.e. we can swap both of the
1925 // operands
1926 const lhs_immediate_ok = switch (tag) {
1927 .add => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
1928 .sub => false,
1929 else => unreachable,
1930 };
1931 const rhs_immediate_ok = switch (tag) {
1932 .add,
1933 .sub,
1934 => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),
1935 else => unreachable,
1936 };
1937
1938 const mir_tag_register: Mir.Inst.Tag = switch (tag) {
1939 .add => .add_shifted_register,
1940 .sub => .sub_shifted_register,
1941 else => unreachable,
1942 };
1943 const mir_tag_immediate: Mir.Inst.Tag = switch (tag) {
1944 .add => .add_immediate,
1945 .sub => .sub_immediate,
1946 else => unreachable,
1947 };
1948
1949 if (rhs_immediate_ok) {
1950 return try self.binOpImmediate(mir_tag_immediate, lhs, rhs, lhs_ty, false, metadata);
1951 } else if (lhs_immediate_ok) {
1952 // swap lhs and rhs
1953 return try self.binOpImmediate(mir_tag_immediate, rhs, lhs, rhs_ty, true, metadata);
1954 } else {
1955 return try self.binOpRegister(mir_tag_register, lhs, rhs, lhs_ty, rhs_ty, metadata);
1956 }
1957 } else {
1958 return self.fail("TODO binary operations on int with bits > 64", .{});
1959 }
1960 },
1961 else => unreachable,
1962 }
1963 },
19641913 .mul => {
19651914 switch (lhs_ty.zigTypeTag()) {
19661915 .Vector => return self.fail("TODO binary operations on vectors", .{}),
......@@ -2134,8 +2083,18 @@ fn binOp(
21342083 else => unreachable,
21352084 };
21362085
2086 const lhs_bind = if (metadata) |md|
2087 ReadArg.Bind{ .inst = md.lhs }
2088 else
2089 ReadArg.Bind{ .mcv = lhs };
2090 const rhs_bind = if (metadata) |md|
2091 ReadArg.Bind{ .inst = md.rhs }
2092 else
2093 ReadArg.Bind{ .mcv = rhs };
2094
21372095 // Generate an add/sub/mul
2138 const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
2096 const maybe_inst: ?Air.Inst.Index = if (metadata) |md| md.inst else null;
2097 const result = try self.addSub(base_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
21392098
21402099 // Truncate if necessary
21412100 switch (lhs_ty.zigTypeTag()) {
......@@ -2304,21 +2263,93 @@ fn binOp(
23042263 }
23052264}
23062265
2266fn addSub(
2267 self: *Self,
2268 tag: Air.Inst.Tag,
2269 lhs_bind: ReadArg.Bind,
2270 rhs_bind: ReadArg.Bind,
2271 lhs_ty: Type,
2272 rhs_ty: Type,
2273 maybe_inst: ?Air.Inst.Index,
2274) InnerError!MCValue {
2275 const mod = self.bin_file.options.module.?;
2276 switch (lhs_ty.zigTypeTag()) {
2277 .Float => return self.fail("TODO binary operations on floats", .{}),
2278 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2279 .Int => {
2280 assert(lhs_ty.eql(rhs_ty, mod));
2281 const int_info = lhs_ty.intInfo(self.target.*);
2282 if (int_info.bits <= 64) {
2283 const lhs_immediate = try lhs_bind.resolveToImmediate(self);
2284 const rhs_immediate = try rhs_bind.resolveToImmediate(self);
2285
2286 // Only say yes if the operation is
2287 // commutative, i.e. we can swap both of the
2288 // operands
2289 const lhs_immediate_ok = switch (tag) {
2290 .add => if (lhs_immediate) |imm| imm <= std.math.maxInt(u12) else false,
2291 .sub => false,
2292 else => unreachable,
2293 };
2294 const rhs_immediate_ok = switch (tag) {
2295 .add,
2296 .sub,
2297 => if (rhs_immediate) |imm| imm <= std.math.maxInt(u12) else false,
2298 else => unreachable,
2299 };
2300
2301 const mir_tag_register: Mir.Inst.Tag = switch (tag) {
2302 .add => .add_shifted_register,
2303 .sub => .sub_shifted_register,
2304 else => unreachable,
2305 };
2306 const mir_tag_immediate: Mir.Inst.Tag = switch (tag) {
2307 .add => .add_immediate,
2308 .sub => .sub_immediate,
2309 else => unreachable,
2310 };
2311
2312 if (rhs_immediate_ok) {
2313 return try self.binOpImmediateNew(mir_tag_immediate, lhs_bind, rhs_immediate.?, lhs_ty, false, maybe_inst);
2314 } else if (lhs_immediate_ok) {
2315 // swap lhs and rhs
2316 return try self.binOpImmediateNew(mir_tag_immediate, rhs_bind, lhs_immediate.?, rhs_ty, true, maybe_inst);
2317 } else {
2318 return try self.binOpRegisterNew(mir_tag_register, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
2319 }
2320 } else {
2321 return self.fail("TODO binary operations on int with bits > 64", .{});
2322 }
2323 },
2324 else => unreachable,
2325 }
2326}
2327
23072328fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
23082329 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2309 const lhs = try self.resolveInst(bin_op.lhs);
2310 const rhs = try self.resolveInst(bin_op.rhs);
23112330 const lhs_ty = self.air.typeOf(bin_op.lhs);
23122331 const rhs_ty = self.air.typeOf(bin_op.rhs);
23132332
2314 const result: MCValue = if (self.liveness.isUnused(inst))
2315 .dead
2316 else
2317 try self.binOp(tag, lhs, rhs, lhs_ty, rhs_ty, BinOpMetadata{
2318 .inst = inst,
2319 .lhs = bin_op.lhs,
2320 .rhs = bin_op.rhs,
2321 });
2333 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2334 const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
2335 const rhs_bind: ReadArg.Bind = .{ .inst = bin_op.rhs };
2336
2337 break :result switch (tag) {
2338 .add => try self.addSub(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
2339 .sub => try self.addSub(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
2340
2341 else => blk: {
2342 const lhs = try self.resolveInst(bin_op.lhs);
2343 const rhs = try self.resolveInst(bin_op.rhs);
2344
2345 break :blk try self.binOp(tag, lhs, rhs, lhs_ty, rhs_ty, BinOpMetadata{
2346 .inst = inst,
2347 .lhs = bin_op.lhs,
2348 .rhs = bin_op.rhs,
2349 });
2350 },
2351 };
2352 };
23222353 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
23232354}
23242355
......@@ -2364,8 +2395,8 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
23642395 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
23652396 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
23662397 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2367 const lhs = try self.resolveInst(extra.lhs);
2368 const rhs = try self.resolveInst(extra.rhs);
2398 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };
2399 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };
23692400 const lhs_ty = self.air.typeOf(extra.lhs);
23702401 const rhs_ty = self.air.typeOf(extra.rhs);
23712402
......@@ -2392,7 +2423,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
23922423 .sub_with_overflow => .sub,
23932424 else => unreachable,
23942425 };
2395 const dest = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, null);
2426 const dest = try self.addSub(base_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, null);
23962427 const dest_reg = dest.register;
23972428 const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);
23982429 defer self.register_manager.unlockReg(dest_reg_lock);
......@@ -2422,18 +2453,21 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
24222453 break :result MCValue{ .stack_offset = stack_offset };
24232454 },
24242455 32, 64 => {
2456 const lhs_immediate = try lhs_bind.resolveToImmediate(self);
2457 const rhs_immediate = try rhs_bind.resolveToImmediate(self);
2458
24252459 // Only say yes if the operation is
24262460 // commutative, i.e. we can swap both of the
24272461 // operands
24282462 const lhs_immediate_ok = switch (tag) {
2429 .add_with_overflow => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
2463 .add_with_overflow => if (lhs_immediate) |imm| imm <= std.math.maxInt(u12) else false,
24302464 .sub_with_overflow => false,
24312465 else => unreachable,
24322466 };
24332467 const rhs_immediate_ok = switch (tag) {
24342468 .add_with_overflow,
24352469 .sub_with_overflow,
2436 => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),
2470 => if (rhs_immediate) |imm| imm <= std.math.maxInt(u12) else false,
24372471 else => unreachable,
24382472 };
24392473
......@@ -2453,12 +2487,12 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
24532487
24542488 const dest = blk: {
24552489 if (rhs_immediate_ok) {
2456 break :blk try self.binOpImmediate(mir_tag_immediate, lhs, rhs, lhs_ty, false, null);
2490 break :blk try self.binOpImmediateNew(mir_tag_immediate, lhs_bind, rhs_immediate.?, lhs_ty, false, null);
24572491 } else if (lhs_immediate_ok) {
24582492 // swap lhs and rhs
2459 break :blk try self.binOpImmediate(mir_tag_immediate, rhs, lhs, rhs_ty, true, null);
2493 break :blk try self.binOpImmediateNew(mir_tag_immediate, rhs_bind, lhs_immediate.?, rhs_ty, true, null);
24602494 } else {
2461 break :blk try self.binOpRegister(mir_tag_register, lhs, rhs, lhs_ty, rhs_ty, null);
2495 break :blk try self.binOpRegisterNew(mir_tag_register, lhs_bind, rhs_bind, lhs_ty, rhs_ty, null);
24622496 }
24632497 };
24642498
......@@ -3650,26 +3684,10 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
36503684 break :result MCValue{ .ptr_stack_offset = off - struct_field_offset };
36513685 },
36523686 else => {
3653 const offset_reg = try self.copyToTmpRegister(ptr_ty, .{
3654 .immediate = struct_field_offset,
3655 });
3656 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
3657 defer self.register_manager.unlockReg(offset_reg_lock);
3658
3659 const addr_reg = try self.copyToTmpRegister(ptr_ty, mcv);
3660 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
3661 defer self.register_manager.unlockReg(addr_reg_lock);
3687 const lhs_bind: ReadArg.Bind = .{ .mcv = mcv };
3688 const rhs_bind: ReadArg.Bind = .{ .mcv = .{ .immediate = struct_field_offset } };
36623689
3663 const dest = try self.binOp(
3664 .add,
3665 .{ .register = addr_reg },
3666 .{ .register = offset_reg },
3667 Type.usize,
3668 Type.usize,
3669 null,
3670 );
3671
3672 break :result dest;
3690 break :result try self.addSub(.add, lhs_bind, rhs_bind, Type.usize, Type.usize, null);
36733691 },
36743692 }
36753693 };