// File: kernel.cpp
#include "loop_120.h"
#include <stdint.h>
#include <arm_sve.h>
#define restrict __restrict
#define SC_SVE_ATTR
#define FOR_COND(P, S, I, N) svptest_first(svptrue_b##S(), P = svwhilelt_b##S(I, N))
#define FOR_LOOP(T, I, M, N, P, S, W) for (T I = M; FOR_COND(P, S, I, N); I += svcnt##W())
#define FOR_LOOP_8(T, I, M, N, P)  FOR_LOOP(T, I, M, N, P, 8, b)
#define FOR_LOOP_16(T, I, M, N, P) FOR_LOOP(T, I, M, N, P, 16, h)
#define FOR_LOOP_32(T, I, M, N, P) FOR_LOOP(T, I, M, N, P, 32, w)
#define FOR_LOOP_64(T, I, M, N, P) FOR_LOOP(T, I, M, N, P, 64, d)
static inline uint32_t get_sve_vl(void) {
  uint64_t vl = 0; asm volatile("incb %[vl], all, mul #8" : [vl] "+r"(vl) : :);
  return (uint32_t)vl;
}
static inline uint32_t get_vl(void) { return get_sve_vl(); }

void NOINLINE do_sort(struct loop_120_data * input) {
  uint32_t n = input->n;
  int32_t *data = input->data;

  for (uint32_t i = n - 1; i > 0; i--) {
    int32_t tmp = data[i - 1];
    svint32_t u = svdup_s32(tmp);

    svbool_t p, q;
    uint32_t j, k;
    for (j = i; FOR_COND(p, 32, j, n);) {
      svint32_t v = svld1(p, data + j);
      q = svcmpge(p, v, u);
      if (!svptest_any(p, q)) {
        svst1(p, data + j - 1, v);
        j += svcntp_b32(p, p);
        continue;
      }
      q = svbrkb_z(p, q);
      svst1(q, data + j - 1, v);
      k = svcntp_b32(q, q);
      j += k;
      if (k == 0) break;
    }

    data[j - 1] = tmp;
  }
}