// File: /workspace/github_cpp_makefile_star2_O2/eryxcc[P]lois/src/formula.cpp
// Function: lois::FormulaQ::simplify(std::shared_ptr<lois::FormulaQ>)
rbool FormulaQ::simplify(std::shared_ptr<FormulaQ> def) {
  
  using namespace std;
  // we know the value of something, maybe?
  for(size_t i=0; i<var.size(); i++) {
    vptr v = var[i];
    if(!right->uses(v)) {
      var[i] = var[var.size()-1];
      var.pop_back(); i--;
      }
    else {
      term v1 = right->valueKnown(v, type);
      if(v1.p) {
        right = substitute(right, v, v1);
        var[i] = var[var.size()-1];
        var.pop_back(); i--;
        }
      }
    }
  
  // no variables
  if(!var.size()) return right;    
  // quantified true/false
  auto fix = std::dynamic_pointer_cast<FormulaFixed> (right.p);
  if(fix) return right;
  
  /*
  // quantified binary, one side does not use the vars
  auto bin = std::dynamic_pointer_cast<FormulaBi> (right.p);
  if(bin) {
    bool leftuses = false, rightuses = false;
    for(auto v: var) leftuses |= bin->left->uses(v), rightuses |= bin->right->uses(v);

    if(!leftuses && bin->type == true) return bin->left && makeq(type, bin->right, var);
    if(!rightuses && bin->type == true) return bin->right && makeq(type, bin->left, var);
    if(!leftuses && bin->type == false) return bin->left || makeq(type, bin->right, var);
    if(!rightuses && bin->type == false) return bin->right || makeq(type, bin->left, var);
    } */
  
  // quantified (in)equality
  // as long as we assume that !right->unused(all vars),
  // and that they are variables,
  // we know the value
  auto eq = std::dynamic_pointer_cast<FormulaEq> (right.p);
  if(eq && eq->t1.asVar() && eq->t2.asVar()) return type ? ffalse : ftrue;
  
  // take the independent components out of the quantifier
  auto bin = std::dynamic_pointer_cast<FormulaBi> (right.p);
  if(bin) {
    bool btype = bin->type;
    std::vector<rbool> phi;
    std::vector<int> vused;
    decomposeBin(right, btype, phi);
    bool suc = false;
    for(size_t k=0; k<phi.size(); k++) {
      size_t li = 0;
      for(size_t i=0; i<var.size(); i++)
        if(phi[k]->uses(var[i])) li = i+1;
      if(li < var.size()) suc = true;
      vused.push_back(li);
      }
    
    if(suc) {
      for(int k=1; k<phi.size(); ) {
        if(k && vused[k] < vused[k-1]) 
          std::swap(vused[k], vused[k-1]), std::swap(phi[k], phi[k-1]), k--;
        else
          k++;
        }
      
      int at = phi.size()-1;
      rbool nphi = phi[at];
      int lev = vused[at];
  
/*    std::cout << "SIMPLIFYING: ";
      display(std::cout);
      std::cout << std::endl;
      
      for(int k=0; k<phi.size(); k++)
        std::cout << k << "." << vused[k] << ") " << phi[k] << std::endl; */
      
      while(true) {
        at--;
        int nlev = at >= 0 ? vused[at] : 0;
        if(lev > nlev) {
          varlist v;
          while(lev > nlev) { lev--; v.push_back(var[lev]); }
          nphi = makeq(type, nphi, v);
          }
        if(at < 0) {
/*        std::cout << "SIMPLIFIED: ";
          display(std::cout);
          std::cout << " TO: " << nphi << std::endl; */
          return nphi;
          }
        else if(btype) nphi = phi[at] && nphi;
        else nphi = phi[at] || nphi;
        }
      }
    }
  
  return rbool(def);
  }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x178, %rsp            # imm = 0x178
movq %rdx, 0x78(%rsp)
movq %rdi, 0x8(%rsp)
leaq 0x28(%rsi), %rax
movq %rax, 0x58(%rsp)
movq %rsi, 0x10(%rsp)
leaq 0x18(%rsi), %r12
leaq 0x140(%rsp), %rax
movq %rax, 0x18(%rsp)
xorl %r15d, %r15d
movq 0x10(%rsp), %rax
movq 0x28(%rax), %rsi
movq 0x30(%rax), %rax
movq %rax, %rcx
subq %rsi, %rcx
sarq $0x4, %rcx
cmpq %rcx, %r15
jae 0x1fa4b
movq %r15, %rbx
shlq $0x4, %rbx
addq %rbx, %rsi
leaq 0x20(%rsp), %rbp
movq %rbp, %rdi
callq 0x1160e
movq %r12, %r14
movq (%r12), %r12
leaq 0x148(%rsp), %r13
movq %r13, %rdi
movq %rbp, %rsi
callq 0x1160e
movq (%r12), %rax
movq %r12, %rdi
movq %r13, %rsi
callq *0x28(%rax)
movl %eax, %r12d
leaq 0x150(%rsp), %rdi
callq 0xefce
testb %r12b, %r12b
je 0x1fa16
movq %r15, %rbp
movq %r14, %r13
movq 0x10(%rsp), %r14
movq 0x18(%r14), %r12
leaq 0x138(%rsp), %r15
movq %r15, %rdi
leaq 0x20(%rsp), %rsi
callq 0x1160e
movzbl 0x10(%r14), %ecx
movq (%r12), %rax
leaq 0x40(%rsp), %rdi
movq %r12, %rsi
movq %r15, %rdx
callq *0x30(%rax)
leaq 0x140(%rsp), %rdi
callq 0xefce
cmpq $0x0, 0x40(%rsp)
movq %rbp, %r15
leaq 0x60(%rsp), %rbp
je 0x1fa04
leaq 0x128(%rsp), %r14
movq %r14, %rdi
leaq 0x20(%rsp), %rsi
callq 0x1160e
movq %rbp, %rdi
movq %r13, %rsi
movq %r14, %rdx
leaq 0x40(%rsp), %rcx
callq 0x11378
movq %r13, %rdi
movq %rbp, %rsi
callq 0xf3dc
leaq 0x68(%rsp), %rdi
callq 0xefce
leaq 0x130(%rsp), %rdi
callq 0xefce
movq 0x10(%rsp), %rax
movq 0x30(%rax), %rsi
addq $-0x10, %rsi
addq 0x28(%rax), %rbx
movq %rbx, %rdi
callq 0x21ff2
movq 0x58(%rsp), %rdi
callq 0x217ba
decq %r15
movq %r13, %r12
leaq 0x48(%rsp), %rdi
callq 0xefce
incq %r15
jmp 0x1fa3c
movq 0x10(%rsp), %rax
movq 0x30(%rax), %rsi
addq $-0x10, %rsi
addq 0x28(%rax), %rbx
movq %rbx, %rdi
callq 0x21ff2
movq 0x58(%rsp), %rdi
callq 0x217ba
movq %r14, %r12
leaq 0x28(%rsp), %rdi
callq 0xefce
jmp 0x1f8c5
cmpq %rsi, %rax
je 0x1fa7e
leaq 0x118(%rsp), %rbx
movq %rbx, %rdi
movq %r12, %rsi
callq 0x217db
cmpq $0x0, (%rbx)
movq 0x8(%rsp), %r14
je 0x1fa93
movq %r14, %rdi
movq %r12, %rsi
callq 0xf04a
jmp 0x1ff51
movq 0x8(%rsp), %r14
movq %r14, %rdi
movq %r12, %rsi
callq 0xf04a
jmp 0x1ff5e
leaq 0x98(%rsp), %rbx
movq %rbx, %rdi
movq %r12, %rsi
callq 0x21830
movq (%rbx), %rsi
testq %rsi, %rsi
je 0x1fb2c
addq $0x18, %rsi
leaq 0x20(%rsp), %rbx
movq %rbx, %rdi
callq 0x219fe
cmpq $0x0, (%rbx)
je 0x1fb22
movq 0x98(%rsp), %rsi
addq $0x28, %rsi
leaq 0x40(%rsp), %rbx
movq %rbx, %rdi
callq 0x219fe
movq (%rbx), %rbx
leaq 0x48(%rsp), %rdi
callq 0xefce
leaq 0x28(%rsp), %rdi
callq 0xefce
testq %rbx, %rbx
je 0x1fb2c
leaq 0x29cbf(%rip), %rax     # 0x497c0
leaq 0x29ca8(%rip), %rsi     # 0x497b0
movq 0x10(%rsp), %rcx
cmpb $0x0, 0x10(%rcx)
cmovneq %rax, %rsi
movq %r14, %rdi
callq 0xf04a
jmp 0x1ff44
leaq 0x28(%rsp), %rdi
callq 0xefce
leaq 0x108(%rsp), %rbx
movq %rbx, %rdi
movq %r12, %rsi
callq 0x21738
movq (%rbx), %rax
testq %rax, %rax
je 0x1fcff
movb 0x10(%rax), %bpl
xorps %xmm0, %xmm0
leaq 0x20(%rsp), %rbx
movaps %xmm0, (%rbx)
andq $0x0, 0x10(%rbx)
movaps %xmm0, 0x40(%rsp)
andq $0x0, 0x50(%rsp)
leaq 0xf8(%rsp), %r15
movq %r15, %rdi
movq %r12, %rsi
callq 0xf04a
movb %bpl, 0x7(%rsp)
movzbl %bpl, %esi
movq %r15, %rdi
movq %rbx, %rdx
callq 0x1f7ae
leaq 0x100(%rsp), %rdi
callq 0xefce
xorl %ecx, %ecx
leaq 0xe8(%rsp), %r15
xorl %r13d, %r13d
movq 0x20(%rsp), %rsi
movq 0x28(%rsp), %rbp
movq %rbp, %rax
subq %rsi, %rax
sarq $0x4, %rax
cmpq %rax, %r13
jae 0x1fc77
movq %rcx, 0x18(%rsp)
movq %r13, 0x80(%rsp)
shlq $0x4, %r13
pushq $0x1
popq %rbx
xorl %r14d, %r14d
xorl %r12d, %r12d
leaq -0x1(%rbx), %rax
movq 0x10(%rsp), %rcx
movq 0x28(%rcx), %rsi
movq 0x30(%rcx), %rbp
subq %rsi, %rbp
sarq $0x4, %rbp
cmpq %rbp, %rax
jae 0x1fc46
movq 0x20(%rsp), %rax
movq (%rax,%r13), %rbp
addq %r14, %rsi
movq %r15, %rdi
callq 0x1160e
movq (%rbp), %rax
movq %rbp, %rdi
movq %r15, %rsi
callq *0x28(%rax)
movl %eax, %ebp
leaq 0xf0(%rsp), %rdi
callq 0xefce
movq %rbx, %rax
testb %bpl, %bpl
jne 0x1fc3a
movq %r12, %rax
addq $0x10, %r14
incq %rbx
movq %rax, %r12
jmp 0x1fbe2
movl %r12d, 0x60(%rsp)
leaq 0x40(%rsp), %rdi
leaq 0x60(%rsp), %rsi
callq 0x22bc6
cmpq %rbp, %r12
setb %al
movq 0x18(%rsp), %rcx
orb %al, %cl
movq 0x80(%rsp), %r13
incq %r13
jmp 0x1fbab
testb $0x1, %cl
je 0x1fce6
pushq $0x1
popq %rbx
movq 0x8(%rsp), %r14
subq %rsi, %rbp
sarq $0x4, %rbp
movq 0x40(%rsp), %rax
movslq %ebx, %rbx
movq %rbx, %rdi
shlq $0x4, %rdi
addq %rsi, %rdi
cmpq %rbx, %rbp
jbe 0x1fd31
testl %ebx, %ebx
je 0x1fcbc
movl (%rax,%rbx,4), %ecx
leal -0x1(%rbx), %edx
movslq %edx, %rdx
movl (%rax,%rdx,4), %r8d
cmpl %r8d, %ecx
jl 0x1fcc5
incq %rbx
addq $0x10, %rdi
jmp 0x1fc9d
movl %r8d, (%rax,%rbx,4)
movl %ecx, (%rax,%rdx,4)
shlq $0x4, %rdx
addq %rdx, %rsi
callq 0x21885
movq 0x20(%rsp), %rsi
movq 0x28(%rsp), %rbp
decl %ebx
jmp 0x1fc84
leaq 0x40(%rsp), %rdi
callq 0x22b92
leaq 0x20(%rsp), %rdi
callq 0x218c6
movq 0x8(%rsp), %r14
leaq 0x158(%rsp), %rbx
movq %rbx, %rdi
movq 0x78(%rsp), %rsi
callq 0x22d3c
movq %r14, %rdi
movq %rbx, %rsi
callq 0xf04a
leaq 0x160(%rsp), %rdi
callq 0xefce
jmp 0x1ff37
decl %ebp
movslq %ebp, %rbx
movq %rbx, %rax
shlq $0x4, %rax
addq %rax, %rsi
movq %r14, %rdi
callq 0xf04a
movq 0x40(%rsp), %rax
movl (%rax,%rbx,4), %r15d
leaq 0x60(%rsp), %r13
movq %rbp, %r12
decq %rbp
testl %r12d, %r12d
jle 0x1fd6d
movl %ebp, %eax
movq 0x40(%rsp), %rcx
movl (%rcx,%rax,4), %eax
jmp 0x1fd6f
xorl %eax, %eax
cmpl %eax, %r15d
jle 0x1fe26
xorps %xmm0, %xmm0
movaps %xmm0, 0x60(%rsp)
andq $0x0, 0x70(%rsp)
movslq %r15d, %r15
movslq %eax, %rbx
movq %r15, %rsi
shlq $0x4, %rsi
addq $-0x10, %rsi
cmpq %rbx, %r15
jle 0x1fdb8
decq %r15
leaq -0x10(%rsi), %r14
movq 0x58(%rsp), %rax
addq (%rax), %rsi
movq %r13, %rdi
callq 0x11466
movq %r14, %rsi
jmp 0x1fd97
movq 0x10(%rsp), %rax
movzbl 0x10(%rax), %eax
movl %eax, 0x18(%rsp)
leaq 0x88(%rsp), %rdi
movq 0x8(%rsp), %r14
movq %r14, %rsi
callq 0xf04a
leaq 0x168(%rsp), %rbx
movq %rbx, %rdi
movl 0x18(%rsp), %esi
leaq 0x88(%rsp), %rdx
movq %r13, %rcx
callq 0x2008a
movq %r14, %rdi
movq %rbx, %rsi
callq 0xf3dc
leaq 0x170(%rsp), %rdi
callq 0xefce
leaq 0x90(%rsp), %rdi
callq 0xefce
movq %r13, %rdi
callq 0x114e6
testl %r12d, %r12d
jle 0x1ff1e
movl %ebp, %esi
cmpb $0x0, 0x7(%rsp)
je 0x1feab
shlq $0x4, %rsi
addq 0x20(%rsp), %rsi
leaq 0xd8(%rsp), %r14
movq %r14, %rdi
callq 0xf04a
leaq 0xc8(%rsp), %r12
movq %r12, %rdi
movq 0x8(%rsp), %rbx
movq %rbx, %rsi
callq 0xf04a
movq %r13, %rdi
movq %r14, %rsi
movq %r12, %rdx
callq 0x20113
movq %rbx, %rdi
movq %r13, %rsi
callq 0xf3dc
leaq 0x68(%rsp), %rdi
callq 0xefce
leaq 0xd0(%rsp), %rdi
callq 0xefce
leaq 0xe0(%rsp), %rdi
callq 0xefce
jmp 0x1fd56
shlq $0x4, %rsi
addq 0x20(%rsp), %rsi
leaq 0xb8(%rsp), %r14
movq %r14, %rdi
callq 0xf04a
leaq 0xa8(%rsp), %r12
movq %r12, %rdi
movq 0x8(%rsp), %rbx
movq %rbx, %rsi
callq 0xf04a
movq %r13, %rdi
movq %r14, %rsi
movq %r12, %rdx
callq 0x202f9
movq %rbx, %rdi
movq %r13, %rsi
callq 0xf3dc
leaq 0x68(%rsp), %rdi
callq 0xefce
leaq 0xb0(%rsp), %rdi
callq 0xefce
leaq 0xc0(%rsp), %rdi
callq 0xefce
jmp 0x1fd56
leaq 0x40(%rsp), %rdi
callq 0x22b92
leaq 0x20(%rsp), %rdi
callq 0x218c6
movq 0x8(%rsp), %r14
leaq 0x110(%rsp), %rdi
callq 0xefce
leaq 0xa0(%rsp), %rdi
callq 0xefce
leaq 0x120(%rsp), %rdi
callq 0xefce
movq %r14, %rax
addq $0x178, %rsp            # imm = 0x178
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %r14
leaq 0x100(%rsp), %rdi
jmp 0x20033
movq %rax, %r14
leaq 0xb0(%rsp), %rdi
callq 0xefce
leaq 0xc0(%rsp), %rdi
jmp 0x1ffb5
movq %rax, %r14
leaq 0xd0(%rsp), %rdi
callq 0xefce
leaq 0xe0(%rsp), %rdi
callq 0xefce
jmp 0x20006
movq %rax, %r14
leaq 0x90(%rsp), %rdi
callq 0xefce
jmp 0x1fffc
movq %rax, %r14
jmp 0x20038
movq %rax, %r14
leaq 0x130(%rsp), %rdi
callq 0xefce
leaq 0x48(%rsp), %rax
movq %rax, 0x18(%rsp)
jmp 0x1fff2
movq %rax, %r14
movq 0x18(%rsp), %rdi
jmp 0x2001c
movq %rax, %r14
leaq 0x60(%rsp), %rdi
callq 0x114e6
movq 0x8(%rsp), %rdi
addq $0x8, %rdi
jmp 0x20033
movq %rax, %r14
leaq 0x150(%rsp), %rdi
callq 0xefce
leaq 0x28(%rsp), %rdi
jmp 0x2006e
movq %rax, %r14
leaq 0xf0(%rsp), %rdi
callq 0xefce
leaq 0x40(%rsp), %rdi
callq 0x22b92
leaq 0x20(%rsp), %rdi
callq 0x218c6
leaq 0x110(%rsp), %rdi
callq 0xefce
leaq 0xa0(%rsp), %rdi
callq 0xefce
leaq 0x120(%rsp), %rdi
callq 0xefce
movq %r14, %rdi
callq 0x7410
nop