// File: /workspace/github_c_makefile_star2_O1/lucvoo[P]sparse-dev/simplify.c
// Function: simplify_select
static int simplify_select(struct instruction *insn)
{
	pseudo_t cond, src1, src2;
	struct instruction *def;

	cond = insn->src1;
	src1 = insn->src2;
	src2 = insn->src3;

	if (constant(cond))
		return replace_with_pseudo(insn, cond->value ? src1 : src2);
	if (src1 == src2)
		return replace_with_pseudo(insn, src1);

	if (constant(src1) && constant(src2)) {
		long long val1 = src1->value;
		long long val2 = src2->value;

		/* The pair 0/1 is special - replace with SETNE/SETEQ */
		if ((val1 | val2) == 1) {
			int opcode = OP_SET_EQ;
			if (val1) {
				src1 = src2;
				opcode = OP_SET_NE;
			}
			insn->opcode = opcode;
			insn->itype = insn->type;
			/* insn->src1 is already cond */
			insn->src2 = src1; /* Zero */
			return REPEAT_CSE;
		}
	}
	if (cond == src2 && is_zero(src1))			// SEL(x, 0, x) --> 0
		return replace_with_pseudo(insn, src1);
	if (cond == src1 && is_zero(src2))			// SEL(x, x, 0) --> x
		return replace_with_pseudo(insn, cond);

	switch (DEF_OPCODE(def, cond)) {
	case OP_SET_EQ:
		if (src1 == def->src1 && src2 == def->src2)
			return replace_with_pseudo(insn, src2); // SEL(x==y,x,y) --> y
		if (src2 == def->src1 && src1 == def->src2)
			return replace_with_pseudo(insn, src2); // SEL(y==x,x,y) --> y
		break;
	case OP_SET_NE:
		if (src1 == def->src1 && src2 == def->src2)
			return replace_with_pseudo(insn, src1); // SEL(x!=y,x,y) --> x
		if (src2 == def->src1 && src1 == def->src2)
			return replace_with_pseudo(insn, src1); // SEL(y!=x,x,y) --> x
		break;
	case OP_SET_LE: case OP_SET_LT:
	case OP_SET_BE: case OP_SET_B:
		if (!one_use(cond))
			break;
		// SEL(x {<,<=} y, a, b) --> SEL(x {>=,>} y, b, a)
		def->opcode = opcode_negate(def->opcode);
		return switch_pseudo(insn, &insn->src2, insn, &insn->src3);
	case OP_SET_GT:
		if (one_use(cond) && is_zero(def->src2)) {
			if (is_negate_of(src2, src1))
				// SEL(x > 0, a, -a) --> SEL(x >= 0, a, -a)
				return replace_opcode(def, OP_SET_GE);
		}
		break;
	case OP_SEL:
		if (constant(def->src2) && constant(def->src3)) {
			// Is the def of the conditional another select?
			// And if that one results in a "zero or not", use the
			// original conditional instead.
			//	SEL(SEL(x, C, 0), y, z) --> SEL(x, y, z)
			//	SEL(SEL(x, C, 0), C, 0) --> SEL(x, C, 0) == cond
			//	SEL(SEL(x, 0, C), y, z) --> SEL(x, z, y)
			//	SEL(SEL(x, C1, C2), y, z) --> y
			if (!def->src3->value) {
				if ((src1 == def->src2) && (src2 == def->src3))
					return replace_with_pseudo(insn, cond);
				return replace_pseudo(insn, &insn->cond, def->cond);
			}
			if (!def->src2->value) {
				switch_pseudo(insn, &insn->src2, insn, &insn->src3);
				return replace_pseudo(insn, &insn->cond, def->cond);
			}
			// both values must be non-zero
			return replace_with_pseudo(insn, src1);
		}
	case OP_AND:
		if (is_pow2(def->src2) && is_pow2(src1) && is_zero(src2) && insn->size == def->size && one_use(cond)) {
			unsigned s1 = log2_exact(def->src2->value);
			unsigned s2 = log2_exact(insn->src2->value);
			unsigned shift;

			if (s1 == s2)
				return replace_with_pseudo(insn, cond);

			// SEL(x & A, B, 0) --> SHIFT(x & A, S)
			insn->opcode = (s1 < s2) ? OP_SHL : OP_LSR;
			shift = (s1 < s2) ? (s2 - s1) : (s1 - s2);
			insn->src2 = value_pseudo(shift);
			return REPEAT_CSE;
		}
		break;
	}

	switch (DEF_OPCODE(def, src1)) {
	case OP_ADD: case OP_OR: case OP_XOR:
		if ((def->src1 == src2) && can_move_to(cond, def)) {
			// SEL(x, OP(y,z), y) --> OP(SEL(x, z, 0), y)
			swap_select(insn, def, cond, def->src2, value_pseudo(0), src2);
			return REPEAT_CSE;
		}
		if ((def->src2 == src2) && can_move_to(cond, def)) {
			// SEL(x, OP(z,y), y) --> OP(SEL(x, z, 0), y)
			swap_select(insn, def, cond, def->src1, value_pseudo(0), src2);
			return REPEAT_CSE;
		}
		break;
	}

	switch (DEF_OPCODE(def, src2)) {
	case OP_ADD: case OP_OR: case OP_XOR:
		if ((def->src1 == src1) && can_move_to(cond, def)) {
			// SEL(x, y, OP(y,z)) --> OP(SEL(x, 0, z), y)
			swap_select(insn, def, cond, value_pseudo(0), def->src2, src1);
			return REPEAT_CSE;
		}
		if ((def->src2 == src1) && can_move_to(cond, def)) {
			// SEL(x, y, OP(z,y)) --> OP(SEL(x, 0, z), y)
			swap_select(insn, def, cond, value_pseudo(0), def->src1, src1);
			return REPEAT_CSE;
		}
		break;
	}
	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rdi, %rbx
movq 0x30(%rdi), %r14
movq 0x38(%rdi), %r15
movq 0x40(%rdi), %r12
cmpl $0x6, 0x4(%r14)
jne 0x2784c
cmpq $0x0, 0x18(%r14)
cmoveq %r12, %r15
jmp 0x27ae8
cmpq %r12, %r15
je 0x27ae8
cmpl $0x6, 0x4(%r15)
jne 0x278ac
cmpl $0x6, 0x4(%r12)
jne 0x278ac
movq 0x18(%r15), %rcx
movq 0x18(%r12), %rax
orq %rcx, %rax
cmpq $0x1, %rax
jne 0x2789d
xorl %edx, %edx
testq %rcx, %rcx
setne %dl
cmovneq %r12, %r15
leal (%rdx,%rdx,8), %ecx
movl (%rbx), %edx
andl $-0x80, %edx
addl %edx, %ecx
addl $0x27, %ecx
movl %ecx, (%rbx)
movq 0x18(%rbx), %rcx
movq %rcx, 0x40(%rbx)
movq %r15, 0x38(%rbx)
movl $0x1, %ebp
cmpq $0x1, %rax
je 0x27cd6
cmpq %r12, %r14
jne 0x278c3
cmpl $0x6, 0x4(%r15)
jne 0x278c3
cmpq $0x0, 0x18(%r15)
je 0x27ae8
cmpq %r15, %r14
jne 0x278dc
cmpl $0x6, 0x4(%r12)
jne 0x278dc
cmpq $0x0, 0x18(%r12)
je 0x27b52
cmpl $0x3, 0x4(%r14)
jne 0x278f5
movq 0x18(%r14), %r13
testq %r13, %r13
je 0x278f9
movl (%r13), %eax
andl $0x7f, %eax
jmp 0x278fe
xorl %eax, %eax
jmp 0x278fe
xorl %r13d, %r13d
xorl %eax, %eax
leaq 0x38(%rbx), %rsi
leaq 0x40(%rbx), %rcx
leal -0x27(%rax), %edx
cmpl $0x9, %edx
ja 0x2797e
leaq 0x20907(%rip), %rax     # 0x4821c
movslq (%rax,%rdx,4), %rdx
addq %rax, %rdx
jmpq *%rdx
movq 0x8(%r14), %rdi
movq %rsi, %rbp
movq %r12, (%rsp)
movq %r14, %r12
movq %r13, %r14
movq %rcx, %r13
callq 0x22603
movq %r13, %rcx
movq %r14, %r13
movq %r12, %r14
movq (%rsp), %r12
testb %al, %al
jne 0x27b84
movl (%r13), %eax
movl %eax, %edi
andl $0x7f, %edi
leaq 0x1b2f4(%rip), %rdx     # 0x42c50
movl (%rdx,%rdi,8), %edx
andl $0x7f, %edx
andl $-0x80, %eax
orl %edx, %eax
movl %eax, (%r13)
movq %rbx, %rdi
movq %rbp, %rsi
movq %rbx, %rdx
callq 0x283fe
jmp 0x27cd1
cmpl $0x16, %eax
je 0x279ca
cmpl $0x41, %eax
jne 0x27b84
movq 0x38(%r13), %rax
cmpl $0x6, 0x4(%rax)
jne 0x279ca
movq 0x40(%r13), %rdx
cmpl $0x6, 0x4(%rdx)
jne 0x279ca
leaq 0x30(%rbx), %rbp
cmpq $0x0, 0x18(%rdx)
je 0x27b48
cmpq $0x0, 0x18(%rax)
jne 0x27ae8
movq %rbx, %rdi
movq %rbx, %rdx
callq 0x283fe
jmp 0x27b5a
movq 0x38(%r13), %rax
cmpl $0x6, 0x4(%rax)
jne 0x27b84
movq 0x18(%rax), %rax
leaq -0x1(%rax), %rcx
xorq %rcx, %rax
cmpq %rcx, %rax
jbe 0x27b84
cmpl $0x6, 0x4(%r15)
jne 0x27b84
movq 0x18(%r15), %rax
leaq -0x1(%rax), %rcx
xorq %rcx, %rax
cmpq %rcx, %rax
jbe 0x27b84
cmpl $0x6, 0x4(%r12)
jne 0x27b84
cmpq $0x0, 0x18(%r12)
jne 0x27b84
movl (%r13), %eax
xorl (%rbx), %eax
cmpl $0xff, %eax
ja 0x27b84
movq 0x8(%r14), %rdi
movq %rsi, %rbp
callq 0x22603
testb %al, %al
jne 0x27b84
movq 0x38(%r13), %rax
bsrq 0x18(%rax), %rdi
xorq $0x3f, %rdi
movq (%rbp), %rax
bsrq 0x18(%rax), %rax
xorq $0x3f, %rax
cmpq %rax, %rdi
je 0x27b52
xorl $0x3f, %eax
xorl $0x3f, %edi
movl %edi, %ecx
subl %eax, %ecx
negl %ecx
xorl %edx, %edx
subl %eax, %edi
setb %dl
cmovbl %ecx, %edi
movl (%rbx), %eax
andl $-0x80, %eax
leal (%rax,%rdx,2), %eax
addl $0xf, %eax
movl %eax, (%rbx)
callq 0x136d3
movq %rax, 0x38(%rbx)
jmp 0x27cd1
movq 0x30(%r13), %rax
cmpq %rax, %r15
jne 0x27aab
cmpq 0x38(%r13), %r12
je 0x27abe
cmpq %rax, %r12
jne 0x27b84
cmpq 0x38(%r13), %r15
jne 0x27b84
movq %rbx, %rdi
movq %r12, %rsi
jmp 0x27aee
movq 0x30(%r13), %rax
cmpq %rax, %r15
jne 0x27ad5
cmpq 0x38(%r13), %r12
je 0x27ae8
cmpq %rax, %r12
jne 0x27b84
cmpq 0x38(%r13), %r15
jne 0x27b84
movq %rbx, %rdi
movq %r15, %rsi
callq 0x3c2b1
movq %rbx, %rdi
xorl %esi, %esi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x24adf
movq 0x8(%r14), %rdi
callq 0x22603
testb %al, %al
jne 0x27b84
movq 0x38(%r13), %rax
cmpl $0x6, 0x4(%rax)
jne 0x27b84
cmpq $0x0, 0x18(%rax)
jne 0x27b84
cmpl $0x3, 0x4(%r12)
jne 0x27b6e
movq 0x18(%r12), %rax
testq %rax, %rax
je 0x27b72
movl (%rax), %ecx
andl $0x7f, %ecx
cmpl $0x32, %ecx
sete %cl
jmp 0x27b76
cmpq %rax, %r15
jne 0x27b5a
cmpq %rdx, %r12
jne 0x27b5a
movq %rbx, %rdi
movq %r14, %rsi
jmp 0x27aee
movq 0x30(%r13), %rdx
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x28833
jmp 0x27cd1
xorl %ecx, %ecx
jmp 0x27b76
xorl %eax, %eax
xorl %ecx, %ecx
testb %cl, %cl
je 0x27b84
cmpq %r15, 0x30(%rax)
je 0x27d59
xorl %eax, %eax
cmpl $0x3, 0x4(%r15)
jne 0x27ba4
movq 0x18(%r15), %r13
testq %r13, %r13
je 0x27b9f
movl (%r13), %eax
andl $0x7f, %eax
jmp 0x27ba4
xorl %r13d, %r13d
xorl %eax, %eax
cmpl $0x18, %eax
ja 0x27bec
movl $0x1800100, %ecx        # imm = 0x1800100
btl %eax, %ecx
jae 0x27bec
cmpq %r12, 0x30(%r13)
jne 0x27bce
movq 0x20(%r13), %rax
movq 0x8(%rax), %rdi
callq 0x22603
testb %al, %al
je 0x27c81
cmpq %r12, 0x38(%r13)
jne 0x27bec
movq %r14, %rdi
movq %r13, %rsi
callq 0x28e73
testb %al, %al
je 0x27bec
movq 0x30(%r13), %r15
jmp 0x27cb3
xorl %ebp, %ebp
cmpl $0x3, 0x4(%r12)
movl $0x0, %eax
jne 0x27c13
movq 0x18(%r12), %r13
testq %r13, %r13
je 0x27c0e
movl (%r13), %eax
andl $0x7f, %eax
jmp 0x27c13
xorl %r13d, %r13d
xorl %eax, %eax
cmpl $0x18, %eax
ja 0x27cd6
movl $0x1800100, %ecx        # imm = 0x1800100
btl %eax, %ecx
jae 0x27cd6
cmpq %r15, 0x30(%r13)
jne 0x27c4c
movq %r14, %rdi
movq %r13, %rsi
callq 0x28e73
testb %al, %al
je 0x27c4c
xorl %edi, %edi
callq 0x136d3
movq 0x38(%r13), %r8
jmp 0x27c70
cmpq %r15, 0x38(%r13)
jne 0x27cd6
movq %r14, %rdi
movq %r13, %rsi
callq 0x28e73
testb %al, %al
je 0x27cd6
xorl %edi, %edi
callq 0x136d3
movq 0x30(%r13), %r8
movq %rbx, %rdi
movq %r13, %rsi
movq %r14, %rdx
movq %rax, %rcx
movq %r15, %r9
jmp 0x27ccc
cmpl $0x3, 0x4(%r14)
jne 0x27caf
movq 0x18(%r14), %rcx
cmpq %r13, %rcx
je 0x27bce
movq 0x8(%rcx), %rdi
movq 0x8(%r13), %rsi
cmpq %rsi, %rdi
je 0x27ce7
callq 0x3e021
testb $0x1, %al
je 0x27bce
movq 0x38(%r13), %r15
xorl %edi, %edi
callq 0x136d3
movq %rbx, %rdi
movq %r13, %rsi
movq %r14, %rdx
movq %r15, %rcx
movq %rax, %r8
movq %r12, %r9
callq 0x2a238
movl $0x1, %ebp
movl %ebp, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x28(%rdi), %rdx
testq %rdx, %rdx
je 0x27d44
movq %rdx, %rsi
movl $0x1, %r10d
movzwl (%rsi), %eax
movsbl %al, %edi
testw %di, %di
jle 0x27d36
movzwl %di, %edi
movzwl %ax, %r8d
xorl %r9d, %r9d
movq 0x18(%rsi,%r9,8), %r11
cmpl $0x100, %r8d            # imm = 0x100
jb 0x27d21
testq %r11, %r11
je 0x27d2e
cmpq %rcx, %r11
sete %al
je 0x27d4a
cmpq %r13, %r11
je 0x27d4a
incq %r9
cmpq %r9, %rdi
jne 0x27d0e
movq 0x10(%rsi), %rsi
cmpq %rdx, %rsi
jne 0x27cf9
xorl %r10d, %r10d
jmp 0x27d4a
movl $0x2, %r10d
testb $0x1, %r10b
je 0x27bce
jmp 0x27ca7
movl (%r13), %eax
andl $-0x80, %eax
orl $0x2a, %eax
movl %eax, (%r13)
jmp 0x27cd1