// #target: macos-x64

import libc;

fn void testf()
{
    float[<4>] y = { 0, 2, 3, 0 };
    int[<4>] w = !y;
    libc::printf("Notf %d %d %d %d\n", w[0], w[1], w[2], w[3]);
}

fn void testi()
{
    int[<4>] y = { 1, 2, 3, 4 };
    int[<4>] z = { 2, 3, 13, -100 };
    int[<4>] w;
    w = y & z;
    libc::printf("And %d %d %d %d\n", w[0], w[1], w[2], w[3]);
    w = y | z;
    libc::printf("Or %d %d %d %d\n", w[0], w[1], w[2], w[3]);
    w = y ^ z;
    libc::printf("Xor %d %d %d %d\n", w[0], w[1], w[2], w[3]);
    w = ~y;
    libc::printf("BitNeg %d %d %d %d\n", w[0], w[1], w[2], w[3]);
    w = -y;
    libc::printf("Neg %d %d %d %d\n", w[0], w[1], w[2], w[3]);
    w = !y;
    w = { -1, 13, 0, 0 };
    w = !w;
    libc::printf("Not %d %d %d %d\n", w[0], w[1], w[2], w[3]);
}

fn void main()
{
    testf();
    testi();
}

/* #expect: vector_bit.ll

define void @vector_bit.testf() #0 {
entry:
  %y = alloca <4 x float>, align 16
  %w = alloca <4 x i32>, align 16
  store <4 x float> <float 0.000000e+00, float 2.000000e+00, float 3.000000e+00, float 0.000000e+00>, ptr %y, align 16
  %0 = load <4 x float>, ptr %y, align 16
  %not = fcmp ueq <4 x float> %0, zeroinitializer
  %1 = sext <4 x i1> %not to <4 x i32>
  store <4 x i32> %1, ptr %w, align 16
  %2 = load <4 x i32>, ptr %w, align 16
  %3 = extractelement <4 x i32> %2, i64 0
  %4 = load <4 x i32>, ptr %w, align 16
  %5 = extractelement <4 x i32> %4, i64 1
  %6 = load <4 x i32>, ptr %w, align 16
  %7 = extractelement <4 x i32> %6, i64 2
  %8 = load <4 x i32>, ptr %w, align 16
  %9 = extractelement <4 x i32> %8, i64 3
  %10 = call i32 (ptr, ...) @printf(ptr @.str, i32 %3, i32 %5, i32 %7, i32 %9)
  ret void
}


define void @vector_bit.testi() #0 {
entry:
  %y = alloca <4 x i32>, align 16
  %z = alloca <4 x i32>, align 16
  %w = alloca <4 x i32>, align 16
  store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %y, align 16
  store <4 x i32> <i32 2, i32 3, i32 13, i32 -100>, ptr %z, align 16
  store <4 x i32> zeroinitializer, ptr %w, align 16
  %0 = load <4 x i32>, ptr %y, align 16
  %1 = load <4 x i32>, ptr %z, align 16
  %and = and <4 x i32> %0, %1
  store <4 x i32> %and, ptr %w, align 16
  %2 = load <4 x i32>, ptr %w, align 16
  %3 = extractelement <4 x i32> %2, i64 0
  %4 = load <4 x i32>, ptr %w, align 16
  %5 = extractelement <4 x i32> %4, i64 1
  %6 = load <4 x i32>, ptr %w, align 16
  %7 = extractelement <4 x i32> %6, i64 2
  %8 = load <4 x i32>, ptr %w, align 16
  %9 = extractelement <4 x i32> %8, i64 3
  %10 = call i32 (ptr, ...) @printf(ptr @.str.1, i32 %3, i32 %5, i32 %7, i32 %9)
  %11 = load <4 x i32>, ptr %y, align 16
  %12 = load <4 x i32>, ptr %z, align 16
  %or = or <4 x i32> %11, %12
  store <4 x i32> %or, ptr %w, align 16
  %13 = load <4 x i32>, ptr %w, align 16
  %14 = extractelement <4 x i32> %13, i64 0
  %15 = load <4 x i32>, ptr %w, align 16
  %16 = extractelement <4 x i32> %15, i64 1
  %17 = load <4 x i32>, ptr %w, align 16
  %18 = extractelement <4 x i32> %17, i64 2
  %19 = load <4 x i32>, ptr %w, align 16
  %20 = extractelement <4 x i32> %19, i64 3
  %21 = call i32 (ptr, ...) @printf(ptr @.str.2, i32 %14, i32 %16, i32 %18, i32 %20)
  %22 = load <4 x i32>, ptr %y, align 16
  %23 = load <4 x i32>, ptr %z, align 16
  %xor = xor <4 x i32> %22, %23
  store <4 x i32> %xor, ptr %w, align 16
  %24 = load <4 x i32>, ptr %w, align 16
  %25 = extractelement <4 x i32> %24, i64 0
  %26 = load <4 x i32>, ptr %w, align 16
  %27 = extractelement <4 x i32> %26, i64 1
  %28 = load <4 x i32>, ptr %w, align 16
  %29 = extractelement <4 x i32> %28, i64 2
  %30 = load <4 x i32>, ptr %w, align 16
  %31 = extractelement <4 x i32> %30, i64 3
  %32 = call i32 (ptr, ...) @printf(ptr @.str.3, i32 %25, i32 %27, i32 %29, i32 %31)
  %33 = load <4 x i32>, ptr %y, align 16
  %bnot = xor <4 x i32> %33,
  store <4 x i32> %bnot, ptr %w, align 16
  %34 = load <4 x i32>, ptr %w, align 16
  %35 = extractelement <4 x i32> %34, i64 0
  %36 = load <4 x i32>, ptr %w, align 16
  %37 = extractelement <4 x i32> %36, i64 1
  %38 = load <4 x i32>, ptr %w, align 16
  %39 = extractelement <4 x i32> %38, i64 2
  %40 = load <4 x i32>, ptr %w, align 16
  %41 = extractelement <4 x i32> %40, i64 3
  %42 = call i32 (ptr, ...) @printf(ptr @.str.4, i32 %35, i32 %37, i32 %39, i32 %41)
  %43 = load <4 x i32>, ptr %y, align 16
  %neg = sub <4 x i32> zeroinitializer, %43
  store <4 x i32> %neg, ptr %w, align 16
  %44 = load <4 x i32>, ptr %w, align 16
  %45 = extractelement <4 x i32> %44, i64 0
  %46 = load <4 x i32>, ptr %w, align 16
  %47 = extractelement <4 x i32> %46, i64 1
  %48 = load <4 x i32>, ptr %w, align 16
  %49 = extractelement <4 x i32> %48, i64 2
  %50 = load <4 x i32>, ptr %w, align 16
  %51 = extractelement <4 x i32> %50, i64 3
  %52 = call i32 (ptr, ...) @printf(ptr @.str.5, i32 %45, i32 %47, i32 %49, i32 %51)
  %53 = load <4 x i32>, ptr %y, align 16
  %not = icmp eq <4 x i32> %53, zeroinitializer
  %54 = sext <4 x i1> %not to <4 x i32>
  store <4 x i32> %54, ptr %w, align 16
  store <4 x i32> <i32 -1, i32 13, i32 0, i32 0>, ptr %w, align 16
  %55 = load <4 x i32>, ptr %w, align 16
  %not1 = icmp eq <4 x i32> %55, zeroinitializer
  %56 = sext <4 x i1> %not1 to <4 x i32>
  store <4 x i32> %56, ptr %w, align 16
  %57 = load <4 x i32>, ptr %w, align 16
  %58 = extractelement <4 x i32> %57, i64 0
  %59 = load <4 x i32>, ptr %w, align 16
  %60 = extractelement <4 x i32> %59, i64 1
  %61 = load <4 x i32>, ptr %w, align 16
  %62 = extractelement <4 x i32> %61, i64 2
  %63 = load <4 x i32>, ptr %w, align 16
  %64 = extractelement <4 x i32> %63, i64 3
  %65 = call i32 (ptr, ...) @printf(ptr @.str.6, i32 %58, i32 %60, i32 %62, i32 %64)
  ret void
}
