// File: splatlab[P]debgr/threadsafe-gqf/gqf.c
// Function: remove(quotient_filter*, unsigned __int128, unsigned long, bool, bool)
inline static bool _remove(QF *qf, __uint128_t hash, uint64_t count, bool lock, bool spin)
{
	uint64_t hash_remainder           = hash & BITMASK(qf->metadata->bits_per_slot);
	uint64_t hash_bucket_index        = hash >> qf->metadata->bits_per_slot;
	uint64_t hash_bucket_lock_offset  = hash_bucket_index % NUM_SLOTS_TO_LOCK;
	uint64_t current_remainder, current_count, current_end;
	uint64_t new_values[67];

	/* Empty bucket */
	if (!is_occupied(qf, hash_bucket_index))
		return false;

	if (lock) {
		/* take the lock for two lock-blocks; the lock-block in which the
		 * hash_bucket_index falls and the next lock-block */

#ifdef LOG_WAIT_TIME
		if (!qf_spin_lock(qf, &qf->mem->locks[hash_bucket_index/NUM_SLOTS_TO_LOCK],
											hash_bucket_index/NUM_SLOTS_TO_LOCK, spin))
			return false;
		if (hash_bucket_lock_offset > (NUM_SLOTS_TO_LOCK - CLUSTER_SIZE)) {
			if (!qf_spin_lock(qf, &qf->mem->locks[hash_bucket_index/NUM_SLOTS_TO_LOCK+1],
												hash_bucket_index/NUM_SLOTS_TO_LOCK+1, spin)) {
				qf_spin_unlock(&qf->mem->locks[hash_bucket_index/NUM_SLOTS_TO_LOCK]);
				return false;
			}
		}
#else
		if (!qf_spin_lock(&qf->mem->locks[hash_bucket_index/NUM_SLOTS_TO_LOCK], spin))
			return false;
		if (hash_bucket_lock_offset > (NUM_SLOTS_TO_LOCK - CLUSTER_SIZE)) {
			if (!qf_spin_lock(&qf->mem->locks[hash_bucket_index/NUM_SLOTS_TO_LOCK+1], spin)) {
				qf_spin_unlock(&qf->mem->locks[hash_bucket_index/NUM_SLOTS_TO_LOCK]);
				return false;
			}
		}
#endif
	}
	uint64_t runstart_index = hash_bucket_index == 0 ? 0 : run_end(qf, hash_bucket_index - 1) + 1;
	uint64_t original_runstart_index = runstart_index;
	int only_item_in_the_run = 0;

	/*Find the counter for this remainder, if one exists.*/
	current_end = decode_counter(qf, runstart_index, &current_remainder, &current_count);
	while (current_remainder < hash_remainder && !is_runend(qf, current_end)) {
		runstart_index = current_end + 1;
		current_end = decode_counter(qf, runstart_index, &current_remainder, &current_count);
	}
	/* remainder not found in the given run */
	if (current_remainder != hash_remainder) {
		if (lock) {
			qf_spin_unlock(&qf->mem->locks[hash_bucket_index/NUM_SLOTS_TO_LOCK]);
			if (hash_bucket_lock_offset > (NUM_SLOTS_TO_LOCK - CLUSTER_SIZE))
				qf_spin_unlock(&qf->mem->locks[hash_bucket_index/NUM_SLOTS_TO_LOCK+1]);
		}
		return false;
	}

	if (original_runstart_index == runstart_index && is_runend(qf, current_end))
		only_item_in_the_run = 1;

	/* endode the new counter */
	uint64_t *p = encode_counter(qf, hash_remainder,
															 count > current_count ? 0 : current_count - count,
															 &new_values[67]);
	remove_replace_slots_and_shift_remainders_and_runends_and_offsets(qf,
																																		only_item_in_the_run,
																																		hash_bucket_index,
																																		runstart_index,
																																		p,
																																		&new_values[67] - p,
																																		current_end - runstart_index + 1);

	if (lock) {
		qf_spin_unlock(&qf->mem->locks[hash_bucket_index/NUM_SLOTS_TO_LOCK]);
		if (hash_bucket_lock_offset > (NUM_SLOTS_TO_LOCK - CLUSTER_SIZE))
			qf_spin_unlock(&qf->mem->locks[hash_bucket_index/NUM_SLOTS_TO_LOCK+1]);
	}

	return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x330, %rsp            # imm = 0x330
movl %r8d, -0x2e4(%rbp)
movq %rcx, %rax
movl -0x2e4(%rbp), %ecx
movq %rax, -0x2e0(%rbp)
movq %rdx, %rax
movq -0x2e0(%rbp), %rdx
movq %rax, -0x2d8(%rbp)
movq %rsi, %rax
movq -0x2d8(%rbp), %rsi
movq %rax, -0x2d0(%rbp)
movq %rdi, %r8
movq -0x2d0(%rbp), %rdi
movb %r9b, %al
movq %rdi, -0x20(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x20(%rbp), %rsi
movq -0x18(%rbp), %rdi
movq %r8, -0x28(%rbp)
movq %rdi, -0x38(%rbp)
movq %rsi, -0x40(%rbp)
movq %rdx, -0x48(%rbp)
andb $0x1, %cl
movb %cl, -0x49(%rbp)
andb $0x1, %al
movb %al, -0x4a(%rbp)
movq -0x40(%rbp), %rax
movq %rax, -0x2c8(%rbp)
movq -0x38(%rbp), %rax
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
cmpq $0x40, 0x38(%rax)
jne 0x26a8a
movq $-0x1, %rax
movq %rax, -0x2f0(%rbp)
jmp 0x26aa9
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x38(%rax), %rcx
movl $0x1, %eax
shlq %cl, %rax
subq $0x1, %rax
movq %rax, -0x2f0(%rbp)
movq -0x2c8(%rbp), %rax
movq -0x2f0(%rbp), %rcx
andq %rcx, %rax
movq %rax, -0x58(%rbp)
movq -0x40(%rbp), %rax
movq -0x38(%rbp), %rsi
movq -0x28(%rbp), %rcx
movq 0x8(%rcx), %rcx
movb 0x38(%rcx), %dl
movb %dl, %cl
movq %rsi, %rdi
shrq %cl, %rdi
movq %rdi, -0x2f8(%rbp)
movb %dl, %cl
shrdq %cl, %rsi, %rax
movq -0x2f8(%rbp), %rcx
testb $0x40, %dl
cmovneq %rcx, %rax
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
andq $0xfff, %rax            # imm = 0xFFF
movq %rax, -0x68(%rbp)
movq -0x28(%rbp), %rdi
movq -0x60(%rbp), %rsi
callq 0x26e50
cmpl $0x0, %eax
jne 0x26b21
movb $0x0, -0x1(%rbp)
jmp 0x26e3e
testb $0x1, -0x49(%rbp)
je 0x26bc4
movq -0x28(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rdi
movq -0x60(%rbp), %rax
shrq $0xc, %rax
shlq $0x2, %rax
addq %rax, %rdi
movb -0x4a(%rbp), %al
andb $0x1, %al
movzbl %al, %esi
callq 0x27ff0
testb $0x1, %al
jne 0x26b5f
movb $0x0, -0x1(%rbp)
jmp 0x26e3e
cmpq $0xf00, -0x68(%rbp)     # imm = 0xF00
jbe 0x26bc2
movq -0x28(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rdi
movq -0x60(%rbp), %rax
shrq $0xc, %rax
addq $0x1, %rax
shlq $0x2, %rax
addq %rax, %rdi
movb -0x4a(%rbp), %al
andb $0x1, %al
movzbl %al, %esi
callq 0x27ff0
testb $0x1, %al
jne 0x26bc0
movq -0x28(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rdi
movq -0x60(%rbp), %rax
shrq $0xc, %rax
shlq $0x2, %rax
addq %rax, %rdi
callq 0x28050
movb $0x0, -0x1(%rbp)
jmp 0x26e3e
jmp 0x26bc2
jmp 0x26bc4
cmpq $0x0, -0x60(%rbp)
jne 0x26bd6
xorl %eax, %eax
movq %rax, -0x300(%rbp)
jmp 0x26bf2
movq -0x28(%rbp), %rdi
movq -0x60(%rbp), %rsi
subq $0x1, %rsi
callq 0x26ea0
addq $0x1, %rax
movq %rax, -0x300(%rbp)
movq -0x300(%rbp), %rax
movq %rax, -0x2a8(%rbp)
movq -0x2a8(%rbp), %rax
movq %rax, -0x2b0(%rbp)
movl $0x0, -0x2b4(%rbp)
movq -0x28(%rbp), %rdi
movq -0x2a8(%rbp), %rsi
leaq -0x70(%rbp), %rdx
leaq -0x78(%rbp), %rcx
callq 0x27050
movq %rax, -0x80(%rbp)
movq -0x70(%rbp), %rcx
xorl %eax, %eax
cmpq -0x58(%rbp), %rcx
movb %al, -0x301(%rbp)
jae 0x26c61
movq -0x28(%rbp), %rdi
movq -0x80(%rbp), %rsi
callq 0x27380
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
movb %al, -0x301(%rbp)
movb -0x301(%rbp), %al
testb $0x1, %al
jne 0x26c6d
jmp 0x26c9a
movq -0x80(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x2a8(%rbp)
movq -0x28(%rbp), %rdi
movq -0x2a8(%rbp), %rsi
leaq -0x70(%rbp), %rdx
leaq -0x78(%rbp), %rcx
callq 0x27050
movq %rax, -0x80(%rbp)
jmp 0x26c34
movq -0x70(%rbp), %rax
cmpq -0x58(%rbp), %rax
je 0x26d01
testb $0x1, -0x49(%rbp)
je 0x26cf8
movq -0x28(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rdi
movq -0x60(%rbp), %rax
shrq $0xc, %rax
shlq $0x2, %rax
addq %rax, %rdi
callq 0x28050
cmpq $0xf00, -0x68(%rbp)     # imm = 0xF00
jbe 0x26cf6
movq -0x28(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rdi
movq -0x60(%rbp), %rax
shrq $0xc, %rax
addq $0x1, %rax
shlq $0x2, %rax
addq %rax, %rdi
callq 0x28050
jmp 0x26cf8
movb $0x0, -0x1(%rbp)
jmp 0x26e3e
movq -0x2b0(%rbp), %rax
cmpq -0x2a8(%rbp), %rax
jne 0x26d2d
movq -0x28(%rbp), %rdi
movq -0x80(%rbp), %rsi
callq 0x27380
cmpl $0x0, %eax
je 0x26d2d
movl $0x1, -0x2b4(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0x318(%rbp)
movq -0x58(%rbp), %rax
movq %rax, -0x310(%rbp)
movq -0x48(%rbp), %rax
cmpq -0x78(%rbp), %rax
jbe 0x26d58
xorl %eax, %eax
movq %rax, -0x320(%rbp)
jmp 0x26d67
movq -0x78(%rbp), %rax
subq -0x48(%rbp), %rax
movq %rax, -0x320(%rbp)
movq -0x310(%rbp), %rsi
movq -0x318(%rbp), %rdi
movq -0x320(%rbp), %rdx
leaq -0x2a0(%rbp), %rcx
addq $0x218, %rcx            # imm = 0x218
callq 0x289f0
movq %rax, -0x2c0(%rbp)
movq -0x28(%rbp), %rdi
movl -0x2b4(%rbp), %esi
movq -0x60(%rbp), %rdx
movq -0x2a8(%rbp), %rcx
movq -0x2c0(%rbp), %r8
leaq -0x2a0(%rbp), %r9
addq $0x218, %r9             # imm = 0x218
movq -0x2c0(%rbp), %rax
subq %rax, %r9
sarq $0x3, %r9
movq -0x80(%rbp), %rax
subq -0x2a8(%rbp), %rax
addq $0x1, %rax
movq %rax, (%rsp)
callq 0x29370
testb $0x1, -0x49(%rbp)
je 0x26e3a
movq -0x28(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rdi
movq -0x60(%rbp), %rax
shrq $0xc, %rax
shlq $0x2, %rax
addq %rax, %rdi
callq 0x28050
cmpq $0xf00, -0x68(%rbp)     # imm = 0xF00
jbe 0x26e38
movq -0x28(%rbp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rdi
movq -0x60(%rbp), %rax
shrq $0xc, %rax
addq $0x1, %rax
shlq $0x2, %rax
addq %rax, %rdi
callq 0x28050
jmp 0x26e3a
movb $0x1, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x330, %rsp            # imm = 0x330
popq %rbp
retq
nopl (%rax)