// File: /workspace/github_c_makefile_star2_O0/lucvoo[P]sparse-dev/simplify.c
// Function: simplify_cast
static int simplify_cast(struct instruction *insn)
{
	unsigned long long mask;
	struct instruction *def, *def2;
	pseudo_t src = insn->src;
	pseudo_t val;
	int osize;
	int size;

	/* A cast of a constant? */
	if (constant(src))
		return simplify_constant_unop(insn);

	// can merge with the previous instruction?
	size = insn->size;
	def = src->def;
	switch (def_opcode(src)) {
	case OP_AND:
		val = def->src2;
		if (val->type != PSEUDO_VAL)
			break;
		/* A cast of a AND might be a no-op.. */
		switch (insn->opcode) {
		case OP_TRUNC:
			if (!one_use(src))
				break;
			def->opcode = OP_TRUNC;
			def->orig_type = def->type;
			def->type = insn->type;
			def->size = size;

			insn->opcode = OP_AND;
			mask = val->value;
			mask &= (1ULL << size) - 1;
			insn->src2 = value_pseudo(mask);
			return REPEAT_CSE;

		case OP_SEXT:
			if (val->value & (1 << (def->size - 1)))
				break;
			// OK, sign bit is 0
		case OP_ZEXT:
			if (!one_use(src))
				break;
			// transform:
			//	and.n	%b <- %a, M
			//	*ext.m	%c <- (n) %b
			// into:
			//	zext.m	%b <- %a
			//	and.m	%c <- %b, M
			// For ZEXT, the mask will always be small
			// enough. For SEXT, it can only be done if
			// the mask force the sign bit to 0.
			def->opcode = OP_ZEXT;
			def->orig_type = insn->orig_type;
			def->type = insn->type;
			def->size = insn->size;
			insn->opcode = OP_AND;
			insn->src2 = val;
			return REPEAT_CSE;
		}
		break;
	case OP_FPCMP ... OP_BINCMP_END:
		switch (insn->opcode) {
		case OP_SEXT:
			if (insn->size == 1)
				break;
			/* fall through */
		case OP_ZEXT:
		case OP_TRUNC:
			// simplify:
			//	setcc.n	%t <- %a, %b
			//	zext.m	%r <- (n) %t
			// into:
			//	setcc.m	%r <- %a, %b
			// and same for s/zext/trunc/
			insn->opcode = def->opcode;
			insn->itype = def->itype;
			use_pseudo(insn, def->src2, &insn->src2);
			return replace_pseudo(insn, &insn->src1, def->src1);
		}
		break;
	case OP_NOT:
		switch (insn->opcode) {
		case OP_TRUNC:
			if (one_use(src)) {
				// TRUNC(NOT(x)) --> NOT(TRUNC(x))
				insn->opcode = OP_NOT;
				def->orig_type = def->type;
				def->opcode = OP_TRUNC;
				def->type = insn->type;
				def->size = insn->size;
				return REPEAT_CSE;
			}
			break;
		}
		break;
	case OP_OR:
		switch (insn->opcode) {
		case OP_TRUNC:
			mask = bits_mask(insn->size);
			return simplify_mask_or(insn, mask, def);
		}
		break;
	case OP_LSR:
	case OP_SHL:
		if (insn->opcode != OP_TRUNC)
			break;
		mask = bits_mask(insn->size);
		return simplify_mask_shift(def, mask);
	case OP_TRUNC:
		switch (insn->opcode) {
		case OP_TRUNC:
			insn->orig_type = def->orig_type;
			return replace_pseudo(insn, &insn->src1, def->src);
		case OP_SEXT:
			if (size != def->orig_type->bit_size)
				break;
			if (DEF_OPCODE(def2, def->src) != OP_LSR)
				break;
			if (def2->src2 != value_pseudo(size - def->size))
				break;
			// SEXT(TRUNC(LSR(x, N))) --> ASR(x, N)
			insn->opcode = OP_ASR;
			insn->src2 = def2->src2;
			return replace_pseudo(insn, &insn->src1, def2->src1);
		case OP_ZEXT:
			if (size != def->orig_type->bit_size)
				break;
			insn->opcode = OP_AND;
			insn->src2 = value_pseudo((1ULL << def->size) - 1);
			return replace_pseudo(insn, &insn->src1, def->src);
		}
		break;
	case OP_ZEXT:
		switch (insn->opcode) {
		case OP_SEXT:
			insn->opcode = OP_ZEXT;
			/* fall through */
		case OP_ZEXT:
			insn->orig_type = def->orig_type;
			return replace_pseudo(insn, &insn->src, def->src);
		}
		/* fall through */
	case OP_SEXT:
		switch (insn->opcode) {
		case OP_TRUNC:
			osize = def->orig_type->bit_size;
			if (size == osize)
				return replace_with_pseudo(insn, def->src);
			if (size > osize)
				insn->opcode = def->opcode;
			insn->orig_type = def->orig_type;
			return replace_pseudo(insn, &insn->src, def->src);
		}
		switch (insn->opcode) {
		case OP_SEXT:
			insn->orig_type = def->orig_type;
			return replace_pseudo(insn, &insn->src, def->src);
		}
		break;
	}

	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rdi
callq 0x382a0
cmpl $0x0, %eax
je 0x36757
movq -0x10(%rbp), %rdi
callq 0x3b640
movl %eax, -0x4(%rbp)
jmp 0x36dce
movq -0x10(%rbp), %rax
movl (%rax), %eax
shrl $0x8, %eax
movl %eax, -0x40(%rbp)
movq -0x30(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x30(%rbp), %rdi
callq 0x3c990
addl $-0xf, %eax
movl %eax, %ecx
movq %rcx, -0x48(%rbp)
subl $0x27, %eax
ja 0x36dc7
movq -0x48(%rbp), %rax
leaq 0x3229f(%rip), %rcx     # 0x68a34
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x20(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
cmpl $0x6, 0x4(%rax)
je 0x367b9
jmp 0x36dc7
movq -0x10(%rbp), %rax
movl (%rax), %eax
andl $0x7f, %eax
movl %eax, -0x4c(%rbp)
subl $0x34, %eax
je 0x367eb
jmp 0x367cc
movl -0x4c(%rbp), %eax
subl $0x35, %eax
je 0x368ca
jmp 0x367da
movl -0x4c(%rbp), %eax
subl $0x36, %eax
je 0x3689a
jmp 0x3694f
movq -0x30(%rbp), %rdi
callq 0x3ad20
testb $0x1, %al
jne 0x367fd
jmp 0x3694f
movq -0x20(%rbp), %rax
movl (%rax), %ecx
andl $-0x80, %ecx
orl $0x34, %ecx
movl %ecx, (%rax)
movq -0x20(%rbp), %rax
movq 0x18(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x40(%rax)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x18(%rax)
movl -0x40(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
andl $0xffffff, %edx         # imm = 0xFFFFFF
shll $0x8, %edx
andl $0xff, %ecx
orl %edx, %ecx
movl %ecx, (%rax)
movq -0x10(%rbp), %rax
movl (%rax), %ecx
andl $-0x80, %ecx
orl $0x16, %ecx
movl %ecx, (%rax)
movq -0x38(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x18(%rbp)
movl -0x40(%rbp), %eax
movl %eax, %ecx
movl $0x1, %eax
shlq %cl, %rax
subq $0x1, %rax
andq -0x18(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
callq 0x1a390
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x38(%rax)
movl $0x1, -0x4(%rbp)
jmp 0x36dce
movq -0x38(%rbp), %rax
movq 0x18(%rax), %rax
movq -0x20(%rbp), %rcx
movl (%rcx), %ecx
shrl $0x8, %ecx
subl $0x1, %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
movslq %ecx, %rcx
andq %rcx, %rax
cmpq $0x0, %rax
je 0x368c8
jmp 0x3694f
jmp 0x368ca
movq -0x30(%rbp), %rdi
callq 0x3ad20
testb $0x1, %al
jne 0x368d9
jmp 0x3694f
movq -0x20(%rbp), %rax
movl (%rax), %ecx
andl $-0x80, %ecx
orl $0x35, %ecx
movl %ecx, (%rax)
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x40(%rax)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x10(%rbp), %rax
movl (%rax), %edx
shrl $0x8, %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
andl $0xffffff, %edx         # imm = 0xFFFFFF
shll $0x8, %edx
andl $0xff, %ecx
orl %edx, %ecx
movl %ecx, (%rax)
movq -0x10(%rbp), %rax
movl (%rax), %ecx
andl $-0x80, %ecx
orl $0x16, %ecx
movl %ecx, (%rax)
movq -0x38(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x38(%rax)
movl $0x1, -0x4(%rbp)
jmp 0x36dce
jmp 0x36dc7
movq -0x10(%rbp), %rax
movl (%rax), %eax
andl $0x7f, %eax
movl %eax, -0x50(%rbp)
addl $-0x34, %eax
subl $0x2, %eax
jb 0x36986
jmp 0x3696a
movl -0x50(%rbp), %eax
subl $0x36, %eax
jne 0x369ed
jmp 0x36974
movq -0x10(%rbp), %rax
movl (%rax), %eax
shrl $0x8, %eax
cmpl $0x1, %eax
jne 0x36984
jmp 0x369ed
jmp 0x36986
movq -0x20(%rbp), %rax
movl (%rax), %edx
andl $0x7f, %edx
movq -0x10(%rbp), %rax
movl (%rax), %ecx
andl $0x7f, %edx
andl $-0x80, %ecx
orl %edx, %ecx
movl %ecx, (%rax)
movq -0x20(%rbp), %rax
movq 0x40(%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x40(%rax)
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rax
movq 0x38(%rax), %rsi
movq -0x10(%rbp), %rdx
addq $0x30, %rdx
addq $0x8, %rdx
callq 0x381b0
movq -0x10(%rbp), %rdi
movq -0x10(%rbp), %rsi
addq $0x30, %rsi
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rdx
callq 0x38d50
movl %eax, -0x4(%rbp)
jmp 0x36dce
jmp 0x36dc7
movq -0x10(%rbp), %rax
movl (%rax), %eax
andl $0x7f, %eax
subl $0x34, %eax
jne 0x36a7d
jmp 0x36a02
movq -0x30(%rbp), %rdi
callq 0x3ad20
testb $0x1, %al
jne 0x36a11
jmp 0x36a7b
movq -0x10(%rbp), %rax
movl (%rax), %ecx
andl $-0x80, %ecx
orl $0x31, %ecx
movl %ecx, (%rax)
movq -0x20(%rbp), %rax
movq 0x18(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x40(%rax)
movq -0x20(%rbp), %rax
movl (%rax), %ecx
andl $-0x80, %ecx
orl $0x34, %ecx
movl %ecx, (%rax)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x10(%rbp), %rax
movl (%rax), %edx
shrl $0x8, %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
andl $0xffffff, %edx         # imm = 0xFFFFFF
shll $0x8, %edx
andl $0xff, %ecx
orl %edx, %ecx
movl %ecx, (%rax)
movl $0x1, -0x4(%rbp)
jmp 0x36dce
jmp 0x36a7d
jmp 0x36dc7
movq -0x10(%rbp), %rax
movl (%rax), %eax
andl $0x7f, %eax
subl $0x34, %eax
jne 0x36abd
jmp 0x36a92
movq -0x10(%rbp), %rax
movl (%rax), %edi
shrl $0x8, %edi
callq 0x3acf0
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0x3af30
movl %eax, -0x4(%rbp)
jmp 0x36dce
jmp 0x36dc7
movq -0x10(%rbp), %rax
movl (%rax), %eax
andl $0x7f, %eax
cmpl $0x34, %eax
je 0x36ad5
jmp 0x36dc7
movq -0x10(%rbp), %rax
movl (%rax), %edi
shrl $0x8, %edi
callq 0x3acf0
movq %rax, -0x18(%rbp)
movq -0x20(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x3b230
movl %eax, -0x4(%rbp)
jmp 0x36dce
movq -0x10(%rbp), %rax
movl (%rax), %eax
andl $0x7f, %eax
movl %eax, -0x54(%rbp)
subl $0x34, %eax
je 0x36b2a
jmp 0x36b0f
movl -0x54(%rbp), %eax
subl $0x35, %eax
je 0x36c28
jmp 0x36b1d
movl -0x54(%rbp), %eax
subl $0x36, %eax
je 0x36b5b
jmp 0x36c92
movq -0x20(%rbp), %rax
movq 0x40(%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x40(%rax)
movq -0x10(%rbp), %rdi
movq -0x10(%rbp), %rsi
addq $0x30, %rsi
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rdx
callq 0x38d50
movl %eax, -0x4(%rbp)
jmp 0x36dce
movl -0x40(%rbp), %eax
movq -0x20(%rbp), %rcx
movq 0x40(%rcx), %rcx
cmpl 0x50(%rcx), %eax
je 0x36b70
jmp 0x36c92
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rax
cmpl $0x3, 0x4(%rax)
jne 0x36ba2
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rax
movq 0x18(%rax), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, %rax
je 0x36ba2
movq -0x28(%rbp), %rax
movl (%rax), %eax
andl $0x7f, %eax
movl %eax, -0x58(%rbp)
jmp 0x36ba9
xorl %eax, %eax
movl %eax, -0x58(%rbp)
jmp 0x36ba9
movl -0x58(%rbp), %eax
cmpl $0xf, %eax
je 0x36bb6
jmp 0x36c92
movq -0x28(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x60(%rbp)
movl -0x40(%rbp), %eax
movq -0x20(%rbp), %rcx
movl (%rcx), %ecx
shrl $0x8, %ecx
subl %ecx, %eax
movslq %eax, %rdi
callq 0x1a390
movq %rax, %rcx
movq -0x60(%rbp), %rax
cmpq %rcx, %rax
je 0x36be9
jmp 0x36c92
movq -0x10(%rbp), %rax
movl (%rax), %ecx
andl $-0x80, %ecx
orl $0x10, %ecx
movl %ecx, (%rax)
movq -0x28(%rbp), %rax
movq 0x38(%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x38(%rax)
movq -0x10(%rbp), %rdi
movq -0x10(%rbp), %rsi
addq $0x30, %rsi
movq -0x28(%rbp), %rax
movq 0x30(%rax), %rdx
callq 0x38d50
movl %eax, -0x4(%rbp)
jmp 0x36dce
movl -0x40(%rbp), %eax
movq -0x20(%rbp), %rcx
movq 0x40(%rcx), %rcx
cmpl 0x50(%rcx), %eax
je 0x36c3a
jmp 0x36c92
movq -0x10(%rbp), %rax
movl (%rax), %ecx
andl $-0x80, %ecx
orl $0x16, %ecx
movl %ecx, (%rax)
movq -0x20(%rbp), %rax
movl (%rax), %eax
shrl $0x8, %eax
movl %eax, %eax
movl %eax, %ecx
movl $0x1, %edi
shlq %cl, %rdi
subq $0x1, %rdi
callq 0x1a390
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x38(%rax)
movq -0x10(%rbp), %rdi
movq -0x10(%rbp), %rsi
addq $0x30, %rsi
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rdx
callq 0x38d50
movl %eax, -0x4(%rbp)
jmp 0x36dce
jmp 0x36dc7
movq -0x10(%rbp), %rax
movl (%rax), %eax
andl $0x7f, %eax
movl %eax, -0x64(%rbp)
subl $0x35, %eax
je 0x36cc2
jmp 0x36caa
movl -0x64(%rbp), %eax
subl $0x36, %eax
jne 0x36cf3
jmp 0x36cb4
movq -0x10(%rbp), %rax
movl (%rax), %ecx
andl $-0x80, %ecx
orl $0x35, %ecx
movl %ecx, (%rax)
movq -0x20(%rbp), %rax
movq 0x40(%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x40(%rax)
movq -0x10(%rbp), %rdi
movq -0x10(%rbp), %rsi
addq $0x30, %rsi
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rdx
callq 0x38d50
movl %eax, -0x4(%rbp)
jmp 0x36dce
jmp 0x36cf5
movq -0x10(%rbp), %rax
movl (%rax), %eax
andl $0x7f, %eax
subl $0x34, %eax
jne 0x36d87
jmp 0x36d09
movq -0x20(%rbp), %rax
movq 0x40(%rax), %rax
movl 0x50(%rax), %eax
movl %eax, -0x3c(%rbp)
movl -0x40(%rbp), %eax
cmpl -0x3c(%rbp), %eax
jne 0x36d38
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rsi
callq 0x357e0
movl %eax, -0x4(%rbp)
jmp 0x36dce
movl -0x40(%rbp), %eax
cmpl -0x3c(%rbp), %eax
jle 0x36d59
movq -0x20(%rbp), %rax
movl (%rax), %edx
andl $0x7f, %edx
movq -0x10(%rbp), %rax
movl (%rax), %ecx
andl $0x7f, %edx
andl $-0x80, %ecx
orl %edx, %ecx
movl %ecx, (%rax)
movq -0x20(%rbp), %rax
movq 0x40(%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x40(%rax)
movq -0x10(%rbp), %rdi
movq -0x10(%rbp), %rsi
addq $0x30, %rsi
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rdx
callq 0x38d50
movl %eax, -0x4(%rbp)
jmp 0x36dce
movq -0x10(%rbp), %rax
movl (%rax), %eax
andl $0x7f, %eax
subl $0x36, %eax
jne 0x36dc5
jmp 0x36d97
movq -0x20(%rbp), %rax
movq 0x40(%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x40(%rax)
movq -0x10(%rbp), %rdi
movq -0x10(%rbp), %rsi
addq $0x30, %rsi
movq -0x20(%rbp), %rax
movq 0x30(%rax), %rdx
callq 0x38d50
movl %eax, -0x4(%rbp)
jmp 0x36dce
jmp 0x36dc7
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x70, %rsp
popq %rbp
retq
nopw (%rax,%rax)