ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
34.1k stars 2.49k forks source link

Compiler crash bit-shifting undefined at comptime #21266

Open Validark opened 1 month ago

Validark commented 1 month ago

Zig Version

0.14.0-dev.1366+d997ddaa1

Steps to Reproduce and Observed Behavior

Running bits_to_nibbles at compile-time crashes the compiler. Godbolt link

const std = @import("std");

export fn bits_to_nibbles(i: u16) u64 {
    const bit_positions = @as(@Vector(8, u8), @splat(1)) << std.simd.iota(u3, 8);
    const bit_positions_ext = std.simd.join(bit_positions, bit_positions);
    const v = std.simd.join(@as(@Vector(2, u8), @bitCast(i)), @as(@Vector(14, u8), @splat(0)));
    return @bitCast(vshrn_n_u16(@bitCast(@select(u8, (@shuffle(u8, v, undefined, [_]i32{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 }) & bit_positions_ext) == bit_positions_ext,
        @as(@Vector(16, u8), @splat(0xff)),
        @as(@Vector(16, u8), @splat(0)),
    )), 4));
}

export fn main() void {
    const i: u16 = 0b0000100001001010;

    @setEvalBranchQuota(10000000);
    @compileLog(comptime bits_to_nibbles(i));
}

const Chunk = @Vector(16, u8);

fn vshrn_n_u16(a: @Vector(@sizeOf(Chunk) / 2, u16), comptime c: u8) @Vector(@sizeOf(Chunk) / 2, u8) {
    // Workaround for https://github.com/llvm/llvm-project/issues/88227#issuecomment-2048490807
    const b = @shuffle(u16, a, undefined, std.simd.join(std.simd.iota(i32, @sizeOf(Chunk) / 2), @as(@Vector(@sizeOf(Chunk) / 2, i32), @splat(-1))));
    return @bitCast(@as(std.meta.Int(.unsigned, @sizeOf(Chunk) * 4), @truncate(@as(std.meta.Int(.unsigned, @bitSizeOf(Chunk)), @bitCast(@shuffle(u8, @as(@Vector(@sizeOf(Chunk) * 2, u8), @bitCast(b >> @splat(c))), undefined, std.simd.iota(i32, @sizeOf(Chunk)) << @splat(1)))))));
}

Expected Behavior

no crash

mlugg commented 2 weeks ago

Reduction:

comptime {
    const a: @Vector(1, u8) = .{undefined};
    _ = a >> @splat(4);
}

Missing undefined check in Value.shrScalar. Same applies to shlScalar and probably a bunch more arithmetic functions -- we should check all of these.