authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-23 22:24:59-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-23 22:24:59-07:00
logbf642204b373e01314ecfb0c50a643dc4b05746f
tree67e2bdde85991275fbeee4784df0985b2c21f207
parent05f304807f4d492bea0fa54c113e77ec9bb49f6d

std.MultiArrayList: add workaround for LLVM bug


1 files changed, 91 insertions(+), 3 deletions(-)

lib/std/multi_array_list.zig+91-3
...@@ -263,9 +263,18 @@ pub fn MultiArrayList(comptime S: type) type {...@@ -263,9 +263,18 @@ pub fn MultiArrayList(comptime S: type) type {
263 }263 }
264264
265 fn capacityInBytes(capacity: usize) usize {265 fn capacityInBytes(capacity: usize) usize {
266 const sizes_vector: std.meta.Vector(sizes.bytes.len, usize) = sizes.bytes;266 // TODO move this workaround of LLVM SIMD bugs into the Zig frontend.
267 const capacity_vector = @splat(sizes.bytes.len, capacity);267 if (std.Target.current.cpu.arch == .aarch64) {
268 return @reduce(.Add, capacity_vector * sizes_vector);268 var sum: usize = 0;
269 for (sizes.bytes) |size| {
270 sum += capacity * size;
271 }
272 return sum;
273 } else {
274 const sizes_vector: std.meta.Vector(sizes.bytes.len, usize) = sizes.bytes;
275 const capacity_vector = @splat(sizes.bytes.len, capacity);
276 return @reduce(.Add, capacity_vector * sizes_vector);
277 }
269 }278 }
270279
271 fn allocatedBytes(self: Self) []align(@alignOf(S)) u8 {280 fn allocatedBytes(self: Self) []align(@alignOf(S)) u8 {
...@@ -357,3 +366,82 @@ test "basic usage" {...@@ -357,3 +366,82 @@ test "basic usage" {
357 testing.expectEqualStrings("zigzag", list.items(.b)[1]);366 testing.expectEqualStrings("zigzag", list.items(.b)[1]);
358 testing.expectEqualStrings("fizzbuzz", list.items(.b)[2]);367 testing.expectEqualStrings("fizzbuzz", list.items(.b)[2]);
359}368}
369
370// This was observed to fail on aarch64 with LLVM 11, when the capacityInBytes
371// function used the @reduce code path.
372test "regression test for @reduce bug" {
373 const ally = std.testing.allocator;
374 var list = MultiArrayList(struct {
375 tag: std.zig.Token.Tag,
376 start: u32,
377 }){};
378 defer list.deinit(ally);
379
380 try list.ensureCapacity(ally, 20);
381
382 try list.append(ally, .{ .tag = .keyword_const, .start = 0 });
383 try list.append(ally, .{ .tag = .identifier, .start = 6 });
384 try list.append(ally, .{ .tag = .equal, .start = 10 });
385 try list.append(ally, .{ .tag = .builtin, .start = 12 });
386 try list.append(ally, .{ .tag = .l_paren, .start = 19 });
387 try list.append(ally, .{ .tag = .string_literal, .start = 20 });
388 try list.append(ally, .{ .tag = .r_paren, .start = 25 });
389 try list.append(ally, .{ .tag = .semicolon, .start = 26 });
390 try list.append(ally, .{ .tag = .keyword_pub, .start = 29 });
391 try list.append(ally, .{ .tag = .keyword_fn, .start = 33 });
392 try list.append(ally, .{ .tag = .identifier, .start = 36 });
393 try list.append(ally, .{ .tag = .l_paren, .start = 40 });
394 try list.append(ally, .{ .tag = .r_paren, .start = 41 });
395 try list.append(ally, .{ .tag = .identifier, .start = 43 });
396 try list.append(ally, .{ .tag = .bang, .start = 51 });
397 try list.append(ally, .{ .tag = .identifier, .start = 52 });
398 try list.append(ally, .{ .tag = .l_brace, .start = 57 });
399 try list.append(ally, .{ .tag = .identifier, .start = 63 });
400 try list.append(ally, .{ .tag = .period, .start = 66 });
401 try list.append(ally, .{ .tag = .identifier, .start = 67 });
402 try list.append(ally, .{ .tag = .period, .start = 70 });
403 try list.append(ally, .{ .tag = .identifier, .start = 71 });
404 try list.append(ally, .{ .tag = .l_paren, .start = 75 });
405 try list.append(ally, .{ .tag = .string_literal, .start = 76 });
406 try list.append(ally, .{ .tag = .comma, .start = 113 });
407 try list.append(ally, .{ .tag = .period, .start = 115 });
408 try list.append(ally, .{ .tag = .l_brace, .start = 116 });
409 try list.append(ally, .{ .tag = .r_brace, .start = 117 });
410 try list.append(ally, .{ .tag = .r_paren, .start = 118 });
411 try list.append(ally, .{ .tag = .semicolon, .start = 119 });
412 try list.append(ally, .{ .tag = .r_brace, .start = 121 });
413 try list.append(ally, .{ .tag = .eof, .start = 123 });
414
415 const tags = list.items(.tag);
416 std.testing.expectEqual(tags[1], .identifier);
417 std.testing.expectEqual(tags[2], .equal);
418 std.testing.expectEqual(tags[3], .builtin);
419 std.testing.expectEqual(tags[4], .l_paren);
420 std.testing.expectEqual(tags[5], .string_literal);
421 std.testing.expectEqual(tags[6], .r_paren);
422 std.testing.expectEqual(tags[7], .semicolon);
423 std.testing.expectEqual(tags[8], .keyword_pub);
424 std.testing.expectEqual(tags[9], .keyword_fn);
425 std.testing.expectEqual(tags[10], .identifier);
426 std.testing.expectEqual(tags[11], .l_paren);
427 std.testing.expectEqual(tags[12], .r_paren);
428 std.testing.expectEqual(tags[13], .identifier);
429 std.testing.expectEqual(tags[14], .bang);
430 std.testing.expectEqual(tags[15], .identifier);
431 std.testing.expectEqual(tags[16], .l_brace);
432 std.testing.expectEqual(tags[17], .identifier);
433 std.testing.expectEqual(tags[18], .period);
434 std.testing.expectEqual(tags[19], .identifier);
435 std.testing.expectEqual(tags[20], .period);
436 std.testing.expectEqual(tags[21], .identifier);
437 std.testing.expectEqual(tags[22], .l_paren);
438 std.testing.expectEqual(tags[23], .string_literal);
439 std.testing.expectEqual(tags[24], .comma);
440 std.testing.expectEqual(tags[25], .period);
441 std.testing.expectEqual(tags[26], .l_brace);
442 std.testing.expectEqual(tags[27], .r_brace);
443 std.testing.expectEqual(tags[28], .r_paren);
444 std.testing.expectEqual(tags[29], .semicolon);
445 std.testing.expectEqual(tags[30], .r_brace);
446 std.testing.expectEqual(tags[31], .eof);
447}