// File: /workspace/github_c_makefile_star2_O0/lucvoo[P]sparse-dev/simplify.c
// Function: simplify_shift
static int simplify_shift(struct instruction *insn, pseudo_t pseudo, long long value)
{
	struct instruction *def;
	unsigned long long mask, omask, nmask;
	unsigned long long nval;
	unsigned int size;
	pseudo_t src2;

	if (!value)
		return replace_with_pseudo(insn, pseudo);
	value = check_shift_count(insn, value);
	if (value < 0)
		return 0;

	size = insn->size;
	switch (insn->opcode) {
	case OP_ASR:
		if (value >= size)
			return 0;
		if (pseudo->type != PSEUDO_REG)
			break;
		def = pseudo->def;
		switch (def->opcode) {
		case OP_LSR:
		case OP_ASR:
			if (def == insn)	// cyclic DAG!
				break;
			src2 = def->src2;
			if (src2->type != PSEUDO_VAL)
				break;
			nval = src2->value;
			if (nval > insn->size || nval == 0)
				break;
			value += nval;
			if (def->opcode == OP_LSR)
				insn->opcode = OP_LSR;
			else if (value >= size)
				value = size - 1;
			goto new_value;

		case OP_ZEXT:
			// transform:
			//	zext.N	%t <- (O) %a
			//	asr.N	%r <- %t, C
			// into
			//	zext.N	%t <- (O) %a
			//	lsr.N	%r <- %t, C
			insn->opcode = OP_LSR;
			return REPEAT_CSE;
		}
		break;
	case OP_LSR:
		size = operand_size(insn, pseudo);
		if (value >= size)
			goto zero;
		switch(DEF_OPCODE(def, pseudo)) {
		case OP_AND:
			// replace (A & M) >> S
			// by      (A >> S) & (M >> S)
			if (!constant(def->src2))
				break;
			mask = bits_mask(insn->size - value) << value;
			omask = def->src2->value;
			nmask = omask & mask;
			if (nmask == 0)
				return replace_with_value(insn, 0);
			if (nmask == mask)
				return replace_pseudo(insn, &insn->src1, def->src1);
			if (!one_use(pseudo))
				break;
			def->opcode = OP_LSR;
			def->src2 = insn->src2;
			insn->opcode = OP_AND;
			insn->src2 = value_pseudo(omask >> value);
			return REPEAT_CSE;
		case OP_LSR:
			goto case_shift_shift;
		case OP_OR:
			mask = bits_mask(size);
			return simplify_mask_shift_or(insn, def, mask);
		case OP_SHL:
			// replace ((x << S) >> S)
			// by      (x & (-1 >> S))
			if (def->src2 != insn->src2)
				break;
			mask = bits_mask(insn->size - value);
			goto replace_mask;
		}
		break;
	case OP_SHL:
		if (value >= size)
			goto zero;
		switch(DEF_OPCODE(def, pseudo)) {
		case OP_AND:
			// simplify (A & M) << S
			if (!constant(def->src2))
				break;
			mask = bits_mask(insn->size) >> value;
			omask = def->src2->value;
			nmask = omask & mask;
			if (nmask == 0)
				return replace_with_value(insn, 0);
			if (nmask == mask)
				return replace_pseudo(insn, &insn->src1, def->src1);
			// do not simplify into ((A << S) & (M << S))
			break;
		case OP_LSR:
			// replace ((x >> S) << S)
			// by      (x & (-1 << S))
			if (def->src2 != insn->src2)
				break;
			mask = bits_mask(insn->size - value) << value;
			goto replace_mask;
		case OP_OR:
			mask = bits_mask(size);
			return simplify_mask_shift_or(insn, def, mask);
		case OP_SHL:
		case_shift_shift:		// also for LSR - LSR
			if (def == insn)	// cyclic DAG!
				break;
			src2 = def->src2;
			if (src2->type != PSEUDO_VAL)
				break;
			nval = src2->value;
			if (nval > insn->size)
				break;
			value += nval;
			goto new_value;
		}
		break;
	}
	return 0;

new_value:
	if (value < size) {
		insn->src2 = value_pseudo(value);
		return replace_pseudo(insn, &insn->src1, pseudo->def->src1);
	}
zero:
	return replace_with_value(insn, 0);
replace_mask:
	insn->opcode = OP_AND;
	insn->src2 = value_pseudo(mask);
	return replace_pseudo(insn, &insn->src1, def->src1);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
jne 0x38ec3
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x357e0
movl %eax, -0x4(%rbp)
jmp 0x39474
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x3ab80
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
jge 0x38ee7
movl $0x0, -0x4(%rbp)
jmp 0x39474
movq -0x10(%rbp), %rax
movl (%rax), %eax
shrl $0x8, %eax
movl %eax, -0x4c(%rbp)
movq -0x10(%rbp), %rax
movl (%rax), %eax
andl $0x7f, %eax
movl %eax, -0x5c(%rbp)
subl $0xf, %eax
je 0x3903a
jmp 0x38f0a
movl -0x5c(%rbp), %eax
subl $0x10, %eax
je 0x38f25
jmp 0x38f14
movl -0x5c(%rbp), %eax
subl $0x11, %eax
je 0x39217
jmp 0x393d4
movq -0x20(%rbp), %rax
movl -0x4c(%rbp), %ecx
cmpq %rcx, %rax
jl 0x38f3d
movl $0x0, -0x4(%rbp)
jmp 0x39474
movq -0x18(%rbp), %rax
cmpl $0x3, 0x4(%rax)
je 0x38f4c
jmp 0x393d4
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
movl (%rax), %eax
andl $0x7f, %eax
movl %eax, -0x60(%rbp)
addl $-0xf, %eax
subl $0x2, %eax
jb 0x38f7f
jmp 0x38f6e
movl -0x60(%rbp), %eax
subl $0x35, %eax
je 0x3901b
jmp 0x39035
movq -0x28(%rbp), %rax
cmpq -0x10(%rbp), %rax
jne 0x38f8e
jmp 0x39035
movq -0x28(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rax
cmpl $0x6, 0x4(%rax)
je 0x38fa9
jmp 0x39035
movq -0x58(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movq -0x10(%rbp), %rcx
movl (%rcx), %ecx
shrl $0x8, %ecx
movl %ecx, %ecx
cmpq %rcx, %rax
ja 0x38fd0
cmpq $0x0, -0x48(%rbp)
jne 0x38fd2
jmp 0x39035
movq -0x48(%rbp), %rax
addq -0x20(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x28(%rbp), %rax
movl (%rax), %eax
andl $0x7f, %eax
cmpl $0xf, %eax
jne 0x38ffc
movq -0x10(%rbp), %rax
movl (%rax), %ecx
andl $-0x80, %ecx
orl $0xf, %ecx
movl %ecx, (%rax)
jmp 0x39016
movq -0x20(%rbp), %rax
movl -0x4c(%rbp), %ecx
cmpq %rcx, %rax
jl 0x39014
movl -0x4c(%rbp), %eax
subl $0x1, %eax
movl %eax, %eax
movq %rax, -0x20(%rbp)
jmp 0x39016
jmp 0x393e0
movq -0x10(%rbp), %rax
movl (%rax), %ecx
andl $-0x80, %ecx
orl $0xf, %ecx
movl %ecx, (%rax)
movl $0x1, -0x4(%rbp)
jmp 0x39474
jmp 0x393d4
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x3ac40
movl %eax, -0x4c(%rbp)
movq -0x20(%rbp), %rax
movl -0x4c(%rbp), %ecx
cmpq %rcx, %rax
jl 0x3905b
jmp 0x39424
movq -0x18(%rbp), %rax
cmpl $0x3, 0x4(%rax)
jne 0x39085
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, %rax
je 0x39085
movq -0x28(%rbp), %rax
movl (%rax), %eax
andl $0x7f, %eax
movl %eax, -0x64(%rbp)
jmp 0x3908c
xorl %eax, %eax
movl %eax, -0x64(%rbp)
jmp 0x3908c
movl -0x64(%rbp), %eax
addl $-0xf, %eax
movl %eax, %ecx
movq %rcx, -0x70(%rbp)
subl $0x8, %eax
ja 0x39212
movq -0x70(%rbp), %rax
leaq 0x2fce8(%rip), %rcx     # 0x68d94
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x28(%rbp), %rax
movq 0x38(%rax), %rdi
callq 0x382a0
cmpl $0x0, %eax
jne 0x390cc
jmp 0x39212
movq -0x10(%rbp), %rax
movl (%rax), %eax
shrl $0x8, %eax
movl %eax, %eax
subq -0x20(%rbp), %rax
movl %eax, %edi
callq 0x3acf0
movq -0x20(%rbp), %rcx
shlq %cl, %rax
movq %rax, -0x30(%rbp)
movq -0x28(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x18(%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
andq -0x30(%rbp), %rax
movq %rax, -0x40(%rbp)
cmpq $0x0, -0x40(%rbp)
jne 0x39125
movq -0x10(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x39480
movl %eax, -0x4(%rbp)
jmp 0x39474
movq -0x40(%rbp), %rax
cmpq -0x30(%rbp), %rax
jne 0x39150
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 0x39474
movq -0x18(%rbp), %rdi
callq 0x3ad20
testb $0x1, %al
jne 0x39162
jmp 0x39212
movq -0x28(%rbp), %rax
movl (%rax), %ecx
andl $-0x80, %ecx
orl $0xf, %ecx
movl %ecx, (%rax)
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x38(%rax)
movq -0x10(%rbp), %rax
movl (%rax), %ecx
andl $-0x80, %ecx
orl $0x16, %ecx
movl %ecx, (%rax)
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rcx
shrq %cl, %rdi
callq 0x1a390
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x38(%rax)
movl $0x1, -0x4(%rbp)
jmp 0x39474
jmp 0x3937e
movl -0x4c(%rbp), %edi
callq 0x3acf0
movq %rax, -0x30(%rbp)
movq -0x10(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x3ad50
movl %eax, -0x4(%rbp)
jmp 0x39474
movq -0x28(%rbp), %rax
movq 0x38(%rax), %rax
movq -0x10(%rbp), %rcx
cmpq 0x38(%rcx), %rax
je 0x391f3
jmp 0x39212
movq -0x10(%rbp), %rax
movl (%rax), %eax
shrl $0x8, %eax
movl %eax, %eax
subq -0x20(%rbp), %rax
movl %eax, %edi
callq 0x3acf0
movq %rax, -0x30(%rbp)
jmp 0x39436
jmp 0x393d4
movq -0x20(%rbp), %rax
movl -0x4c(%rbp), %ecx
cmpq %rcx, %rax
jl 0x39228
jmp 0x39424
movq -0x18(%rbp), %rax
cmpl $0x3, 0x4(%rax)
jne 0x39252
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, %rax
je 0x39252
movq -0x28(%rbp), %rax
movl (%rax), %eax
andl $0x7f, %eax
movl %eax, -0x74(%rbp)
jmp 0x39259
xorl %eax, %eax
movl %eax, -0x74(%rbp)
jmp 0x39259
movl -0x74(%rbp), %eax
addl $-0xf, %eax
movl %eax, %ecx
movq %rcx, -0x80(%rbp)
subl $0x8, %eax
ja 0x393d2
movq -0x80(%rbp), %rax
leaq 0x2faf7(%rip), %rcx     # 0x68d70
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x28(%rbp), %rax
movq 0x38(%rax), %rdi
callq 0x382a0
cmpl $0x0, %eax
jne 0x39299
jmp 0x393d2
movq -0x10(%rbp), %rax
movl (%rax), %edi
shrl $0x8, %edi
callq 0x3acf0
movq -0x20(%rbp), %rcx
shrq %cl, %rax
movq %rax, -0x30(%rbp)
movq -0x28(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x18(%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
andq -0x30(%rbp), %rax
movq %rax, -0x40(%rbp)
cmpq $0x0, -0x40(%rbp)
jne 0x392ea
movq -0x10(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x39480
movl %eax, -0x4(%rbp)
jmp 0x39474
movq -0x40(%rbp), %rax
cmpq -0x30(%rbp), %rax
jne 0x39315
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 0x39474
jmp 0x393d2
movq -0x28(%rbp), %rax
movq 0x38(%rax), %rax
movq -0x10(%rbp), %rcx
cmpq 0x38(%rcx), %rax
je 0x39331
jmp 0x393d2
movq -0x10(%rbp), %rax
movl (%rax), %eax
shrl $0x8, %eax
movl %eax, %eax
subq -0x20(%rbp), %rax
movl %eax, %edi
callq 0x3acf0
movq -0x20(%rbp), %rcx
shlq %cl, %rax
movq %rax, -0x30(%rbp)
jmp 0x39436
movl -0x4c(%rbp), %edi
callq 0x3acf0
movq %rax, -0x30(%rbp)
movq -0x10(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x3ad50
movl %eax, -0x4(%rbp)
jmp 0x39474
jmp 0x3937e
movq -0x28(%rbp), %rax
cmpq -0x10(%rbp), %rax
jne 0x3938a
jmp 0x393d2
movq -0x28(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rax
cmpl $0x6, 0x4(%rax)
je 0x393a2
jmp 0x393d2
movq -0x58(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movq -0x10(%rbp), %rcx
movl (%rcx), %ecx
shrl $0x8, %ecx
movl %ecx, %ecx
cmpq %rcx, %rax
jbe 0x393c4
jmp 0x393d2
movq -0x48(%rbp), %rax
addq -0x20(%rbp), %rax
movq %rax, -0x20(%rbp)
jmp 0x393e0
jmp 0x393d4
movl $0x0, -0x4(%rbp)
jmp 0x39474
movq -0x20(%rbp), %rax
movl -0x4c(%rbp), %ecx
cmpq %rcx, %rax
jge 0x39422
movq -0x20(%rbp), %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 -0x18(%rbp), %rax
movq 0x18(%rax), %rax
movq 0x30(%rax), %rdx
callq 0x38d50
movl %eax, -0x4(%rbp)
jmp 0x39474
jmp 0x39424
movq -0x10(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x39480
movl %eax, -0x4(%rbp)
jmp 0x39474
movq -0x10(%rbp), %rax
movl (%rax), %ecx
andl $-0x80, %ecx
orl $0x16, %ecx
movl %ecx, (%rax)
movq -0x30(%rbp), %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 -0x28(%rbp), %rax
movq 0x30(%rax), %rdx
callq 0x38d50
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x80, %rsp
popq %rbp
retq