// File: /workspace/github_cpp_makefile_star2_O1/rossy[P]crossc/SPIRV-Cross/spirv_cross.cpp
// Function: spirv_cross::Compiler::analyze_parameter_preservation(spirv_cross::SPIRFunction&, spirv_cross::CFG const&, std::unordered_map<unsigned int, std::unordered_set<unsigned int, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<unsigned int>>, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, std::unordered_set<unsigned int, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<unsigned int>>>>> const&, std::unordered_map<unsigned int, std::unordered_set<unsigned int, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<unsigned int>>, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, std::unordered_set<unsigned int, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<unsigned int>>>>> const&)
void Compiler::analyze_parameter_preservation(
    SPIRFunction &entry, const CFG &cfg, const unordered_map<uint32_t, unordered_set<uint32_t>> &variable_to_blocks,
    const unordered_map<uint32_t, unordered_set<uint32_t>> &complete_write_blocks)
{
	for (auto &arg : entry.arguments)
	{
		// Non-pointers are always inputs.
		auto &type = get<SPIRType>(arg.type);
		if (!type.pointer)
			continue;

		// Opaque argument types are always in
		bool potential_preserve;
		switch (type.basetype)
		{
		case SPIRType::Sampler:
		case SPIRType::Image:
		case SPIRType::SampledImage:
		case SPIRType::AtomicCounter:
			potential_preserve = false;
			break;

		default:
			potential_preserve = true;
			break;
		}

		if (!potential_preserve)
			continue;

		auto itr = variable_to_blocks.find(arg.id);
		if (itr == end(variable_to_blocks))
		{
			// Variable is never accessed.
			continue;
		}

		// We have accessed a variable, but there was no complete writes to that variable.
		// We deduce that we must preserve the argument.
		itr = complete_write_blocks.find(arg.id);
		if (itr == end(complete_write_blocks))
		{
			arg.read_count++;
			continue;
		}

		// If there is a path through the CFG where no block completely writes to the variable, the variable will be in an undefined state
		// when the function returns. We therefore need to implicitly preserve the variable in case there are writers in the function.
		// Major case here is if a function is
		// void foo(int &var) { if (cond) var = 10; }
		// Using read/write counts, we will think it's just an out variable, but it really needs to be inout,
		// because if we don't write anything whatever we put into the function must return back to the caller.
		if (exists_unaccessed_path_to_return(cfg, entry.entry_block, itr->second))
			arg.read_count++;
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %r8, 0x10(%rsp)
movq %rdx, 0x8(%rsp)
movq 0x18(%rsi), %rbp
movq 0x20(%rsi), %r15
cmpq %r15, %rbp
je 0x18841
movq %rcx, %r14
movq %rsi, %r12
movq %rdi, %r13
addq $0x4, %rbp
movl $0xe100, %ebx           # imm = 0xE100
movl -0x4(%rbp), %esi
movq %r13, %rdi
callq 0xa426
cmpb $0x1, 0x60(%rax)
jne 0x187bd
movl 0xc(%rax), %eax
cmpl $0xf, %eax
ja 0x187cf
btl %eax, %ebx
jae 0x187cf
leaq 0x14(%rbp), %rax
addq $0x10, %rbp
cmpq %r15, %rbp
movq %rax, %rbp
jne 0x1879f
jmp 0x18841
movl (%rbp), %ecx
movq %rcx, %rax
xorl %edx, %edx
divq 0x8(%r14)
movq %r14, %rdi
movq %rdx, %rsi
movq %rbp, %rdx
callq 0x23792
testq %rax, %rax
je 0x187bd
cmpq $0x0, (%rax)
je 0x187bd
movl (%rbp), %ecx
movq %rcx, %rax
xorl %edx, %edx
movq 0x10(%rsp), %rdi
divq 0x8(%rdi)
movq %rdx, %rsi
movq %rbp, %rdx
callq 0x23792
movl $0x0, %edx
testq %rax, %rax
je 0x1881d
movq (%rax), %rdx
testq %rdx, %rdx
je 0x18839
movl 0x60(%r12), %esi
addq $0x10, %rdx
movq 0x8(%rsp), %rdi
callq 0x18850
testb %al, %al
je 0x187bd
incl 0x4(%rbp)
jmp 0x187bd
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq