authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-12-02 19:54:00-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-12-02 22:21:24-05:00
logfdedd62365b5e3f3fa908ae063df86d11a3c02bb
tree46f6b65879ff774baec072d6ad745106f7ff3032
parentaf4361f57af388238a075b0c8ef5b34e75b73787

cbe: use memcpy for underaligned loads and stores


8 files changed, 22 insertions(+), 29 deletions(-)

src/codegen/c.zig+22-15
......@@ -2999,30 +2999,31 @@ fn airArg(f: *Function) CValue {
29992999fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
30003000 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
30013001 const ptr_info = f.air.typeOf(ty_op.operand).ptrInfo().data;
3002 const src_ty = ptr_info.pointee_type;
30023003
3003 const inst_ty = f.air.typeOfIndex(inst);
3004 if (!inst_ty.hasRuntimeBitsIgnoreComptime() or
3004 if (!src_ty.hasRuntimeBitsIgnoreComptime() or
30053005 !ptr_info.@"volatile" and f.liveness.isUnused(inst))
30063006 return CValue.none;
30073007
30083008 const target = f.object.dg.module.getTarget();
3009 const is_array = lowersToArray(inst_ty, target);
3009 const is_aligned = ptr_info.@"align" == 0 or ptr_info.@"align" >= src_ty.abiAlignment(target);
3010 const is_array = lowersToArray(src_ty, target);
3011 const need_memcpy = !is_aligned or is_array;
30103012 const operand = try f.resolveInst(ty_op.operand);
30113013 const writer = f.object.writer();
30123014
3013 // We need to separately initialize arrays with a memcpy so they must be mutable.
3014 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
3015 // We need to initialize arrays and unaligned loads with a memcpy so they must be mutable.
3016 const local = try f.allocLocal(src_ty, if (need_memcpy) .Mut else .Const);
30153017
3016 if (is_array) {
3017 // Insert a memcpy to initialize this array. The source operand is always a pointer
3018 // and thus we only need to know size/type information from the local type/dest.
3018 if (need_memcpy) {
30193019 try writer.writeAll(";\n");
30203020 try writer.writeAll("memcpy(");
3021 if (!is_array) try writer.writeByte('&');
30213022 try f.writeCValue(writer, local, .FunctionArgument);
3022 try writer.writeAll(", ");
3023 try f.writeCValue(writer, operand, .FunctionArgument);
3023 try writer.writeAll(", (const char *)");
3024 try f.writeCValue(writer, operand, .Other);
30243025 try writer.writeAll(", sizeof(");
3025 try f.renderTypecast(writer, inst_ty);
3026 try f.renderTypecast(writer, src_ty);
30263027 try writer.writeAll("))");
30273028 } else if (ptr_info.host_size != 0) {
30283029 var host_pl = Type.Payload.Bits{
......@@ -3045,12 +3046,12 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
30453046
30463047 var field_pl = Type.Payload.Bits{
30473048 .base = .{ .tag = .int_unsigned },
3048 .data = @intCast(u16, inst_ty.bitSize(target)),
3049 .data = @intCast(u16, src_ty.bitSize(target)),
30493050 };
30503051 const field_ty = Type.initPayload(&field_pl.base);
30513052
30523053 try writer.writeAll(" = (");
3053 try f.renderTypecast(writer, inst_ty);
3054 try f.renderTypecast(writer, src_ty);
30543055 try writer.writeAll(")zig_wrap_");
30553056 try f.object.dg.renderTypeForBuiltinFnName(writer, field_ty);
30563057 try writer.writeAll("((");
......@@ -3226,8 +3227,13 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
32263227 return try airStoreUndefined(f, ptr_info.pointee_type, ptr_val);
32273228
32283229 const target = f.object.dg.module.getTarget();
3230 const is_aligned = ptr_info.@"align" == 0 or
3231 ptr_info.@"align" >= ptr_info.pointee_type.abiAlignment(target);
3232 const is_array = lowersToArray(ptr_info.pointee_type, target);
3233 const need_memcpy = !is_aligned or is_array;
32293234 const writer = f.object.writer();
3230 if (lowersToArray(ptr_info.pointee_type, target)) {
3235
3236 if (need_memcpy) {
32313237 // For this memcpy to safely work we need the rhs to have the same
32323238 // underlying type as the lhs (i.e. they must both be arrays of the same underlying type).
32333239 assert(src_ty.eql(ptr_info.pointee_type, f.object.dg.module));
......@@ -3244,9 +3250,10 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
32443250 break :blk new_local;
32453251 } else src_val;
32463252
3247 try writer.writeAll("memcpy(");
3253 try writer.writeAll("memcpy((char *)");
32483254 try f.writeCValue(writer, ptr_val, .FunctionArgument);
32493255 try writer.writeAll(", ");
3256 if (!is_array) try writer.writeByte('&');
32503257 try f.writeCValue(writer, array_src, .FunctionArgument);
32513258 try writer.writeAll(", sizeof(");
32523259 try f.renderTypecast(writer, src_ty);
test/behavior/basic.zig-2
......@@ -754,7 +754,6 @@ fn maybe(x: bool) anyerror!?u32 {
754754}
755755
756756test "pointer to thread local array" {
757 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
758757 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
759758 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
760759 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -770,7 +769,6 @@ threadlocal var buffer: [11]u8 = undefined;
770769
771770test "auto created variables have correct alignment" {
772771 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
773 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
774772
775773 const S = struct {
776774 fn foo(str: [*]const u8) u32 {
test/behavior/bitreverse.zig-1
......@@ -155,7 +155,6 @@ fn vector0() !void {
155155test "bitReverse vectors u0" {
156156 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
157157 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
158 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
159158 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
160159
161160 comptime try vector0();
test/behavior/byteswap.zig-1
......@@ -121,7 +121,6 @@ fn vector0() !void {
121121test "@byteSwap vectors u0" {
122122 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
123123 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
124 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
125124 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
126125
127126 comptime try vector0();
test/behavior/math.zig-1
......@@ -1518,7 +1518,6 @@ fn testRound(comptime T: type, x: T) !void {
15181518}
15191519
15201520test "vector integer addition" {
1521 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
15221521 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
15231522 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15241523 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/ptrcast.zig-1
......@@ -78,7 +78,6 @@ fn testReinterpretBytesAsExternStruct() !void {
7878
7979test "reinterpret bytes of an extern struct (with under-aligned fields) into another" {
8080 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
81 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO: Under-aligned fields are not yet supported in the CBE
8281
8382 try testReinterpretExternStructAsExternStruct();
8483 comptime try testReinterpretExternStructAsExternStruct();
test/behavior/struct.zig-1
......@@ -641,7 +641,6 @@ test "default struct initialization fields" {
641641
642642test "packed array 24bits" {
643643 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
644 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
645644 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
646645 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
647646 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
test/behavior/vector.zig-7
......@@ -75,7 +75,6 @@ test "vector bin compares with mem.eql" {
7575
7676test "vector int operators" {
7777 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
78 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
7978 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
8079 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
8180 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -139,7 +138,6 @@ test "vector bit operators" {
139138
140139test "implicit cast vector to array" {
141140 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
142 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
143141 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
144142 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
145143 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -158,7 +156,6 @@ test "implicit cast vector to array" {
158156
159157test "array to vector" {
160158 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
161 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
162159 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
163160 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
164161 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -177,7 +174,6 @@ test "array to vector" {
177174
178175test "tuple to vector" {
179176 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
180 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
181177 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
182178 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
183179 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -210,7 +206,6 @@ test "tuple to vector" {
210206
211207test "vector casts of sizes not divisible by 8" {
212208 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
213 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
214209 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
215210 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
216211 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -945,7 +940,6 @@ test "multiplication-assignment operator with an array operand" {
945940 return error.SkipZigTest;
946941 }
947942 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
948 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
949943 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
950944 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
951945 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -1194,7 +1188,6 @@ test "zero divisor" {
11941188
11951189test "zero multiplicand" {
11961190 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1197 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11981191 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11991192 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12001193 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO