authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-11 20:15:13-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-03-11 20:15:13-05:00
log6f986298c6cc58d2d86e9790b11bad5ce36085ad
tree0db86846775295f41d1159b9b19a2649cef82565
parentfca51c81bc5fd83a3d4a87092696df80790003e9
parent226fcd7c709ec664c5d883042cf7beb3026f66cb
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11125 from jmc-88/cbe

CBE: promote an already passing test, and add implementation for clz, ctz for integers

4 files changed, 55 insertions(+), 5 deletions(-)

src/codegen/c.zig+22-2
...@@ -1708,8 +1708,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -1708,8 +1708,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
1708 .memcpy => try airMemcpy(f, inst),1708 .memcpy => try airMemcpy(f, inst),
1709 .set_union_tag => try airSetUnionTag(f, inst),1709 .set_union_tag => try airSetUnionTag(f, inst),
1710 .get_union_tag => try airGetUnionTag(f, inst),1710 .get_union_tag => try airGetUnionTag(f, inst),
1711 .clz => try airBuiltinCall(f, inst, "clz"),1711 .clz => try airCountZeroes(f, inst, "clz"),
1712 .ctz => try airBuiltinCall(f, inst, "ctz"),1712 .ctz => try airCountZeroes(f, inst, "ctz"),
1713 .popcount => try airBuiltinCall(f, inst, "popcount"),1713 .popcount => try airBuiltinCall(f, inst, "popcount"),
1714 .byte_swap => try airBuiltinCall(f, inst, "byte_swap"),1714 .byte_swap => try airBuiltinCall(f, inst, "byte_swap"),
1715 .bit_reverse => try airBuiltinCall(f, inst, "bit_reverse"),1715 .bit_reverse => try airBuiltinCall(f, inst, "bit_reverse"),
...@@ -3349,6 +3349,26 @@ fn airBuiltinCall(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u8) !C...@@ -3349,6 +3349,26 @@ fn airBuiltinCall(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u8) !C
3349 return local;3349 return local;
3350}3350}
33513351
3352fn airCountZeroes(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u8) !CValue {
3353 if (f.liveness.isUnused(inst)) return CValue.none;
3354
3355 const inst_ty = f.air.typeOfIndex(inst);
3356 const local = try f.allocLocal(inst_ty, .Const);
3357 const operand = f.air.instructions.items(.data)[inst].ty_op.operand;
3358 const operand_ty = f.air.typeOf(operand);
3359 const target = f.object.dg.module.getTarget();
3360 const writer = f.object.writer();
3361
3362 const zig_bits = operand_ty.intInfo(target).bits;
3363 _ = toCIntBits(zig_bits) orelse
3364 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
3365
3366 try writer.print(" = zig_{s}(", .{fn_name});
3367 try f.writeCValue(writer, try f.resolveInst(operand));
3368 try writer.print(", {d});\n", .{zig_bits});
3369 return local;
3370}
3371
3352fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue {3372fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue {
3353 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;3373 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
3354 const extra = f.air.extraData(Air.Cmpxchg, ty_pl.payload).data;3374 const extra = f.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
src/link/C/zig.h+18
...@@ -500,3 +500,21 @@ zig_shl_sat_s(isize, intptr_t, ((sizeof(intptr_t)) * CHAR_BIT - 1))...@@ -500,3 +500,21 @@ zig_shl_sat_s(isize, intptr_t, ((sizeof(intptr_t)) * CHAR_BIT - 1))
500zig_shl_sat_s(short, short, ((sizeof(short )) * CHAR_BIT - 1))500zig_shl_sat_s(short, short, ((sizeof(short )) * CHAR_BIT - 1))
501zig_shl_sat_s(int, int, ((sizeof(int )) * CHAR_BIT - 1))501zig_shl_sat_s(int, int, ((sizeof(int )) * CHAR_BIT - 1))
502zig_shl_sat_s(long, long, ((sizeof(long )) * CHAR_BIT - 1))502zig_shl_sat_s(long, long, ((sizeof(long )) * CHAR_BIT - 1))
503
504#define zig_bitsizeof(T) (CHAR_BIT * sizeof(T))
505
506static inline int zig_clz(uint64_t value, uint8_t zig_type_bit_width) {
507 if (value == 0) return zig_type_bit_width;
508 if (zig_type_bit_width <= zig_bitsizeof(unsigned int))
509 return (__builtin_clz(value) - zig_bitsizeof(unsigned int) + zig_type_bit_width);
510 if (zig_type_bit_width <= zig_bitsizeof(unsigned long))
511 return (__builtin_clzl(value) - zig_bitsizeof(unsigned long) + zig_type_bit_width);
512 return (__builtin_clzll(value) - zig_bitsizeof(unsigned long long) + zig_type_bit_width);
513}
514
515static inline int zig_ctz(uint64_t value, uint8_t zig_type_bit_width) {
516 if (value == 0) return zig_type_bit_width;
517 if (zig_type_bit_width <= zig_bitsizeof(unsigned int)) return __builtin_ctz(value);
518 if (zig_type_bit_width <= zig_bitsizeof(unsigned long)) return __builtin_ctzl(value);
519 return __builtin_ctzll(value);
520}
test/behavior.zig+1-1
...@@ -139,6 +139,7 @@ test {...@@ -139,6 +139,7 @@ test {
139 _ = @import("behavior/export_self_referential_type_info.zig");139 _ = @import("behavior/export_self_referential_type_info.zig");
140 _ = @import("behavior/int128.zig");140 _ = @import("behavior/int128.zig");
141 _ = @import("behavior/translate_c_macros.zig");141 _ = @import("behavior/translate_c_macros.zig");
142 _ = @import("behavior/union_with_members.zig");
142143
143 if (builtin.zig_backend != .stage2_c) {144 if (builtin.zig_backend != .stage2_c) {
144 // Tests that pass for stage1 and the llvm backend.145 // Tests that pass for stage1 and the llvm backend.
...@@ -152,7 +153,6 @@ test {...@@ -152,7 +153,6 @@ test {
152 _ = @import("behavior/bugs/3779.zig");153 _ = @import("behavior/bugs/3779.zig");
153 _ = @import("behavior/bugs/10147.zig");154 _ = @import("behavior/bugs/10147.zig");
154 _ = @import("behavior/shuffle.zig");155 _ = @import("behavior/shuffle.zig");
155 _ = @import("behavior/union_with_members.zig");
156156
157 if (builtin.zig_backend == .stage1) {157 if (builtin.zig_backend == .stage1) {
158 // Tests that only pass for the stage1 backend.158 // Tests that only pass for the stage1 backend.
test/behavior/math.zig+14-2
...@@ -65,7 +65,6 @@ test "@clz" {...@@ -65,7 +65,6 @@ test "@clz" {
65 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO65 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
66 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO66 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
67 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO67 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
68 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
6968
70 try testClz();69 try testClz();
71 comptime try testClz();70 comptime try testClz();
...@@ -76,6 +75,20 @@ fn testClz() !void {...@@ -76,6 +75,20 @@ fn testClz() !void {
76 try expect(testOneClz(u8, 0b00001010) == 4);75 try expect(testOneClz(u8, 0b00001010) == 4);
77 try expect(testOneClz(u8, 0b00011010) == 3);76 try expect(testOneClz(u8, 0b00011010) == 3);
78 try expect(testOneClz(u8, 0b00000000) == 8);77 try expect(testOneClz(u8, 0b00000000) == 8);
78}
79
80test "@clz big ints" {
81 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
82 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
83 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
84 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
85 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
86
87 try testClzBigInts();
88 comptime try testClzBigInts();
89}
90
91fn testClzBigInts() !void {
79 try expect(testOneClz(u128, 0xffffffffffffffff) == 64);92 try expect(testOneClz(u128, 0xffffffffffffffff) == 64);
80 try expect(testOneClz(u128, 0x10000000000000000) == 63);93 try expect(testOneClz(u128, 0x10000000000000000) == 63);
81}94}
...@@ -130,7 +143,6 @@ test "@ctz" {...@@ -130,7 +143,6 @@ test "@ctz" {
130 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO143 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
131 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO144 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
132 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO145 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
133 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
134146
135 try testCtz();147 try testCtz();
136 comptime try testCtz();148 comptime try testCtz();