// File: jliesch[P]ofxget/pugixml/pugixml.cpp
// Function: pugi::impl::(anonymous namespace)::xpath_ast_node::optimize_self(pugi::impl::(anonymous namespace)::xpath_allocator*)
void optimize_self(xpath_allocator* alloc)
		{
			// Rewrite [position()=expr] with [expr]
			// Note that this step has to go before classification to recognize [position()=1]
			if ((_type == ast_filter || _type == ast_predicate) &&
				_right->_type == ast_op_equal && _right->_left->_type == ast_func_position && _right->_right->_rettype == xpath_type_number)
			{
				_right = _right->_right;
			}

			// Classify filter/predicate ops to perform various optimizations during evaluation
			if (_type == ast_filter || _type == ast_predicate)
			{
				assert(_test == predicate_default);

				if (_right->_type == ast_number_constant && _right->_data.number == 1.0)
					_test = predicate_constant_one;
				else if (_right->_rettype == xpath_type_number && (_right->_type == ast_number_constant || _right->_type == ast_variable || _right->_type == ast_func_last))
					_test = predicate_constant;
				else if (_right->_rettype != xpath_type_number && _right->is_posinv_expr())
					_test = predicate_posinv;
			}

			// Rewrite descendant-or-self::node()/child::foo with descendant::foo
			// The former is a full form of //foo, the latter is much faster since it executes the node test immediately
			// Do a similar kind of rewrite for self/descendant/descendant-or-self axes
			// Note that we only rewrite positionally invariant steps (//foo[1] != /descendant::foo[1])
			if (_type == ast_step && (_axis == axis_child || _axis == axis_self || _axis == axis_descendant || _axis == axis_descendant_or_self) && _left &&
				_left->_type == ast_step && _left->_axis == axis_descendant_or_self && _left->_test == nodetest_type_node && !_left->_right &&
				is_posinv_step())
			{
				if (_axis == axis_child || _axis == axis_descendant)
					_axis = axis_descendant;
				else
					_axis = axis_descendant_or_self;

				_left = _left->_left;
			}

			// Use optimized lookup table implementation for translate() with constant arguments
			if (_type == ast_func_translate && _right->_type == ast_string_constant && _right->_next->_type == ast_string_constant)
			{
				unsigned char* table = translate_table_generate(alloc, _right->_data.string, _right->_next->_data.string);

				if (table)
				{
					_type = ast_opt_translate_table;
					_data.table = table;
				}
			}

			// Use optimized path for @attr = 'value' or @attr = $value
			if (_type == ast_op_equal &&
				_left->_type == ast_step && _left->_axis == axis_attribute && _left->_test == nodetest_name && !_left->_left && !_left->_right &&
				(_right->_type == ast_string_constant || (_right->_type == ast_variable && _right->_rettype == xpath_type_string)))
			{
				_type = ast_opt_compare_attribute;
			}
		}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x20(%rbp)
movsbl (%rax), %eax
cmpl $0x11, %eax
je 0x5df7c
movq -0x20(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x10, %eax
jne 0x5dfc5
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movsbl (%rax), %eax
cmpl $0x3, %eax
jne 0x5dfc5
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movq 0x8(%rax), %rax
movsbl (%rax), %eax
cmpl $0x16, %eax
jne 0x5dfc5
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movq 0x10(%rax), %rax
movsbl 0x1(%rax), %eax
cmpl $0x2, %eax
jne 0x5dfc5
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rcx
movq 0x10(%rcx), %rcx
movq %rcx, 0x10(%rax)
movq -0x20(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x11, %eax
je 0x5dfe1
movq -0x20(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x10, %eax
jne 0x5e0c3
movq -0x20(%rbp), %rax
movsbl 0x3(%rax), %eax
cmpl $0x0, %eax
jne 0x5dff0
jmp 0x5e00f
leaq 0xfc1f(%rip), %rdi      # 0x6dc16
leaq 0xd357(%rip), %rsi      # 0x6b355
movl $0x2a81, %edx           # imm = 0x2A81
leaq 0xfc27(%rip), %rcx      # 0x6dc31
callq 0x7180
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movsbl (%rax), %eax
cmpl $0x13, %eax
jne 0x5e046
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movsd 0x20(%rax), %xmm0
movsd 0xd2ec(%rip), %xmm1     # 0x6b320
ucomisd %xmm1, %xmm0
jne 0x5e046
jp 0x5e046
movq -0x20(%rbp), %rax
movb $0x3, 0x3(%rax)
jmp 0x5e0c1
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movsbl 0x1(%rax), %eax
cmpl $0x2, %eax
jne 0x5e091
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movsbl (%rax), %eax
cmpl $0x13, %eax
je 0x5e087
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movsbl (%rax), %eax
cmpl $0x14, %eax
je 0x5e087
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movsbl (%rax), %eax
cmpl $0x15, %eax
jne 0x5e091
movq -0x20(%rbp), %rax
movb $0x2, 0x3(%rax)
jmp 0x5e0bf
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movsbl 0x1(%rax), %eax
cmpl $0x2, %eax
je 0x5e0bd
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0x5e2c0
testb $0x1, %al
jne 0x5e0b5
jmp 0x5e0bd
movq -0x20(%rbp), %rax
movb $0x1, 0x3(%rax)
jmp 0x5e0bf
jmp 0x5e0c1
jmp 0x5e0c3
movq -0x20(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x38, %eax
jne 0x5e1a6
movq -0x20(%rbp), %rax
movsbl 0x2(%rax), %eax
cmpl $0x3, %eax
je 0x5e10b
movq -0x20(%rbp), %rax
movsbl 0x2(%rax), %eax
cmpl $0xc, %eax
je 0x5e10b
movq -0x20(%rbp), %rax
movsbl 0x2(%rax), %eax
cmpl $0x4, %eax
je 0x5e10b
movq -0x20(%rbp), %rax
movsbl 0x2(%rax), %eax
cmpl $0x5, %eax
jne 0x5e1a6
movq -0x20(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0x5e1a6
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movsbl (%rax), %eax
cmpl $0x38, %eax
jne 0x5e1a6
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movsbl 0x2(%rax), %eax
cmpl $0x5, %eax
jne 0x5e1a6
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movsbl 0x3(%rax), %eax
cmpl $0x2, %eax
jne 0x5e1a6
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
cmpq $0x0, 0x10(%rax)
jne 0x5e1a6
movq -0x20(%rbp), %rdi
callq 0x5e380
testb $0x1, %al
jne 0x5e16a
jmp 0x5e1a6
movq -0x20(%rbp), %rax
movsbl 0x2(%rax), %eax
cmpl $0x3, %eax
je 0x5e184
movq -0x20(%rbp), %rax
movsbl 0x2(%rax), %eax
cmpl $0x4, %eax
jne 0x5e18e
movq -0x20(%rbp), %rax
movb $0x4, 0x2(%rax)
jmp 0x5e196
movq -0x20(%rbp), %rax
movb $0x5, 0x2(%rax)
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rcx
movq 0x8(%rcx), %rcx
movq %rcx, 0x8(%rax)
movq -0x20(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x2c, %eax
jne 0x5e213
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movsbl (%rax), %eax
cmpl $0x12, %eax
jne 0x5e213
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movq 0x18(%rax), %rax
movsbl (%rax), %eax
cmpl $0x12, %eax
jne 0x5e213
movq -0x20(%rbp), %rax
movq -0x10(%rbp), %rdi
movq 0x10(%rax), %rcx
movq 0x20(%rcx), %rsi
movq 0x10(%rax), %rax
movq 0x18(%rax), %rax
movq 0x20(%rax), %rdx
callq 0x5e430
movq %rax, -0x18(%rbp)
cmpq $0x0, -0x18(%rbp)
je 0x5e211
movq -0x20(%rbp), %rax
movb $0x3a, (%rax)
movq -0x18(%rbp), %rcx
movq %rcx, 0x20(%rax)
jmp 0x5e213
movq -0x20(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x3, %eax
jne 0x5e2ab
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movsbl (%rax), %eax
cmpl $0x38, %eax
jne 0x5e2ab
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movsbl 0x2(%rax), %eax
cmpl $0x2, %eax
jne 0x5e2ab
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movsbl 0x3(%rax), %eax
cmpl $0x1, %eax
jne 0x5e2ab
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
cmpq $0x0, 0x8(%rax)
jne 0x5e2ab
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
cmpq $0x0, 0x10(%rax)
jne 0x5e2ab
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movsbl (%rax), %eax
cmpl $0x12, %eax
je 0x5e2a4
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movsbl (%rax), %eax
cmpl $0x14, %eax
jne 0x5e2ab
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movsbl 0x1(%rax), %eax
cmpl $0x3, %eax
jne 0x5e2ab
movq -0x20(%rbp), %rax
movb $0x3b, (%rax)
addq $0x20, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)