// File: /workspace/github_c_makefile_star2_O0/janet-lang[P]janet/src/core/bytecode.c
// Function: janet_bytecode_movopt
void janet_bytecode_movopt(JanetFuncDef *def) {
    JanetcRegisterAllocator ra;
    int recur = 1;

    /* Iterate this until no more instructions can be removed. */
    while (recur) {
        janetc_regalloc_init(&ra);

        /* Look for slots that have writes but no reads (and aren't in the closure bitset). */
        if (def->closure_bitset != NULL) {
            for (int32_t i = 0; i < def->slotcount; i++) {
                int32_t index = i >> 5;
                uint32_t mask = 1U << (((uint32_t) i) & 31);
                if (def->closure_bitset[index] & mask) {
                    janetc_regalloc_touch(&ra, i);
                }
            }
        }

#define AA ((instr >> 8)  & 0xFF)
#define BB ((instr >> 16) & 0xFF)
#define CC (instr >> 24)
#define DD (instr >> 8)
#define EE (instr >> 16)

        /* Check reads and writes */
        for (int32_t i = 0; i < def->bytecode_length; i++) {
            uint32_t instr = def->bytecode[i];
            switch (instr & 0x7F) {

                /* Group instructions my how they read from slots */

                /* No reads or writes */
                default:
                    janet_assert(0, "unhandled instruction");
                case JOP_JUMP:
                case JOP_NOOP:
                case JOP_RETURN_NIL:
                /* Write A */
                case JOP_LOAD_INTEGER:
                case JOP_LOAD_CONSTANT:
                case JOP_LOAD_UPVALUE:
                case JOP_CLOSURE:
                /* Write D */
                case JOP_LOAD_NIL:
                case JOP_LOAD_TRUE:
                case JOP_LOAD_FALSE:
                case JOP_LOAD_SELF:
                    break;
                case JOP_MAKE_ARRAY:
                case JOP_MAKE_BUFFER:
                case JOP_MAKE_STRING:
                case JOP_MAKE_STRUCT:
                case JOP_MAKE_TABLE:
                case JOP_MAKE_TUPLE:
                case JOP_MAKE_BRACKET_TUPLE:
                    /* Reads from the stack, don't remove */
                    janetc_regalloc_touch(&ra, DD);
                    break;

                /* Read A */
                case JOP_ERROR:
                case JOP_TYPECHECK:
                case JOP_JUMP_IF:
                case JOP_JUMP_IF_NOT:
                case JOP_JUMP_IF_NIL:
                case JOP_JUMP_IF_NOT_NIL:
                case JOP_SET_UPVALUE:
                /* Write E, Read A */
                case JOP_MOVE_FAR:
                    janetc_regalloc_touch(&ra, AA);
                    break;

                /* Read B */
                case JOP_SIGNAL:
                /* Write A, Read B */
                case JOP_ADD_IMMEDIATE:
                case JOP_SUBTRACT_IMMEDIATE:
                case JOP_MULTIPLY_IMMEDIATE:
                case JOP_DIVIDE_IMMEDIATE:
                case JOP_SHIFT_LEFT_IMMEDIATE:
                case JOP_SHIFT_RIGHT_IMMEDIATE:
                case JOP_SHIFT_RIGHT_UNSIGNED_IMMEDIATE:
                case JOP_GREATER_THAN_IMMEDIATE:
                case JOP_LESS_THAN_IMMEDIATE:
                case JOP_EQUALS_IMMEDIATE:
                case JOP_NOT_EQUALS_IMMEDIATE:
                case JOP_GET_INDEX:
                    janetc_regalloc_touch(&ra, BB);
                    break;

                /* Read D */
                case JOP_RETURN:
                case JOP_PUSH:
                case JOP_PUSH_ARRAY:
                case JOP_TAILCALL:
                    janetc_regalloc_touch(&ra, DD);
                    break;

                /* Write A, Read E */
                case JOP_MOVE_NEAR:
                case JOP_LENGTH:
                case JOP_BNOT:
                case JOP_CALL:
                    janetc_regalloc_touch(&ra, EE);
                    break;

                /* Read A, B */
                case JOP_PUT_INDEX:
                    janetc_regalloc_touch(&ra, AA);
                    janetc_regalloc_touch(&ra, BB);
                    break;

                /* Read A, E */
                case JOP_PUSH_2:
                    janetc_regalloc_touch(&ra, AA);
                    janetc_regalloc_touch(&ra, EE);
                    break;

                /* Read B, C */
                case JOP_PROPAGATE:
                /* Write A, Read B and C */
                case JOP_BAND:
                case JOP_BOR:
                case JOP_BXOR:
                case JOP_ADD:
                case JOP_SUBTRACT:
                case JOP_MULTIPLY:
                case JOP_DIVIDE:
                case JOP_DIVIDE_FLOOR:
                case JOP_MODULO:
                case JOP_REMAINDER:
                case JOP_SHIFT_LEFT:
                case JOP_SHIFT_RIGHT:
                case JOP_SHIFT_RIGHT_UNSIGNED:
                case JOP_GREATER_THAN:
                case JOP_LESS_THAN:
                case JOP_EQUALS:
                case JOP_COMPARE:
                case JOP_IN:
                case JOP_GET:
                case JOP_GREATER_THAN_EQUAL:
                case JOP_LESS_THAN_EQUAL:
                case JOP_NOT_EQUALS:
                case JOP_CANCEL:
                case JOP_RESUME:
                case JOP_NEXT:
                    janetc_regalloc_touch(&ra, BB);
                    janetc_regalloc_touch(&ra, CC);
                    break;

                /* Read A, B, C */
                case JOP_PUT:
                case JOP_PUSH_3:
                    janetc_regalloc_touch(&ra, AA);
                    janetc_regalloc_touch(&ra, BB);
                    janetc_regalloc_touch(&ra, CC);
                    break;
            }
        }

        /* Iterate and set noops on instructions that make writes that no one ever reads.
         * Only set noops for instructions with no side effects - moves, loads, etc. that can't
         * raise errors (outside of systemic errors like oom or stack overflow). */
        recur = 0;
        for (int32_t i = 0; i < def->bytecode_length; i++) {
            uint32_t instr = def->bytecode[i];
            switch (instr & 0x7F) {
                default:
                    break;
                /* Write D */
                case JOP_LOAD_NIL:
                case JOP_LOAD_TRUE:
                case JOP_LOAD_FALSE:
                case JOP_LOAD_SELF:
                case JOP_MAKE_ARRAY:
                case JOP_MAKE_TUPLE:
                case JOP_MAKE_BRACKET_TUPLE: {
                    if (!janetc_regalloc_check(&ra, DD)) {
                        def->bytecode[i] = JOP_NOOP;
                        recur = 1;
                    }
                }
                break;
                /* Write E, Read A */
                case JOP_MOVE_FAR: {
                    if (!janetc_regalloc_check(&ra, EE)) {
                        def->bytecode[i] = JOP_NOOP;
                        recur = 1;
                    }
                }
                break;
                /* Write A, Read E */
                case JOP_MOVE_NEAR:
                /* Write A, Read B */
                case JOP_GET_INDEX:
                /* Write A */
                case JOP_LOAD_INTEGER:
                case JOP_LOAD_CONSTANT:
                case JOP_LOAD_UPVALUE:
                case JOP_CLOSURE: {
                    if (!janetc_regalloc_check(&ra, AA)) {
                        def->bytecode[i] = JOP_NOOP;
                        recur = 1;
                    }
                }
                break;
            }
        }

        janetc_regalloc_deinit(&ra);
#undef AA
#undef BB
#undef CC
#undef DD
#undef EE
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movl $0x1, -0x24(%rbp)
cmpl $0x0, -0x24(%rbp)
je 0x1a58c
leaq -0x20(%rbp), %rdi
callq 0x5dd80
movq -0x8(%rbp), %rax
cmpq $0x0, 0x30(%rax)
je 0x1a26f
movl $0x0, -0x28(%rbp)
movl -0x28(%rbp), %eax
movq -0x8(%rbp), %rcx
cmpl 0x5c(%rcx), %eax
jge 0x1a26d
movl -0x28(%rbp), %eax
sarl $0x5, %eax
movl %eax, -0x2c(%rbp)
movl -0x28(%rbp), %ecx
andl $0x1f, %ecx
movl $0x1, %eax
shll %cl, %eax
movl %eax, -0x30(%rbp)
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movslq -0x2c(%rbp), %rcx
movl (%rax,%rcx,4), %eax
andl -0x30(%rbp), %eax
cmpl $0x0, %eax
je 0x1a260
movl -0x28(%rbp), %esi
leaq -0x20(%rbp), %rdi
callq 0x5ded0
jmp 0x1a262
movl -0x28(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x28(%rbp)
jmp 0x1a218
jmp 0x1a26f
movl $0x0, -0x34(%rbp)
movl -0x34(%rbp), %eax
movq -0x8(%rbp), %rcx
cmpl 0x70(%rcx), %eax
jge 0x1a42a
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x34(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x38(%rbp)
movl -0x38(%rbp), %eax
andl $0x7f, %eax
movl %eax, %ecx
movq %rcx, -0x48(%rbp)
subl $0x4c, %eax
ja 0x1a2bd
movq -0x48(%rbp), %rax
leaq 0x66bf4(%rip), %rcx     # 0x80ea8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
jmp 0x1a2bf
jmp 0x1a2c1
movq 0x95d28(%rip), %rax     # 0xafff0
movq (%rax), %rdi
leaq 0x66d42(%rip), %rsi     # 0x81014
movl $0xd7, %edx
leaq 0x66d66(%rip), %rcx     # 0x81044
leaq 0x66d73(%rip), %r8      # 0x81058
movb $0x0, %al
callq 0x125f0
callq 0x12100
jmp 0x1a41a
movl -0x38(%rbp), %esi
shrl $0x8, %esi
leaq -0x20(%rbp), %rdi
callq 0x5ded0
jmp 0x1a41a
movl -0x38(%rbp), %esi
shrl $0x8, %esi
andl $0xff, %esi
leaq -0x20(%rbp), %rdi
callq 0x5ded0
jmp 0x1a41a
movl -0x38(%rbp), %esi
shrl $0x10, %esi
andl $0xff, %esi
leaq -0x20(%rbp), %rdi
callq 0x5ded0
jmp 0x1a41a
movl -0x38(%rbp), %esi
shrl $0x8, %esi
leaq -0x20(%rbp), %rdi
callq 0x5ded0
jmp 0x1a41a
movl -0x38(%rbp), %esi
shrl $0x10, %esi
leaq -0x20(%rbp), %rdi
callq 0x5ded0
jmp 0x1a41a
movl -0x38(%rbp), %esi
shrl $0x8, %esi
andl $0xff, %esi
leaq -0x20(%rbp), %rdi
callq 0x5ded0
movl -0x38(%rbp), %esi
shrl $0x10, %esi
andl $0xff, %esi
leaq -0x20(%rbp), %rdi
callq 0x5ded0
jmp 0x1a41a
movl -0x38(%rbp), %esi
shrl $0x8, %esi
andl $0xff, %esi
leaq -0x20(%rbp), %rdi
callq 0x5ded0
movl -0x38(%rbp), %esi
shrl $0x10, %esi
leaq -0x20(%rbp), %rdi
callq 0x5ded0
jmp 0x1a41a
movl -0x38(%rbp), %esi
shrl $0x10, %esi
andl $0xff, %esi
leaq -0x20(%rbp), %rdi
callq 0x5ded0
movl -0x38(%rbp), %esi
shrl $0x18, %esi
leaq -0x20(%rbp), %rdi
callq 0x5ded0
jmp 0x1a41a
movl -0x38(%rbp), %esi
shrl $0x8, %esi
andl $0xff, %esi
leaq -0x20(%rbp), %rdi
callq 0x5ded0
movl -0x38(%rbp), %esi
shrl $0x10, %esi
andl $0xff, %esi
leaq -0x20(%rbp), %rdi
callq 0x5ded0
movl -0x38(%rbp), %esi
shrl $0x18, %esi
leaq -0x20(%rbp), %rdi
callq 0x5ded0
jmp 0x1a41c
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x1a276
movl $0x0, -0x24(%rbp)
movl $0x0, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
movq -0x8(%rbp), %rcx
cmpl 0x70(%rcx), %eax
jge 0x1a57e
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x3c(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x40(%rbp)
movl -0x40(%rbp), %eax
andl $0x7f, %eax
movl %eax, -0x4c(%rbp)
subl $0x1a, %eax
je 0x1a508
jmp 0x1a46e
movl -0x4c(%rbp), %eax
subl $0x1b, %eax
je 0x1a538
jmp 0x1a47c
movl -0x4c(%rbp), %eax
addl $-0x28, %eax
subl $0x3, %eax
jb 0x1a4d8
jmp 0x1a489
movl -0x4c(%rbp), %eax
addl $-0x2b, %eax
subl $0x3, %eax
jb 0x1a538
jmp 0x1a49a
movl -0x4c(%rbp), %eax
subl $0x2e, %eax
je 0x1a4d8
jmp 0x1a4a4
movl -0x4c(%rbp), %eax
subl $0x30, %eax
je 0x1a538
jmp 0x1a4b2
movl -0x4c(%rbp), %eax
subl $0x3d, %eax
je 0x1a538
jmp 0x1a4bc
movl -0x4c(%rbp), %eax
subl $0x40, %eax
je 0x1a4d8
jmp 0x1a4c6
movl -0x4c(%rbp), %eax
addl $-0x45, %eax
subl $0x2, %eax
jb 0x1a4d8
jmp 0x1a4d3
jmp 0x1a56e
movl -0x40(%rbp), %esi
shrl $0x8, %esi
leaq -0x20(%rbp), %rdi
callq 0x5e110
cmpl $0x0, %eax
jne 0x1a506
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x3c(%rbp), %rcx
movl $0x0, (%rax,%rcx,4)
movl $0x1, -0x24(%rbp)
jmp 0x1a56e
movl -0x40(%rbp), %esi
shrl $0x10, %esi
leaq -0x20(%rbp), %rdi
callq 0x5e110
cmpl $0x0, %eax
jne 0x1a536
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x3c(%rbp), %rcx
movl $0x0, (%rax,%rcx,4)
movl $0x1, -0x24(%rbp)
jmp 0x1a56e
movl -0x40(%rbp), %esi
shrl $0x8, %esi
andl $0xff, %esi
leaq -0x20(%rbp), %rdi
callq 0x5e110
cmpl $0x0, %eax
jne 0x1a56c
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x3c(%rbp), %rcx
movl $0x0, (%rax,%rcx,4)
movl $0x1, -0x24(%rbp)
jmp 0x1a56e
jmp 0x1a570
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x1a438
leaq -0x20(%rbp), %rdi
callq 0x5ddd0
jmp 0x1a1f3
addq $0x50, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)