// File: /workspace/github_c_makefile_star2_O3/Tarsnap[P]kivaloo/kvlds/btree_balance.c
// Function: planmergenode
static int
planmergenode(struct balance_cookie * B, struct node * N)
{
	size_t maxplen = (B->T->pagelen * 2) / 3;
	size_t i;
	size_t plen;
	int gotdirty;
	int leafchild;
	int merging;

	/* If this node has no children, do nothing. */
	if (N->type != NODE_TYPE_PARENT)
		goto done;

	/* If this node is not dirty, it doesn't need splitting. */
	if (N->state != NODE_STATE_DIRTY)
		goto done;

	/* Plan merges under our children first. */
	for (i = 0; i <= N->nkeys; i++) {
		if (planmergenode(B, N->v.children[i]))
			goto err0;
	}

	/* Scan this node to see if we can merge any of its children. */
	/*
	 * Child number N->nkeys can't be merged into a higher-numbered child
	 * so we jump directly to nomerge.  This could be done using an
	 * "are we on the first pass through the loop" test inside the loop,
	 * but this confuses gcc.
	 */
	i = N->nkeys;
	goto nomerge;
	for (/* i = N->nkeys; */; i <= N->nkeys; i--) {
		/* Have we seen a dirty node yet? */
		if (N->v.children[i]->state == NODE_STATE_DIRTY) {
			gotdirty = 1;
			leafchild = (N->v.children[i]->type == NODE_TYPE_LEAF);
		}

		/*
		 * If we haven't seen a dirty node, we can't possibly need to
		 * merge this into the previous node.
		 */
		if (!gotdirty)
			goto nomerge;

		/*
		 * Figure out how large a node we'll produce if we merge this
		 * node into the next one.
		 */
		if (!leafchild)
			plen += kvldskey_serial_size(N->u.keys[i]);
		plen += serialize_merge_size(N->v.children[i]);

		/* Would the resulting node be too big? */
		if (plen > maxplen)
			goto nomerge;

		/* Mark this node as requiring merging. */
		N->v.children[i]->merging = 1;

		/* Move on to considering the next child. */
		continue;

nomerge:
		/*
		 * We're not merging this node into the next one.  Reset the
		 * state we're tracking so we can check if other nodes should
		 * be merged into this one.
		 */
		plen = serialize_size(N->v.children[i]);
		gotdirty = (N->v.children[i]->state == NODE_STATE_DIRTY);
		leafchild = (N->v.children[i]->type == NODE_TYPE_LEAF);
	}

	/* Page in any nodes which are needed for merging. */
	for (merging = i = 0; i <= N->nkeys; i++) {
		/* Do we need this node? */
		if (merging || N->v.children[i]->merging) {
			/* Is it present? */
			if (node_present(N->v.children[i])) {
				/* Make sure it stays present. */
				btree_node_lock(B->T, N->v.children[i]);
			} else {
				/* Fetch it. */
				B->nmergefetch += 1;
				if (btree_node_fetch(B->T, N->v.children[i],
				    merge_fetch, B))
					goto err0;
			}
		}

		/* Are we in the middle of a merging range? */
		merging = N->v.children[i]->merging;
	}

done:
	/* Success! */
	return (0);

err0:
	/* Failure! */
	return (-1);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq 0x10(%rdi), %rax
movq (%rax), %rax
addq %rax, %rax
movabsq $-0x5555555555555555, %rcx # imm = 0xAAAAAAAAAAAAAAAB
mulq %rcx
movb 0x1c(%rsi), %al
andb $0xf, %al
cmpb $0x8, %al
jne 0x6a96
movq %rsi, %rbx
movq %rdi, %r14
movq %rdx, %r15
shrq %r15
xorl %r12d, %r12d
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movq 0x48(%rbx), %rax
movq (%rax,%r12,8), %rsi
movq %r14, %rdi
callq 0x68d5
testl %eax, %eax
jne 0x6a98
incq %r12
movq 0x38(%rbx), %r13
cmpq %r13, %r12
jbe 0x6918
movq 0x48(%rbx), %rax
movq (%rax,%r13,8), %rdi
callq 0xa5e7
leaq -0x1(%r13), %r12
movq 0x48(%rbx), %rcx
cmpq 0x38(%rbx), %r12
ja 0x6a15
leaq (%rcx,%r13,8), %rdx
movq %r15, (%rsp)
movq (%rdx), %rcx
movb 0x1c(%rcx), %dl
movl %edx, %ecx
andb $0xc, %cl
cmpb $0x8, %cl
setne %cl
andb $0x3, %dl
xorl %r13d, %r13d
cmpb $0x1, %dl
sete %r13b
movl %r13d, %edx
movq 0x48(%rbx), %rsi
movq (%rsi,%r12,8), %rdi
movb 0x1c(%rdi), %sil
movl %esi, %r8d
andb $0xc, %r8b
andb $0x3, %sil
xorl %r13d, %r13d
cmpb $0x1, %sil
sete %r13b
cmpb $0x8, %r8b
cmovnel %edx, %r13d
je 0x69b5
testb $0x1, %cl
jne 0x69f5
testl %r13d, %r13d
jne 0x69cb
movq 0x40(%rbx), %rcx
movq (%rcx,%r12,8), %rcx
movzbl (%rcx), %ecx
addq %rcx, %rax
incq %rax
movq %rax, %r15
callq 0xab3d
addq %r15, %rax
movq 0x48(%rbx), %rcx
movq (%rcx,%r12,8), %rdi
cmpq (%rsp), %rax
ja 0x69f5
orb $0x20, 0x1c(%rdi)
decq %r12
xorl %ecx, %ecx
cmpq 0x38(%rbx), %r12
jbe 0x6981
jmp 0x6a11
callq 0xa5e7
movq 0x48(%rbx), %rcx
leaq (%rcx,%r12,8), %rdx
decq %r12
cmpq 0x38(%rbx), %r12
jbe 0x6963
jmp 0x6a15
movq 0x48(%rbx), %rcx
xorl %eax, %eax
leaq 0x231(%rip), %r15       # 0x6c4f
xorl %r12d, %r12d
movq (%rcx,%r12,8), %rsi
movb 0x1c(%rsi), %cl
testl %eax, %eax
jne 0x6a32
movl %ecx, %eax
andb $0x20, %al
je 0x6a7c
testb $0x2, %cl
jne 0x6a5d
movq 0x10(%r14), %rax
movq 0x30(%rax), %rdi
movq 0x20(%rdi), %rax
movq (%rsi,%rax), %rax
movq (%rax), %rcx
leaq 0x1(%rcx), %rdx
movq %rdx, (%rax)
testq %rcx, %rcx
jne 0x6a7c
callq 0x1070f
jmp 0x6a7c
incq 0x18(%r14)
movq 0x10(%r14), %rdi
movq 0x48(%rbx), %rax
movq (%rax,%r12,8), %rsi
movq %r15, %rdx
movq %r14, %rcx
callq 0x8ba0
testl %eax, %eax
jne 0x6a98
movq 0x48(%rbx), %rcx
movq (%rcx,%r12,8), %rax
movl 0x1c(%rax), %eax
shrl $0x5, %eax
andl $0x1, %eax
incq %r12
cmpq 0x38(%rbx), %r12
jbe 0x6a21
xorl %ebp, %ebp
movl %ebp, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq