Skip to content

Commit 0912265

Browse files
joachimschmidt557kubkon
authored andcommitted
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
1 parent 8032ecb commit 0912265

3 files changed

Lines changed: 18 additions & 14 deletions

File tree

src/arch/aarch64/CodeGen.zig

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ pub fn generate(
433433
.prev_di_pc = 0,
434434
.prev_di_line = module_fn.lbrace_line,
435435
.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,
437437
.saved_regs_stack_space = function.saved_regs_stack_space,
438438
};
439439
defer emit.deinit();
@@ -560,6 +560,7 @@ fn gen(self: *Self) !void {
560560
const total_stack_size = self.max_end_stack + self.saved_regs_stack_space;
561561
const aligned_total_stack_end = mem.alignForwardGeneric(u32, total_stack_size, self.stack_align);
562562
const stack_size = aligned_total_stack_end - self.saved_regs_stack_space;
563+
self.max_end_stack = stack_size;
563564
if (math.cast(u12, stack_size)) |size| {
564565
self.mir_instructions.set(backpatch_reloc, .{
565566
.tag = .sub_immediate,
@@ -982,11 +983,16 @@ fn allocMem(
982983
assert(abi_size > 0);
983984
assert(abi_align > 0);
984985

985-
if (abi_align > self.stack_align)
986-
self.stack_align = abi_align;
986+
// In order to efficiently load and store stack items that fit
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

988994
// 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;
990996
self.next_stack_offset = offset;
991997
self.max_end_stack = @max(self.max_end_stack, self.next_stack_offset);
992998

@@ -5396,15 +5402,15 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void {
53965402
}
53975403

53985404
fn 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.*));
54005406
switch (mcv) {
54015407
.dead => unreachable,
54025408
.unreach, .none => return, // Nothing to do.
54035409
.undef => {
54045410
if (!self.wantSafety())
54055411
return; // The already existing value will do just fine.
54065412
// TODO Upgrade this to a memset call when we have that available.
5407-
switch (ty.abiSize(self.target.*)) {
5413+
switch (abi_size) {
54085414
1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }),
54095415
2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),
54105416
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
54265432
.register => |reg| {
54275433
switch (abi_size) {
54285434
1, 2, 4, 8 => {
5435+
assert(std.mem.isAlignedGeneric(u32, stack_offset, abi_size));
5436+
54295437
const tag: Mir.Inst.Tag = switch (abi_size) {
54305438
1 => .strb_stack,
54315439
2 => .strh_stack,
@@ -5438,7 +5446,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
54385446
.tag = tag,
54395447
.data = .{ .load_store_stack = .{
54405448
.rt = rt,
5441-
.offset = @intCast(u32, stack_offset),
5449+
.offset = stack_offset,
54425450
} },
54435451
});
54445452
},
@@ -6001,9 +6009,10 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void {
60016009
}
60026010

60036011
fn 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;
60056014
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 });
60076016
}
60086017

60096018
fn airReduce(self: *Self, inst: Air.Inst.Index) !void {

test/behavior/basic.zig

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -890,7 +890,6 @@ test "labeled block with runtime branch forwards its result location type to bre
890890
}
891891

892892
test "try in labeled block doesn't cast to wrong type" {
893-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
894893
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
895894

896895
const S = struct {
@@ -1036,7 +1035,6 @@ comptime {
10361035
}
10371036

10381037
test "switch inside @as gets correct type" {
1039-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10401038
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10411039

10421040
var a: u32 = 0;

test/behavior/error.zig

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ fn unwrapSimpleValueFromErrorDo() anyerror!isize {
7676
}
7777

7878
test "error return in assignment" {
79-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
8079
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8180

8281
doErrReturnInAssignment() catch unreachable;
@@ -829,7 +828,6 @@ test "alignment of wrapping an error union payload" {
829828
}
830829

831830
test "compare error union and error set" {
832-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
833831
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
834832

835833
var a: anyerror = error.Foo;
@@ -889,7 +887,6 @@ test "field access of anyerror results in smaller error set" {
889887

890888
test "optional error union return type" {
891889
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
892-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
893890

894891
const S = struct {
895892
fn foo() ?anyerror!u32 {

0 commit comments

Comments
 (0)