authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2023-01-03 19:20:55+08:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-01-03 19:56:09+01:00
log09122650bab893c721f4fa1a852af93358ed1af2
tree2d711729a7bf1ef2e2c95d17cab2af1789dfbfb7
parent8032ecb73040f837d7232216b16ae7edaacbc867

stage2 AArch64: bump up alignment of stack items fitting in regs

This enables us to use more efficient loading and storing for these small stack items

3 files changed, 18 insertions(+), 14 deletions(-)

src/arch/aarch64/CodeGen.zig+18-9
...@@ -433,7 +433,7 @@ pub fn generate(...@@ -433,7 +433,7 @@ pub fn generate(
433 .prev_di_pc = 0,433 .prev_di_pc = 0,
434 .prev_di_line = module_fn.lbrace_line,434 .prev_di_line = module_fn.lbrace_line,
435 .prev_di_column = module_fn.lbrace_column,435 .prev_di_column = module_fn.lbrace_column,
436 .stack_size = mem.alignForwardGeneric(u32, function.max_end_stack, function.stack_align),436 .stack_size = function.max_end_stack,
437 .saved_regs_stack_space = function.saved_regs_stack_space,437 .saved_regs_stack_space = function.saved_regs_stack_space,
438 };438 };
439 defer emit.deinit();439 defer emit.deinit();
...@@ -560,6 +560,7 @@ fn gen(self: *Self) !void {...@@ -560,6 +560,7 @@ fn gen(self: *Self) !void {
560 const total_stack_size = self.max_end_stack + self.saved_regs_stack_space;560 const total_stack_size = self.max_end_stack + self.saved_regs_stack_space;
561 const aligned_total_stack_end = mem.alignForwardGeneric(u32, total_stack_size, self.stack_align);561 const aligned_total_stack_end = mem.alignForwardGeneric(u32, total_stack_size, self.stack_align);
562 const stack_size = aligned_total_stack_end - self.saved_regs_stack_space;562 const stack_size = aligned_total_stack_end - self.saved_regs_stack_space;
563 self.max_end_stack = stack_size;
563 if (math.cast(u12, stack_size)) |size| {564 if (math.cast(u12, stack_size)) |size| {
564 self.mir_instructions.set(backpatch_reloc, .{565 self.mir_instructions.set(backpatch_reloc, .{
565 .tag = .sub_immediate,566 .tag = .sub_immediate,
...@@ -982,11 +983,16 @@ fn allocMem(...@@ -982,11 +983,16 @@ fn allocMem(
982 assert(abi_size > 0);983 assert(abi_size > 0);
983 assert(abi_align > 0);984 assert(abi_align > 0);
984985
985 if (abi_align > self.stack_align)986 // In order to efficiently load and store stack items that fit
986 self.stack_align = abi_align;987 // into registers, we bump up the alignment to the next power of
988 // two.
989 const adjusted_align = if (abi_size > 8)
990 abi_align
991 else
992 std.math.ceilPowerOfTwoAssert(u32, abi_size);
987993
988 // TODO find a free slot instead of always appending994 // TODO find a free slot instead of always appending
989 const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align) + abi_size;995 const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, adjusted_align) + abi_size;
990 self.next_stack_offset = offset;996 self.next_stack_offset = offset;
991 self.max_end_stack = @max(self.max_end_stack, self.next_stack_offset);997 self.max_end_stack = @max(self.max_end_stack, self.next_stack_offset);
992998
...@@ -5396,7 +5402,7 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void {...@@ -5396,7 +5402,7 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void {
5396}5402}
53975403
5398fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void {5404fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void {
5399 const abi_size = ty.abiSize(self.target.*);5405 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
5400 switch (mcv) {5406 switch (mcv) {
5401 .dead => unreachable,5407 .dead => unreachable,
5402 .unreach, .none => return, // Nothing to do.5408 .unreach, .none => return, // Nothing to do.
...@@ -5404,7 +5410,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -5404,7 +5410,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5404 if (!self.wantSafety())5410 if (!self.wantSafety())
5405 return; // The already existing value will do just fine.5411 return; // The already existing value will do just fine.
5406 // TODO Upgrade this to a memset call when we have that available.5412 // TODO Upgrade this to a memset call when we have that available.
5407 switch (ty.abiSize(self.target.*)) {5413 switch (abi_size) {
5408 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }),5414 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }),
5409 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),5415 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),
5410 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),5416 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),
...@@ -5426,6 +5432,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -5426,6 +5432,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5426 .register => |reg| {5432 .register => |reg| {
5427 switch (abi_size) {5433 switch (abi_size) {
5428 1, 2, 4, 8 => {5434 1, 2, 4, 8 => {
5435 assert(std.mem.isAlignedGeneric(u32, stack_offset, abi_size));
5436
5429 const tag: Mir.Inst.Tag = switch (abi_size) {5437 const tag: Mir.Inst.Tag = switch (abi_size) {
5430 1 => .strb_stack,5438 1 => .strb_stack,
5431 2 => .strh_stack,5439 2 => .strh_stack,
...@@ -5438,7 +5446,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -5438,7 +5446,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5438 .tag = tag,5446 .tag = tag,
5439 .data = .{ .load_store_stack = .{5447 .data = .{ .load_store_stack = .{
5440 .rt = rt,5448 .rt = rt,
5441 .offset = @intCast(u32, stack_offset),5449 .offset = stack_offset,
5442 } },5450 } },
5443 });5451 });
5444 },5452 },
...@@ -6001,9 +6009,10 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void {...@@ -6001,9 +6009,10 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void {
6001}6009}
60026010
6003fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {6011fn airShuffle(self: *Self, inst: Air.Inst.Index) !void {
6004 const ty_op = self.air.instructions.items(.data)[inst].ty_op;6012 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
6013 const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data;
6005 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airShuffle for {}", .{self.target.cpu.arch});6014 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airShuffle for {}", .{self.target.cpu.arch});
6006 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });6015 return self.finishAir(inst, result, .{ extra.a, extra.b, .none });
6007}6016}
60086017
6009fn airReduce(self: *Self, inst: Air.Inst.Index) !void {6018fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
test/behavior/basic.zig-2
...@@ -890,7 +890,6 @@ test "labeled block with runtime branch forwards its result location type to bre...@@ -890,7 +890,6 @@ test "labeled block with runtime branch forwards its result location type to bre
890}890}
891891
892test "try in labeled block doesn't cast to wrong type" {892test "try in labeled block doesn't cast to wrong type" {
893 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
894 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO893 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
895894
896 const S = struct {895 const S = struct {
...@@ -1036,7 +1035,6 @@ comptime {...@@ -1036,7 +1035,6 @@ comptime {
1036}1035}
10371036
1038test "switch inside @as gets correct type" {1037test "switch inside @as gets correct type" {
1039 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1040 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1038 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10411039
1042 var a: u32 = 0;1040 var a: u32 = 0;
test/behavior/error.zig-3
...@@ -76,7 +76,6 @@ fn unwrapSimpleValueFromErrorDo() anyerror!isize {...@@ -76,7 +76,6 @@ fn unwrapSimpleValueFromErrorDo() anyerror!isize {
76}76}
7777
78test "error return in assignment" {78test "error return in assignment" {
79 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
80 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO79 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8180
82 doErrReturnInAssignment() catch unreachable;81 doErrReturnInAssignment() catch unreachable;
...@@ -829,7 +828,6 @@ test "alignment of wrapping an error union payload" {...@@ -829,7 +828,6 @@ test "alignment of wrapping an error union payload" {
829}828}
830829
831test "compare error union and error set" {830test "compare error union and error set" {
832 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
833 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO831 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
834832
835 var a: anyerror = error.Foo;833 var a: anyerror = error.Foo;
...@@ -889,7 +887,6 @@ test "field access of anyerror results in smaller error set" {...@@ -889,7 +887,6 @@ test "field access of anyerror results in smaller error set" {
889887
890test "optional error union return type" {888test "optional error union return type" {
891 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO889 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
892 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
893890
894 const S = struct {891 const S = struct {
895 fn foo() ?anyerror!u32 {892 fn foo() ?anyerror!u32 {