From d486a7b81188ea1e027334c81589157efde2ad23 Mon Sep 17 00:00:00 2001 From: joachimschmidt557 Date: Fri, 4 Mar 2022 19:19:26 +0100 Subject: [PATCH] stage2 ARM: generate less no-op branches The checks detecting such no-op branches (essentially instructions that branch to the instruction immediately following the branch) were tightened to catch more of these occurrences. --- src/arch/arm/CodeGen.zig | 35 +++++++++++++++++++++++------------ test/behavior/align.zig | 1 - test/behavior/cast.zig | 3 --- test/behavior/error.zig | 1 - test/behavior/floatop.zig | 1 - test/behavior/inttoptr.zig | 1 - test/behavior/math.zig | 3 --- test/behavior/slice.zig | 1 - test/behavior/switch.zig | 2 -- 9 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index 04dc68db5a..80f0169ba5 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -445,16 +445,17 @@ fn gen(self: *Self) !void { }); // exitlude jumps - const only_one_exitlude_jump = self.exitlude_jump_relocs.items.len == 1 and - self.exitlude_jump_relocs.items[0] == self.mir_instructions.len - 1; - if (only_one_exitlude_jump) { - // There is only one relocation. Hence, - // this relocation must be at the end of - // the code. Therefore, we can just delete - // the space initially reserved for the - // jump - self.mir_instructions.orderedRemove(self.exitlude_jump_relocs.items[0]); - } else for (self.exitlude_jump_relocs.items) |jmp_reloc| { + if (self.exitlude_jump_relocs.items.len > 0 and + self.exitlude_jump_relocs.items[self.exitlude_jump_relocs.items.len - 1] == self.mir_instructions.len - 2) + { + // If the last Mir instruction (apart from the + // dbg_epilogue_begin) is the last exitlude jump + // relocation (which would just jump one instruction + // further), it can be safely removed + self.mir_instructions.orderedRemove(self.exitlude_jump_relocs.pop()); + } + + for (self.exitlude_jump_relocs.items) |jmp_reloc| { self.mir_instructions.set(jmp_reloc, .{ .tag = .b, .data = .{ .inst = @intCast(u32, self.mir_instructions.len) }, @@ -3197,7 +3198,17 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void { const body = self.air.extra[extra.end..][0..extra.data.body_len]; try self.genBody(body); - for (self.blocks.getPtr(inst).?.relocs.items) |reloc| try self.performReloc(reloc); + // relocations for `br` instructions + const relocs = &self.blocks.getPtr(inst).?.relocs; + if (relocs.items.len > 0 and relocs.items[relocs.items.len - 1] == self.mir_instructions.len - 1) { + // If the last Mir instruction is the last relocation (which + // would just jump one instruction further), it can be safely + // removed + self.mir_instructions.orderedRemove(relocs.pop()); + } + for (relocs.items) |reloc| { + try self.performReloc(reloc); + } const result = self.blocks.getPtr(inst).?.mcv; return self.finishAir(inst, result, .{ .none, .none, .none }); @@ -3952,7 +3963,7 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { const ptr_ty = self.air.typeOf(ty_op.operand); const ptr = try self.resolveInst(ty_op.operand); const array_ty = ptr_ty.childType(); - const array_len = @intCast(u32, array_ty.arrayLenIncludingSentinel()); + const array_len = @intCast(u32, array_ty.arrayLen()); const stack_offset = try self.allocMem(inst, 8, 8); try self.genSetStack(ptr_ty, stack_offset + 4, ptr); diff --git a/test/behavior/align.zig b/test/behavior/align.zig index bde74c605f..461fd852e4 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -271,7 +271,6 @@ test "runtime known array index has best alignment possible" { if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO // take full advantage of over-alignment var array align(4) = [_]u8{ 1, 2, 3, 4 }; diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 8e53b7d44d..70fe65d1b1 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -223,8 +223,6 @@ test "@intToEnum passed a comptime_int to an enum with one item" { } test "@intCast to u0 and use the result" { - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - const S = struct { fn doTheTest(zero: u1, one: u1, bigzero: i32) !void { try expect((one << @intCast(u0, bigzero)) == 1); @@ -818,7 +816,6 @@ test "peer resolution of string literals" { test "peer cast [:x]T to []T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { diff --git a/test/behavior/error.zig b/test/behavior/error.zig index 7d3dee8d6a..982926c5bf 100644 --- a/test/behavior/error.zig +++ b/test/behavior/error.zig @@ -211,7 +211,6 @@ fn testErrorSetType() !void { test "explicit error set cast" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index 1b3652fa6a..9f8636ad6e 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -24,7 +24,6 @@ test "floating point comparisons" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO try testFloatComparisons(); diff --git a/test/behavior/inttoptr.zig b/test/behavior/inttoptr.zig index 4b8f6ac161..f559f9776b 100644 --- a/test/behavior/inttoptr.zig +++ b/test/behavior/inttoptr.zig @@ -2,7 +2,6 @@ const builtin = @import("builtin"); test "casting integer address to function pointer" { if (builtin.zig_backend == .stage1) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; addressToFunction(); diff --git a/test/behavior/math.zig b/test/behavior/math.zig index 13a6f59cba..c541ab4731 100644 --- a/test/behavior/math.zig +++ b/test/behavior/math.zig @@ -313,7 +313,6 @@ test "xor" { if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO try test_xor(); comptime try test_xor(); @@ -565,7 +564,6 @@ test "bit shift a u1" { test "truncating shift right" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO try testShrTrunc(maxInt(u16)); comptime try testShrTrunc(maxInt(u16)); @@ -735,7 +733,6 @@ test "overflow arithmetic with u0 values" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO var result: u0 = undefined; try expect(!@addWithOverflow(u0, 0, 0, &result)); diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index 992a187a3e..a00297f84b 100644 --- a/test/behavior/slice.zig +++ b/test/behavior/slice.zig @@ -191,7 +191,6 @@ test "comptime pointer cast array and then slice" { test "slicing zero length array" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; const s1 = ""[0..]; diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig index 22c78e3162..fab564f71d 100644 --- a/test/behavior/switch.zig +++ b/test/behavior/switch.zig @@ -190,7 +190,6 @@ test "switch with disjoint range" { } test "switch variable for range and multiple prongs" { - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO const S = struct { @@ -358,7 +357,6 @@ fn returnsFalse() bool { } } test "switch on const enum with var" { - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO try expect(!returnsFalse());