Merge pull request #13768 from ziglang/cbe-reuse-locals-2

C backend: reuse locals but respect loops to pass behavior tests
This commit is contained in:
Andrew Kelley 2022-12-04 21:59:01 -05:00 committed by GitHub
commit 70ad5bc363
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 1715 additions and 857 deletions

9
build.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/sh
set -e
if [ "x$1" != x--debug ]; then
cmake -GNinja -S. -Bbuild -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_C_COMPILER:FILEPATH=clang -DCMAKE_CXX_COMPILER:FILEPATH=clang++ -DZIG_NO_LIB:BOOL=ON
cmake --build build
cmake --install build
fi
build/stage3/bin/zig build -p debug -Dno-lib -Denable-stage1 -Denable-llvm -freference-trace
#build/stage3/bin/zig build -p only-c -Dno-lib -Donly-c

View File

@ -399,6 +399,14 @@ pub fn ArrayHashMap(
return other.promoteContext(allocator, ctx);
}
/// Set the map to an empty state, making deinitialization a no-op, and
/// returning a copy of the original.
pub fn move(self: *Self) Self {
const result = self.*;
self.unmanaged = .{};
return result;
}
/// Rebuilds the key indexes. If the underlying entries has been modified directly, users
/// can call `reIndex` to update the indexes to account for these new entries.
pub fn reIndex(self: *Self) !void {
@ -1149,6 +1157,8 @@ pub fn ArrayHashMapUnmanaged(
errdefer other.entries.deinit(allocator);
if (self.index_header) |header| {
// TODO: I'm pretty sure this could be memcpy'd instead of
// doing all this work.
const new_header = try IndexHeader.alloc(allocator, header.bit_index);
other.insertAllEntriesIntoNewHeader(if (store_hash) {} else ctx, new_header);
other.index_header = new_header;
@ -1156,6 +1166,14 @@ pub fn ArrayHashMapUnmanaged(
return other;
}
/// Set the map to an empty state, making deinitialization a no-op, and
/// returning a copy of the original.
pub fn move(self: *Self) Self {
const result = self.*;
self.* = .{};
return result;
}
/// Rebuilds the key indexes. If the underlying entries has been modified directly, users
/// can call `reIndex` to update the indexes to account for these new entries.
pub fn reIndex(self: *Self, allocator: Allocator) !void {
@ -1163,6 +1181,7 @@ pub fn ArrayHashMapUnmanaged(
@compileError("Cannot infer context " ++ @typeName(Context) ++ ", call reIndexContext instead.");
return self.reIndexContext(allocator, undefined);
}
pub fn reIndexContext(self: *Self, allocator: Allocator, ctx: Context) !void {
if (self.entries.capacity <= linear_scan_max) return;
// We're going to rebuild the index header and replace the existing one (if any). The

View File

@ -673,6 +673,14 @@ pub fn HashMap(
var other = try self.unmanaged.cloneContext(new_allocator, new_ctx);
return other.promoteContext(new_allocator, new_ctx);
}
/// Set the map to an empty state, making deinitialization a no-op, and
/// returning a copy of the original.
pub fn move(self: *Self) Self {
const result = self.*;
self.unmanaged = .{};
return result;
}
};
}
@ -1488,6 +1496,14 @@ pub fn HashMapUnmanaged(
return other;
}
/// Set the map to an empty state, making deinitialization a no-op, and
/// returning a copy of the original.
pub fn move(self: *Self) Self {
const result = self.*;
self.* = .{};
return result;
}
fn grow(self: *Self, allocator: Allocator, new_capacity: Size, ctx: Context) Allocator.Error!void {
@setCold(true);
const new_cap = std.math.max(new_capacity, minimal_capacity);

View File

@ -2001,7 +2001,7 @@ fn airRetLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
try func.restoreStackPointer();
try func.addTag(.@"return");
return func.finishAir(inst, .none, &.{});
return func.finishAir(inst, .none, &.{un_op});
}
fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.Modifier) InnerError!void {
@ -3161,7 +3161,7 @@ fn airBitcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
}
break :result func.reuseOperand(ty_op.operand, operand);
} else WValue{ .none = {} };
func.finishAir(inst, result, &.{});
func.finishAir(inst, result, &.{ty_op.operand});
}
fn bitcast(func: *CodeGen, wanted_ty: Type, given_ty: Type, operand: WValue) InnerError!WValue {
@ -4115,7 +4115,7 @@ fn airMemset(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
const len = try func.resolveInst(bin_op.rhs);
try func.memset(ptr, len, value);
func.finishAir(inst, .none, &.{pl_op.operand});
func.finishAir(inst, .none, &.{ pl_op.operand, bin_op.lhs, bin_op.rhs });
}
/// Sets a region of memory at `ptr` to the value of `value`
@ -4424,6 +4424,7 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
else => unreachable,
}
};
// TODO: this is incorrect Liveness handling code
func.finishAir(inst, result, &.{});
}
@ -4747,7 +4748,7 @@ fn airMemcpy(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
const len = try func.resolveInst(bin_op.rhs);
try func.memcpy(dst, src, len);
func.finishAir(inst, .none, &.{pl_op.operand});
func.finishAir(inst, .none, &.{ pl_op.operand, bin_op.lhs, bin_op.rhs });
}
fn airPopcount(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
@ -5158,7 +5159,8 @@ fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: enum { max, min }) InnerE
fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
const pl_op = func.air.instructions.items(.data)[inst].pl_op;
const bin_op = func.air.extraData(Air.Bin, pl_op.payload).data;
if (func.liveness.isUnused(inst)) return func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });
if (func.liveness.isUnused(inst))
return func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand });
const ty = func.air.typeOfIndex(inst);
if (ty.zigTypeTag() == .Vector) {
@ -5186,7 +5188,7 @@ fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
break :result try (try func.binOp(mul_result, addend, ty, .add)).toLocal(func, ty);
};
func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand });
}
fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {

File diff suppressed because it is too large Load Diff

View File

@ -5346,7 +5346,8 @@ pub const FuncGen = struct {
const err_union_ty = self.air.typeOf(pl_op.operand);
const payload_ty = self.air.typeOfIndex(inst);
const can_elide_load = if (isByRef(payload_ty)) self.canElideLoad(body_tail) else false;
return lowerTry(self, err_union, body, err_union_ty, false, can_elide_load, payload_ty);
const is_unused = self.liveness.isUnused(inst);
return lowerTry(self, err_union, body, err_union_ty, false, can_elide_load, is_unused, payload_ty);
}
fn airTryPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
@ -5356,7 +5357,8 @@ pub const FuncGen = struct {
const body = self.air.extra[extra.end..][0..extra.data.body_len];
const err_union_ty = self.air.typeOf(extra.data.ptr).childType();
const payload_ty = self.air.typeOfIndex(inst);
return lowerTry(self, err_union_ptr, body, err_union_ty, true, true, payload_ty);
const is_unused = self.liveness.isUnused(inst);
return lowerTry(self, err_union_ptr, body, err_union_ty, true, true, is_unused, payload_ty);
}
fn lowerTry(
@ -5366,6 +5368,7 @@ pub const FuncGen = struct {
err_union_ty: Type,
operand_is_ptr: bool,
can_elide_load: bool,
is_unused: bool,
result_ty: Type,
) !?*llvm.Value {
const payload_ty = err_union_ty.errorUnionPayload();
@ -5405,6 +5408,9 @@ pub const FuncGen = struct {
fg.builder.positionBuilderAtEnd(continue_block);
}
if (is_unused) {
return null;
}
if (!payload_has_bits) {
if (!operand_is_ptr) return null;

View File

@ -133,19 +133,11 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes
.code = code.toManaged(module.gpa),
.indent_writer = undefined, // set later so we can get a pointer to object.code
},
.arena = std.heap.ArenaAllocator.init(module.gpa),
};
function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() };
defer {
function.blocks.deinit(module.gpa);
function.value_map.deinit();
function.object.code.deinit();
for (function.object.dg.typedefs.values()) |typedef| {
module.gpa.free(typedef.rendered);
}
function.object.dg.typedefs.deinit();
function.object.dg.fwd_decl.deinit();
}
defer function.deinit(module.gpa);
codegen.genFunc(&function) catch |err| switch (err) {
error.AnalysisFail => {

20
test.sh Executable file
View File

@ -0,0 +1,20 @@
#!/bin/bash
if [[ $1 == --enable-fixed-behavior ]]; then
declare -A offsets
git g -n stage2_c test/behavior | while read -r match; do
printf '\e[36mTrying to enable... %s\e[m\n' "$match"
file=`cut -d: -f1 <<<"$match"`
offset=${offsets[$file]:=0}
let line=`cut -d: -f2 <<<"$match"`-$offset
contents=`cut -d: -f3- <<<"$match"`
sed --in-place "${line}d" "$file"
if zigd test -Itest test/behavior.zig -fno-stage1 -fno-LLVM -ofmt=c; then
printf '\e[32mTest was enabled! :)\e[m\n'
let offsets[$file]+=1
else
printf '\e[31mTest kept disabled. :(\e[m\n'
sed --in-place "${line}i\\
$contents" "$file"
fi
done
fi

View File

@ -1522,6 +1522,7 @@ test "vector integer addition" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
const S = struct {
fn doTheTest() !void {

View File

@ -78,6 +78,7 @@ test "vector int operators" {
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
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
const S = struct {
fn doTheTest() !void {
@ -177,6 +178,7 @@ test "tuple to vector" {
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
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if ((builtin.zig_backend == .stage1 or builtin.zig_backend == .stage2_llvm) and
builtin.cpu.arch == .aarch64)
@ -943,6 +945,7 @@ test "multiplication-assignment operator with an array operand" {
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
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
const S = struct {
fn doTheTest() !void {