/*OptPass012

Pass #0
When parsing the arg expressions to a function
call, there is a call to OptPass012 to determine
the type of the expression. OptPass012

Pass #1 & #2
Constant expressions are simplified.
Eliminated opcodes are set to NOP.
Types are determined by reconstructing an
expression tree for operators
CIntermediateCode. CICTreeLinks.

Pointer arithmetic size is set, once
the type is determined.

Branches are expressed with short-circuit
logic. 3-Arg comparisons are established.

*/

CIntermediateCode *OptPass012(CCompCtrl *cc)
{/*Simplify CONST arithmetic.
Sets the class throughout Expression trees.
Returns the type of an Expression for use
in int<-->F64 conversions of function args.
*/
    I64                  code, i;
    Bool                 is_unsigned;
    CHashClass          *tmpc, *tmpc1, *tmpc2;
    CIntermediateCode   *tmpi, *tmpi1, *tmpi2, *tmpi3, *tmpi_push, *last_with_class = NULL;
    CCodeMisc           *lb, *lb1, *lb2;
    CParseStack         *ps;

    if (!(ps = cc->ps))
        ps = cc->ps = MAlloc(sizeof(CParseStack));
    ps->ptr = 0;
    ps->ptr2 = 0;
    tmpi = cc->coc.coc_head.next;
    while (code = tmpi->ic_code)
    {
        tmpc = tmpi->ic_class;
        tmpi->ic_class2 = tmpc;
        tmpi_push = tmpi;
        MemSet(&tmpi->arg1, 0, 3 * sizeof(CICArg));
        tmpi->arg1_type_pointed_to = 0;
        switch [intermediate_code_table[code].arg_count]
        {
            case IS_V_ARG:
                ps->ptr -= tmpi->ic_data >> 2;
                break;

            case IS_2_ARG:
                tmpi2 = ParsePop(ps);
                tmpc2 = tmpi2->ic_class;
                tmpi->t.arg2_tree = tmpi2;
                tmpi->t.arg2_class = ParsePop(ps);

            case IS_1_ARG:
                tmpi1 = ParsePop(ps);
                tmpc1 = tmpi1->ic_class;
                tmpi->t.arg1_tree = tmpi1;
                tmpi->t.arg1_class = ParsePop(ps);
                break;

            case IS_0_ARG: //nobound switch
                break;
        }
        if (intermediate_code_table[code].not_const)
            cc->flags |= CCF_NOT_CONST;
        switch [code]
        {
            case IC_IMM_F64:
                tmpi->ic_flags &= ~ICF_RES_TO_F64;
                if (cc->pass == 2 && tmpi->ic_flags & ICF_RES_TO_INT)
                {
                    tmpi->ic_data = ToI64(tmpi->ic_data(F64));
                    tmpi->ic_flags &= ~ICF_RES_TO_INT;
                    tmpi->ic_code = IC_IMM_I64;
                    tmpi->ic_class = cmp.internal_types[RT_I64];
                }
                break;

            case IC_IMM_I64:
                tmpi->ic_flags &= ~ICF_RES_TO_INT;
                if (cc->pass == 2 && tmpi->ic_flags & ICF_RES_TO_F64)
                {
                    tmpi->ic_data(F64) = ToF64(tmpi->ic_data);
                    tmpi->ic_flags &= ~ICF_RES_TO_F64;
                    tmpi->ic_code = IC_IMM_F64;
                    tmpi->ic_class = cmp.internal_types[RT_F64];
                }
                break;

            case IC_POSTFIX_TYPECAST:
                if (tmpi1->ic_code == IC_IMM_I64 || tmpi1->ic_code == IC_IMM_F64)
                {
                    if (tmpi->ic_class->raw_type == RT_F64)
                        tmpi1->ic_code = IC_IMM_F64;
                    else
                        tmpi1->ic_code = IC_IMM_I64;
                    tmpi1->ic_class = tmpi->ic_class;
                    tmpi1->ic_flags |= tmpi->ic_flags;
                    tmpi_push = tmpi1;
                    OptSetNOP1(tmpi);
                }
                else
                {
                    if (tmpi->ic_data)
                    {//was paren
                        if (!tmpi_push->ic_class->ptr_stars_count)
                        {
                            if (tmpi_push->ic_class->raw_type == RT_F64)
                                tmpi_push->ic_class2 = cmp.internal_types[RT_F64];
                            else
                                tmpi_push->ic_class2 = cmp.internal_types[RT_I64];
                        }
                    }
                    else
                    {
                        tmpi1->ic_class = tmpi->ic_class;
                        tmpi1->ic_flags |= tmpi->ic_flags;
                        tmpi_push = tmpi1;
                        OptSetNOP1(tmpi);
                    }
                }
                break;

            case IC_FS:
            case IC_GS:
//CALL,FS/GS,CALL_END,IMM,ADD,DEREF-->MOV_FS/GS
                tmpi1 = tmpi->next->next; //IMM
                tmpi2 = tmpi1->next; //ADD
                tmpi3 = tmpi2->next; //DEREF
                if (tmpi1->ic_code == IC_IMM_I64 && tmpi2->ic_code == IC_ADD && tmpi3->ic_code == IC_DEREF &&
                    !(tmpi3->ic_flags & ~ICG_NO_CONVERT_MASK))
                {
                    tmpi->ic_flags |= tmpi1->ic_flags | tmpi2->ic_flags | tmpi3->ic_flags;
                    if (tmpi->ic_code == IC_FS)
                        tmpi->ic_code = IC_MOV_FS;
                    else
                        tmpi->ic_code = IC_MOV_GS;
                    tmpi->ic_data = tmpi1->ic_data;
                    tmpi->ic_class  = tmpi3->ic_class;
                    tmpi->ic_class2 = tmpi3->ic_class2;
                    OptSetNOP1(tmpi1);
                    OptSetNOP1(tmpi2);
                    OptSetNOP1(tmpi3);

                    tmpi1 = tmpi->last; //CALL
                    tmpi2 = tmpi->next; //CALL_END
                    tmpi->ic_flags |= tmpi1->ic_flags | tmpi2->ic_flags;
                    OptSetNOP1(tmpi1);
                    OptSetNOP1(tmpi2);
                }
                break;

            case IC_PUSH_CMP:
                if (tmpi1 = OptLag(tmpi))
                {
                    if (tmpi1->ic_code == IC_AND_AND)
                        tmpi1 = OptLag(tmpi1);
                    if (tmpi1)
                        tmpi->ic_class = tmpi1->ic_class;
                }
                tmpi->ic_class2 = tmpi->ic_class;
                tmpi->ic_data = 0;
                if (tmpi->ic_class->raw_type == RT_F64)
                    tmpi->ic_flags |= ICF_USE_F64;
                break;

            case IC_COM:
                if (tmpi1->ic_code == IC_IMM_I64)
                {
                    tmpi->ic_data = ~tmpi1->ic_data;
                    tmpi->ic_code = IC_IMM_I64;
                    tmpi->ic_flags |= tmpi1->ic_flags;
                    OptSetNOP1(tmpi1);
                }
                tmpi_push->ic_class2 = cmp.internal_types[RT_I64];
                break;
            start:
                case IC_NOT:
                    if (tmpc->raw_type == RT_F64)
                    {
                        if (tmpi1->ic_code == IC_IMM_F64) {
                            tmpi->ic_data(F64) = !tmpi1->ic_data(F64);
                            tmpi->ic_code = IC_IMM_F64;
                            tmpi->ic_flags |= tmpi1->ic_flags;
                            OptSetNOP1(tmpi1);
                        }
                        break;
                    }
                    if (tmpi1->ic_code == IC_IMM_I64)
                    {
                        tmpi->ic_data = !tmpi1->ic_data;
                        tmpi->ic_code = IC_IMM_I64;
                        tmpi->ic_flags |= tmpi1->ic_flags;
                        OptSetNOP1(tmpi1);
                    }
                    break;

                case IC_UNARY_MINUS:
                    if (i = OptFixupUnaryOp(tmpi, tmpi1, &is_unsigned))
                    {
                        if (i == FBO1_INT)
                        {
                            tmpi->ic_data = -tmpi1->ic_data(I64);
                            tmpi->ic_code = IC_IMM_I64;
                        }
                        else
                        {
                            tmpi->ic_data(F64) = -tmpi1->ic_data(F64);
                            tmpi->ic_code = IC_IMM_F64;
                        }
                    }
                    if (tmpc1->type & HTT_INTERNAL_TYPE && tmpc1->raw_type & RTF_UNSIGNED)
                        tmpi->ic_class = cmp.internal_types[tmpc1->raw_type - 1];
                    break;

                case IC_SHL_CONST:
                    if (i = OptFixupUnaryOp(tmpi, tmpi1, &is_unsigned))
                    {
                        if (i == FBO1_INT)
                        {
                            if (is_unsigned)
                                tmpi->ic_data = tmpi1->ic_data(U64) << tmpi->ic_data(U64);
                            else
                                tmpi->ic_data = tmpi1->ic_data(I64) << tmpi->ic_data(I64);
                            tmpi->ic_code=IC_IMM_I64;
                        }
                        else
                        {
                            tmpi->ic_data(F64) = tmpi1->ic_data(F64) << tmpi->ic_data;
                            tmpi->ic_code = IC_IMM_F64;
                        }
                    }
                    else if (tmpi1->ic_code == IC_SHL_CONST)
                    {
                        tmpi->ic_flags |= tmpi1->ic_flags;
                        tmpi->ic_data += tmpi1->ic_data;
                        OptSetNOP1(tmpi1);
                    }
                    break;

                case IC_SHR_CONST:
                    if (i = OptFixupUnaryOp(tmpi, tmpi1, &is_unsigned))
                    {
                        if (i == FBO1_INT)
                        {
                            if (is_unsigned)
                                tmpi->ic_data = tmpi1->ic_data(U64) >> tmpi->ic_data(U64);
                            else
                                tmpi->ic_data = tmpi1->ic_data(I64) >> tmpi->ic_data(I64);
                            tmpi->ic_code = IC_IMM_I64;
                        }
                        else
                        {
                            tmpi->ic_data(F64) = tmpi1->ic_data(F64) >> tmpi->ic_data;
                            tmpi->ic_code = IC_IMM_F64;
                        }
                    }
                    else if (tmpi1->ic_code == IC_SHR_CONST)
                    {
                        tmpi->ic_flags |= tmpi1->ic_flags;
                        tmpi->ic_data += tmpi1->ic_data;
                        OptSetNOP1(tmpi1);
                    }
                    break;

                case IC_SHL:
                    if (i = OptFixupBinaryOp1(tmpi, tmpi1, tmpi2, &is_unsigned))
                    {
                        if (i == FBO1_INT)
                        {
                            if (is_unsigned)
                                tmpi->ic_data = tmpi1->ic_data(U64) << tmpi2->ic_data(U64);
                            else
                                tmpi->ic_data = tmpi1->ic_data(I64) << tmpi2->ic_data(I64);
                            tmpi->ic_code = IC_IMM_I64;
                        }
                        else
                        {
                            tmpi->ic_data(F64) = tmpi1->ic_data(F64) << tmpi2->ic_data(F64);
                            tmpi->ic_code = IC_IMM_F64;
                        }
                    }
                    else if (tmpi2->ic_code == IC_IMM_I64)
                    {
                        tmpi->ic_flags |= tmpi2->ic_flags;
                        tmpi->ic_data = tmpi2->ic_data;
                        tmpi->ic_code = IC_SHL_CONST;
                        OptSetNOP1(tmpi2);
                    }
                    break;

                case IC_SHR:
                    if (i = OptFixupBinaryOp1(tmpi, tmpi1, tmpi2, &is_unsigned))
                    {
                        if (i == FBO1_INT)
                        {
                            if (is_unsigned)
                                tmpi->ic_data = tmpi1->ic_data(U64) >> tmpi2->ic_data(U64);
                            else
                                tmpi->ic_data = tmpi1->ic_data(I64) >> tmpi2->ic_data(I64);
                            tmpi->ic_code=IC_IMM_I64;
                        }
                        else
                        {
                            tmpi->ic_data(F64) = tmpi1->ic_data(F64) >> tmpi2->ic_data(F64);
                            tmpi->ic_code = IC_IMM_F64;
                        }
                    }
                    else if (tmpi2->ic_code == IC_IMM_I64)
                    {
                        tmpi->ic_flags |= tmpi2->ic_flags;
                        tmpi->ic_data = tmpi2->ic_data;
                        tmpi->ic_code = IC_SHR_CONST;
                        OptSetNOP1(tmpi2);
                    }
                    break;
            end:
                if (!tmpi_push->ic_class->ptr_stars_count)
                {
                    if (tmpi_push->ic_class->raw_type == RT_F64)
                        tmpi_push->ic_class2 = cmp.internal_types[RT_F64];
                    else
                        tmpi_push->ic_class2 = cmp.internal_types[RT_I64];
                }
                break;

            case IC_DEREF:
                if (cc->pass == 2)
                {
                    if (!tmpc->size)
                        LexWarn(cc, "Dereference U0 ");
                    if (tmpi1->ic_class->raw_type != RT_F64)
                    {
                        if (tmpi1->ic_code == IC__PP)
                        {
                            tmpi->ic_code = IC_DEREF_PP;
                            tmpi->ic_flags |= tmpi1->ic_flags;
                            OptSetNOP1(tmpi1);
                        }
                        else if (tmpi1->ic_code == IC__MM)
                        {
                            tmpi->ic_code = IC_DEREF_MM;
                            tmpi->ic_flags |= tmpi1->ic_flags;
                            OptSetNOP1(tmpi1);
                        }
                    }
                }
                break;

            case IC__PP:
            case IC__MM:
            case IC_PP_:
            case IC_MM_:
                if (cc->pass == 2 && !tmpc->size)
                    LexWarn(cc, "Dereference U0 ");
                break;

            case IC_POWER:
                tmpc = tmpi->ic_class = cmp.internal_types[RT_F64];
                if (tmpc1->raw_type != RT_F64)
                    tmpi1->ic_flags |= ICF_RES_TO_F64;
                if (tmpc2->raw_type != RT_F64)
                    tmpi2->ic_flags |= ICF_RES_TO_F64;
                tmpi_push->ic_class2 = cmp.internal_types[RT_F64];
                break;
            start:
                case IC_MUL:
                    if (i = OptFixupBinaryOp1(tmpi, tmpi1, tmpi2, &is_unsigned))
                    {
                        if (i == FBO1_INT)
                        {
                            if (is_unsigned)
                                tmpi->ic_data = tmpi1->ic_data(U64) * tmpi2->ic_data(U64);
                            else
                                tmpi->ic_data = tmpi1->ic_data(I64) * tmpi2->ic_data(I64);
                            tmpi->ic_code = IC_IMM_I64;
                        }
                        else
                        {
                            tmpi->ic_data(F64) = tmpi1->ic_data(F64) * tmpi2->ic_data(F64);
                            tmpi->ic_code = IC_IMM_F64;
                        }
                    }
                    else
                    {
                        if (tmpi1->ic_code == IC_IMM_I64 && cc->pass == 2)
                        {
                            switch (i = tmpi1->ic_data)
                            {
                                case 0:
                                    break;

                                case 1:
                                    tmpi2->ic_flags |= tmpi->ic_flags | tmpi1->ic_flags;
                                    tmpi2->ic_class2 = tmpi->ic_class2;
                                    tmpi_push = tmpi2;
                                    OptSetNOP1(tmpi1);
                                    OptSetNOP1(tmpi);
                                    break;

                                default:
                                    if (Bsf(i) == Bsr(i))
                                    {
                                        tmpi->ic_flags |= tmpi1->ic_flags;
                                        tmpi->t.arg1_class = tmpi->t.arg2_class;
                                        tmpi->ic_data = Bsf(i);
                                        tmpi->ic_code = IC_SHL_CONST;
                                        OptSetNOP1(tmpi1);
                                    }
                            }
                        }
                        else if (tmpi2->ic_code == IC_IMM_I64)
                        {
                            switch (i = tmpi2->ic_data)
                            {
                                case 0:
                                    break;

                                case 1:
                                    tmpi1->ic_flags |= tmpi->ic_flags | tmpi2->ic_flags;
                                    tmpi1->ic_class2 = tmpi->ic_class2;
                                    tmpi_push = tmpi1;
                                    OptSetNOP1(tmpi2);
                                    OptSetNOP1(tmpi);
                                    break;

                                default:
                                    if (Bsf(i) == Bsr(i))
                                    {
                                        tmpi->ic_flags |= tmpi2->ic_flags;
                                        tmpi->ic_data = Bsf(i);
                                        tmpi->ic_code = IC_SHL_CONST;
                                        OptSetNOP1(tmpi2);
                                    }
                                    else if (tmpi1->ic_code == IC_MUL && cc->pass == 2)
                                    {
                                        if (tmpi1->t.arg1_tree->ic_code == IC_IMM_I64)
                                        {
                                            tmpi1->ic_flags |= tmpi->ic_flags;
                                            tmpi1->t.arg1_tree->ic_data *= tmpi2->ic_data;
                                            tmpi1->ic_class2 = tmpi->ic_class2;
                                            tmpi_push = tmpi1;
                                            OptSetNOP1(tmpi2);
                                            OptSetNOP1(tmpi);
                                        }
                                        else if (tmpi1->t.arg2_tree->ic_code == IC_IMM_I64)
                                        {
                                            tmpi1->ic_flags |= tmpi->ic_flags;
                                            tmpi1->t.arg2_tree->ic_data *= tmpi2->ic_data;
                                            tmpi1->ic_class2 = tmpi->ic_class2;
                                            tmpi_push = tmpi1;
                                            OptSetNOP1(tmpi2);
                                            OptSetNOP1(tmpi);
                                        }
                                    }
                            }
                        }
                        else if (tmpi2->ic_code == IC_IMM_F64 && cc->pass == 2)
                        {
                            if (tmpi2->ic_data(F64) == 1.0)
                            {
                                tmpi1->ic_flags |= tmpi->ic_flags | tmpi2->ic_flags;
                                tmpi1->ic_class2 = tmpi->ic_class2;
                                tmpi_push = tmpi1;
                                OptSetNOP1(tmpi2);
                                OptSetNOP1(tmpi);
                            }
                            else if (tmpi1->ic_code == IC_MUL)
                            {
                                if (tmpi1->t.arg1_tree->ic_code == IC_IMM_F64)
                                {
                                    tmpi1->ic_flags |= tmpi->ic_flags | tmpi2->ic_flags;
                                    tmpi1->t.arg1_tree->ic_data(F64) *= tmpi2->ic_data(F64);
                                    tmpi1->ic_class2 = tmpi->ic_class2;
                                    tmpi_push = tmpi1;
                                    OptSetNOP1(tmpi2);
                                    OptSetNOP1(tmpi);
                                }
                                else if (tmpi1->t.arg2_tree->ic_code == IC_IMM_F64)
                                {
                                    tmpi1->ic_flags |= tmpi->ic_flags | tmpi2->ic_flags;
                                    tmpi1->t.arg2_tree->ic_data(F64) *= tmpi2->ic_data(F64);
                                    tmpi1->ic_class2 = tmpi->ic_class2;
                                    tmpi_push = tmpi1;
                                    OptSetNOP1(tmpi2);
                                    OptSetNOP1(tmpi);
                                }
                            }
                        }
                    }
                    break;

                case IC_DIV:
                    if ((tmpi2->ic_data || tmpi2->ic_code != IC_IMM_I64 && tmpi2->ic_code != IC_IMM_F64) &&
                        (i = OptFixupBinaryOp1(tmpi, tmpi1, tmpi2, &is_unsigned)))
                    {
                        if (i == FBO1_INT)
                        {
                            if (is_unsigned)
                                tmpi->ic_data = tmpi1->ic_data(U64) / tmpi2->ic_data(U64);
                            else
                                tmpi->ic_data = tmpi1->ic_data(I64) / tmpi2->ic_data(I64);
                            tmpi->ic_code = IC_IMM_I64;
                        }
                        else
                        {
                            tmpi->ic_data(F64) = tmpi1->ic_data(F64) / tmpi2->ic_data(F64);
                            tmpi->ic_code = IC_IMM_F64;
                        }
                    }
                    else
                    {
                        if (tmpi2->ic_code == IC_IMM_I64 && (i = tmpi2->ic_data))
                        {
                            if (i == 1)
                            {
                                tmpi1->ic_flags |= tmpi2->ic_flags | tmpi->ic_flags;
                                tmpi1->ic_class2 = tmpi->ic_class2;
                                tmpi_push = tmpi1;
                                OptSetNOP1(tmpi2);
                                OptSetNOP1(tmpi);
                            }
                            else if (Bsf(i) == Bsr(i))
                            {
                                tmpi->ic_flags |= tmpi2->ic_flags;
                                tmpi->ic_data = Bsf(i);
                                tmpi->ic_code = IC_SHR_CONST;
                                OptSetNOP1(tmpi2);
                            }
                        }
                    }
                    break;

                case IC_MOD:
                    if ((tmpi2->ic_data || tmpi2->ic_code != IC_IMM_I64 && tmpi2->ic_code != IC_IMM_F64) &&
                        (i = OptFixupBinaryOp1(tmpi, tmpi1, tmpi2, &is_unsigned)))
                    {
                        if (i == FBO1_INT)
                        {
                            if (is_unsigned)
                                tmpi->ic_data = tmpi1->ic_data(U64) % tmpi2->ic_data(U64);
                            else
                                tmpi->ic_data = tmpi1->ic_data(I64) % tmpi2->ic_data(I64);
                            tmpi->ic_code=IC_IMM_I64;
                        }
                        else
                        {
                            tmpi->ic_data(F64) = tmpi1->ic_data(F64) % tmpi2->ic_data(F64);
                            tmpi->ic_code = IC_IMM_F64;
                        }
                    }
                    else if (cc->pass == 2 && tmpi2->ic_code == IC_IMM_I64 && (i = tmpi2->ic_data) && Bsf(i)==Bsr(i) &&
                            tmpi_push->ic_class->raw_type != RT_F64 && tmpi_push->ic_class->raw_type & RTF_UNSIGNED)
                    {//do only unsigned
                        tmpi2->ic_data = i - 1;
                        tmpi->ic_code = IC_AND;
                    }
                    break;

                case IC_AND:
                    if (i = OptFixupBinaryOp1(tmpi, tmpi1, tmpi2, &is_unsigned))
                    {
                        tmpi->ic_data = tmpi1->ic_data & tmpi2->ic_data;
                        if (i == FBO1_INT)
                            tmpi->ic_code = IC_IMM_I64;
                        else
                            tmpi->ic_code = IC_IMM_F64;
                    }
                    break;

                case IC_OR:
                    if (i = OptFixupBinaryOp1(tmpi, tmpi1, tmpi2, &is_unsigned))
                    {
                        tmpi->ic_data = tmpi1->ic_data | tmpi2->ic_data;
                        if (i == FBO1_INT)
                            tmpi->ic_code = IC_IMM_I64;
                        else
                            tmpi->ic_code = IC_IMM_F64;
                    }
                    break;

                case IC_XOR:
                    if (i = OptFixupBinaryOp1(tmpi, tmpi1, tmpi2, &is_unsigned))
                    {
                        tmpi->ic_data = tmpi1->ic_data ^ tmpi2->ic_data;
                        if (i == FBO1_INT)
                            tmpi->ic_code = IC_IMM_I64;
                        else
                            tmpi->ic_code = IC_IMM_F64;
                    }
                    break;

                case IC_ADD:
                    if (i = OptFixupBinaryOp1(tmpi, tmpi1, tmpi2, &is_unsigned))
                    {
                        if (i == FBO1_INT)
                        {
                            tmpi->ic_data = tmpi1->ic_data + tmpi2->ic_data;
                            tmpi->ic_code = IC_IMM_I64;
                        }
                        else
                        {
                            tmpi->ic_data(F64) = tmpi1->ic_data(F64) + tmpi2->ic_data(F64);
                            tmpi->ic_code = IC_IMM_F64;
                        }
                    }
                    else
                    {
                        if (tmpi1->ic_code == IC_ABS_ADDR && tmpi2->ic_code == IC_IMM_I64)
                        {
                            tmpi->ic_flags |= tmpi1->ic_flags | tmpi2->ic_flags;
                            tmpi->ic_data = tmpi1->ic_data + tmpi2->ic_data;
                            tmpi->ic_code = IC_ABS_ADDR;
                            OptSetNOP1(tmpi1);
                            OptSetNOP1(tmpi2);
                        }
                        else if (cc->pass == 2)
                        {
                            if (tmpi1->ic_code == IC_IMM_I64)
                            {
                                if (!tmpi1->ic_data)
                                {
                                    tmpi2->ic_flags |= tmpi1->ic_flags | tmpi->ic_flags;
                                    tmpi2->ic_class2 = tmpi->ic_class2;
                                    tmpi_push = tmpi2;
                                    OptSetNOP1(tmpi1);
                                    OptSetNOP1(tmpi);
                                }
                                else if (tmpi2->ic_code == IC_ADD || tmpi2->ic_code == IC_SUB)
                                {
                                    if (tmpi2->t.arg1_tree->ic_code == IC_IMM_I64)
                                    {
                                        tmpi2->ic_flags |= tmpi->ic_flags;
                                        tmpi2->t.arg1_tree->ic_data += tmpi1->ic_data;
                                        tmpi2->ic_class2 = tmpi->ic_class2;
                                        tmpi_push = tmpi2;
                                        OptSetNOP1(tmpi1);
                                        OptSetNOP1(tmpi);
                                    }
                                    else if (tmpi2->t.arg2_tree->ic_code == IC_IMM_I64)
                                    {
                                        tmpi2->ic_flags |= tmpi->ic_flags;
                                        if (tmpi2->ic_code == IC_ADD)
                                            tmpi2->t.arg2_tree->ic_data += tmpi1->ic_data;
                                        else
                                            tmpi2->t.arg2_tree->ic_data -= tmpi1->ic_data;
                                        tmpi2->ic_class2 = tmpi->ic_class2;
                                        tmpi_push = tmpi2;
                                        OptSetNOP1(tmpi1);
                                        OptSetNOP1(tmpi);
                                    }
                                }
                            }
                            else if (tmpi2->ic_code == IC_IMM_I64)
                            {
                                if (!tmpi2->ic_data)
                                {
                                    tmpi1->ic_flags |= tmpi2->ic_flags | tmpi->ic_flags;
                                    tmpi1->ic_class2 = tmpi->ic_class2;
                                    tmpi_push = tmpi1;
                                    OptSetNOP1(tmpi2);
                                    OptSetNOP1(tmpi);
                                }
                                else if (tmpi1->ic_code == IC_ADD || tmpi1->ic_code == IC_SUB)
                                {
                                    if (tmpi1->t.arg1_tree->ic_code == IC_IMM_I64)
                                    {
                                        tmpi1->ic_flags |= tmpi->ic_flags;
                                        tmpi1->t.arg1_tree->ic_data += tmpi2->ic_data;
                                        tmpi1->ic_class2 = tmpi->ic_class2;
                                        tmpi_push = tmpi1;
                                        OptSetNOP1(tmpi2);
                                        OptSetNOP1(tmpi);
                                    }
                                    else if (tmpi1->t.arg2_tree->ic_code == IC_IMM_I64)
                                    {
                                        tmpi1->ic_flags |= tmpi->ic_flags;
                                        if (tmpi1->ic_code == IC_ADD)
                                            tmpi1->t.arg2_tree->ic_data += tmpi2->ic_data;
                                        else
                                            tmpi1->t.arg2_tree->ic_data -= tmpi2->ic_data;
                                        tmpi1->ic_class2 = tmpi->ic_class2;
                                        tmpi_push = tmpi1;
                                        OptSetNOP1(tmpi2);
                                        OptSetNOP1(tmpi);
                                    }
                                }
                            }
                            else if (tmpi1->ic_code == IC_IMM_F64)
                            {
                                if (!tmpi1->ic_data)
                                {
                                    tmpi2->ic_flags |= tmpi1->ic_flags | tmpi->ic_flags;
                                    tmpi2->ic_class2 = tmpi->ic_class2;
                                    tmpi_push = tmpi2;
                                    OptSetNOP1(tmpi1);
                                    OptSetNOP1(tmpi);
                                }
                                else if (tmpi2->ic_code == IC_ADD || tmpi2->ic_code == IC_SUB)
                                {
                                    if (tmpi2->t.arg1_tree->ic_code == IC_IMM_F64)
                                    {
                                        tmpi2->ic_flags |= tmpi->ic_flags;
                                        tmpi2->t.arg1_tree->ic_data(F64) += tmpi1->ic_data(F64);
                                        tmpi2->ic_class2 = tmpi->ic_class2;
                                        tmpi_push = tmpi2;
                                        OptSetNOP1(tmpi1);
                                        OptSetNOP1(tmpi);
                                    }
                                    else if (tmpi2->t.arg2_tree->ic_code == IC_IMM_F64)
                                    {
                                        tmpi2->ic_flags |= tmpi->ic_flags;
                                        if (tmpi2->ic_code == IC_ADD)
                                            tmpi2->t.arg2_tree->ic_data(F64) += tmpi1->ic_data(F64);
                                        else
                                            tmpi2->t.arg2_tree->ic_data(F64) -= tmpi1->ic_data(F64);
                                        tmpi2->ic_class2 = tmpi->ic_class2;
                                        tmpi_push = tmpi2;
                                        OptSetNOP1(tmpi1);
                                        OptSetNOP1(tmpi);
                                    }
                                }
                            }
                            else if (tmpi2->ic_code == IC_IMM_F64)
                            {
                                if (!tmpi2->ic_data)
                                {
                                    tmpi1->ic_flags |= tmpi2->ic_flags | tmpi->ic_flags;
                                    tmpi1->ic_class2 = tmpi->ic_class2;
                                    tmpi_push = tmpi1;
                                    OptSetNOP1(tmpi2);
                                    OptSetNOP1(tmpi);
                                }
                                else if (tmpi1->ic_code == IC_ADD || tmpi1->ic_code == IC_SUB)
                                {
                                    if (tmpi1->t.arg1_tree->ic_code == IC_IMM_F64)
                                    {
                                        tmpi1->ic_flags |= tmpi->ic_flags;
                                        tmpi1->t.arg1_tree->ic_data(F64) += tmpi2->ic_data(F64);
                                        tmpi1->ic_class2 = tmpi->ic_class2;
                                        tmpi_push = tmpi1;
                                        OptSetNOP1(tmpi2);
                                        OptSetNOP1(tmpi);
                                    }
                                    else if (tmpi1->t.arg2_tree->ic_code == IC_IMM_F64)
                                    {
                                        tmpi1->ic_flags |= tmpi->ic_flags;
                                        if (tmpi1->ic_code == IC_ADD)
                                            tmpi1->t.arg2_tree->ic_data(F64) += tmpi2->ic_data(F64);
                                        else
                                            tmpi1->t.arg2_tree->ic_data(F64) -= tmpi2->ic_data(F64);
                                        tmpi1->ic_class2 = tmpi->ic_class2;
                                        tmpi_push = tmpi1;
                                        OptSetNOP1(tmpi2);
                                        OptSetNOP1(tmpi);
                                    }
                                }
                            }
                        }
                    }
                    break;

                case IC_SUB:
                    if (i = OptFixupBinaryOp1(tmpi, tmpi1, tmpi2, &is_unsigned))
                    {
                        if (i == FBO1_INT)
                        {
                            tmpi->ic_data = tmpi1->ic_data - tmpi2->ic_data;
                            tmpi->ic_code = IC_IMM_I64;
                        }
                        else
                        {
                            tmpi->ic_data(F64) = tmpi1->ic_data(F64) - tmpi2->ic_data(F64);
                            tmpi->ic_code = IC_IMM_F64;
                        }
                    }
                    else
                    {
                        if (cc->pass == 2)
                        {
                            if (tmpi2->ic_code == IC_IMM_I64)
                            {
                                if (!tmpi2->ic_data)
                                {
                                    tmpi1->ic_flags |= tmpi2->ic_flags | tmpi->ic_flags;
                                    tmpi1->ic_class2 = tmpi->ic_class2;
                                    tmpi_push = tmpi1;
                                    OptSetNOP1(tmpi2);
                                    OptSetNOP1(tmpi);
                                }
                                else
                                    if (tmpi1->ic_code == IC_ADD || tmpi1->ic_code == IC_SUB)
                                    {
                                        if (tmpi1->t.arg1_tree->ic_code == IC_IMM_I64)
                                        {
                                            tmpi1->ic_flags |= tmpi->ic_flags;
                                            tmpi1->t.arg1_tree->ic_data -= tmpi2->ic_data;
                                            tmpi1->ic_class2 = tmpi->ic_class2;
                                            tmpi_push = tmpi1;
                                            OptSetNOP1(tmpi2);
                                            OptSetNOP1(tmpi);
                                        }
                                        else if (tmpi1->t.arg2_tree->ic_code == IC_IMM_I64)
                                        {
                                            tmpi1->ic_flags |= tmpi->ic_flags;
                                            if (tmpi1->ic_code == IC_ADD)
                                                tmpi1->t.arg2_tree->ic_data -= tmpi2->ic_data;
                                            else
                                                tmpi1->t.arg2_tree->ic_data += tmpi2->ic_data;
                                            tmpi1->ic_class2 = tmpi->ic_class2;
                                            tmpi_push=tmpi1;
                                            OptSetNOP1(tmpi2);
                                            OptSetNOP1(tmpi);
                                        }
                                    }
                            }
                            else
                                if (tmpi2->ic_code == IC_IMM_F64)
                                {
                                    if (!tmpi2->ic_data)
                                    {
                                        tmpi1->ic_flags |= tmpi2->ic_flags | tmpi->ic_flags;
                                        tmpi1->ic_class2 = tmpi->ic_class2;
                                        tmpi_push = tmpi1;
                                        OptSetNOP1(tmpi2);
                                        OptSetNOP1(tmpi);
                                    }
                                    else
                                        if (tmpi1->ic_code == IC_ADD || tmpi1->ic_code == IC_SUB)
                                        {
                                            if (tmpi1->t.arg1_tree->ic_code == IC_IMM_F64)
                                            {
                                                tmpi1->ic_flags |= tmpi->ic_flags | tmpi2->ic_flags;
                                                tmpi1->t.arg1_tree->ic_data(F64) -= tmpi2->ic_data(F64);
                                                tmpi1->ic_class2 = tmpi->ic_class2;
                                                tmpi_push = tmpi1;
                                                OptSetNOP1(tmpi2);
                                                OptSetNOP1(tmpi);
                                            }
                                            else if (tmpi1->t.arg2_tree->ic_code == IC_IMM_F64)
                                            {
                                                tmpi1->ic_flags |= tmpi->ic_flags | tmpi2->ic_flags;
                                                if (tmpi1->ic_code == IC_ADD)
                                                    tmpi1->t.arg2_tree->ic_data(F64) -= tmpi2->ic_data(F64);
                                                else
                                                    tmpi1->t.arg2_tree->ic_data(F64) += tmpi2->ic_data(F64);
                                                tmpi1->ic_class2 = tmpi->ic_class2;
                                                tmpi_push = tmpi1;
                                                OptSetNOP1(tmpi2);
                                                OptSetNOP1(tmpi);
                                            }
                                        }
                                }
                        }
                    }
                    break;

                case IC_AND_AND:
                    if (OptFixupBinaryOp1(tmpi, tmpi1, tmpi2, &is_unsigned))
                    {
                        tmpi->ic_data = tmpi1->ic_data && tmpi2->ic_data;
                        tmpi->ic_code = IC_IMM_I64;
                    }
                    tmpi->ic_class = cmp.internal_types[RT_I64];
                    break;

                case IC_OR_OR:
                    if (OptFixupBinaryOp1(tmpi, tmpi1, tmpi2, &is_unsigned))
                    {
                        tmpi->ic_data = tmpi1->ic_data || tmpi2->ic_data;
                        tmpi->ic_code = IC_IMM_I64;
                    }
                    tmpi->ic_class = cmp.internal_types[RT_I64];
                    break;

                case IC_XOR_XOR:
                    if (OptFixupBinaryOp1(tmpi, tmpi1, tmpi2, &is_unsigned))
                    {
                        tmpi->ic_data = tmpi1->ic_data ^^ tmpi2->ic_data;
                        tmpi->ic_code = IC_IMM_I64;
                    }
                    tmpi->ic_class = cmp.internal_types[RT_I64];
                    break;
            end:
                if (!tmpi_push->ic_class->ptr_stars_count)
                {
                    if (tmpi_push->ic_class->raw_type == RT_F64)
                        tmpi_push->ic_class2 = cmp.internal_types[RT_F64];
                    else if (is_unsigned)
                        tmpi_push->ic_class2 = cmp.internal_types[RT_U64];
                    else
                        tmpi_push->ic_class2 = cmp.internal_types[RT_I64];
                }
                break;
            start:
                case IC_EQU_EQU:
                    if (OptFixupBinaryOp1(tmpi, tmpi1, tmpi2, &is_unsigned))
                    {
                        tmpi->ic_data = tmpi1->ic_data == tmpi2->ic_data;
                        tmpi->ic_code = IC_IMM_I64;
                    }
                    else
                        if (tmpi->ic_class->raw_type == RT_F64)
                            tmpi->ic_flags |= ICF_USE_F64;
                    break;

                case IC_NOT_EQU:
                    if (OptFixupBinaryOp1(tmpi, tmpi1, tmpi2, &is_unsigned))
                    {
                        tmpi->ic_data = tmpi1->ic_data != tmpi2->ic_data;
                        tmpi->ic_code = IC_IMM_I64;
                    }
                    else
                        if (tmpi->ic_class->raw_type == RT_F64)
                            tmpi->ic_flags |= ICF_USE_F64;
                    break;

                case IC_LESS:
                    if (i = OptFixupBinaryOp1(tmpi, tmpi1, tmpi2, &is_unsigned))
                    {
                        if (i == FBO1_INT)
                        {
                            if (is_unsigned)
                                tmpi->ic_data = tmpi1->ic_data(U64) < tmpi2->ic_data(U64);
                            else
                                tmpi->ic_data = tmpi1->ic_data(I64) < tmpi2->ic_data(I64);
                        }
                        else
                            tmpi->ic_data = tmpi1->ic_data(F64) < tmpi2->ic_data(F64);
                        tmpi->ic_code = IC_IMM_I64;
                    }
                    else
                    {
                        if (is_unsigned)
                            tmpi->ic_flags |= ICF_USE_UNSIGNED;
                        if (tmpi->ic_class->raw_type == RT_F64)
                            tmpi->ic_flags |= ICF_USE_F64;
                    }
                    break;

                case IC_GREATER_EQU:
                    if (i = OptFixupBinaryOp1(tmpi, tmpi1, tmpi2, &is_unsigned))
                    {
                        if (i == FBO1_INT)
                        {
                            if (is_unsigned)
                                tmpi->ic_data = tmpi1->ic_data(U64) >= tmpi2->ic_data(U64);
                            else
                                tmpi->ic_data = tmpi1->ic_data(I64) >= tmpi2->ic_data(I64);
                        }
                        else
                            tmpi->ic_data = tmpi1->ic_data(F64) >= tmpi2->ic_data(F64);
                        tmpi->ic_code = IC_IMM_I64;
                    }
                    else
                    {
                        if (is_unsigned)
                            tmpi->ic_flags |= ICF_USE_UNSIGNED;
                        if (tmpi->ic_class->raw_type == RT_F64)
                            tmpi->ic_flags |= ICF_USE_F64;
                    }
                    break;

                case IC_GREATER:
                    if (i = OptFixupBinaryOp1(tmpi, tmpi1, tmpi2, &is_unsigned))
                    {
                        if (i == FBO1_INT)
                        {
                            if (is_unsigned)
                                tmpi->ic_data = tmpi1->ic_data(U64) > tmpi2->ic_data(U64);
                            else
                                tmpi->ic_data = tmpi1->ic_data(I64) > tmpi2->ic_data(I64);
                        }
                        else
                            tmpi->ic_data = tmpi1->ic_data(F64) > tmpi2->ic_data(F64);
                        tmpi->ic_code = IC_IMM_I64;
                    }
                    else
                    {
                        if (is_unsigned)
                            tmpi->ic_flags |= ICF_USE_UNSIGNED;
                        if (tmpi->ic_class->raw_type == RT_F64)
                            tmpi->ic_flags |= ICF_USE_F64;
                    }
                    break;

                case IC_LESS_EQU:
                    if (i = OptFixupBinaryOp1(tmpi, tmpi1, tmpi2, &is_unsigned))
                    {
                        if (i == FBO1_INT)
                        {
                            if (is_unsigned)
                                tmpi->ic_data = tmpi1->ic_data(U64) <= tmpi2->ic_data(U64);
                            else
                                tmpi->ic_data = tmpi1->ic_data(I64) <= tmpi2->ic_data(I64);
                        }
                        else
                            tmpi->ic_data = tmpi1->ic_data(F64) <= tmpi2->ic_data(F64);
                        tmpi->ic_code = IC_IMM_I64;
                    }
                    else
                    {
                        if (is_unsigned)
                            tmpi->ic_flags |= ICF_USE_UNSIGNED;
                        if (tmpi->ic_class->raw_type == RT_F64)
                            tmpi->ic_flags |= ICF_USE_F64;
                    }
                    break;
            end:
                tmpi->ic_flags &= ~ICF_RES_TO_INT;
                if (!tmpi_push->ic_class->ptr_stars_count)
                {
                    if (tmpi_push->ic_class->raw_type == RT_F64)
                        tmpi_push->ic_class2 = cmp.internal_types[RT_F64];
                    else if (is_unsigned)
                        tmpi_push->ic_class2 = cmp.internal_types[RT_U64];
                    else
                        tmpi_push->ic_class2 = cmp.internal_types[RT_I64];
                }
                if (tmpi_push->ic_flags & ICF_PUSH_CMP)
                    tmpi->ic_class = tmpi->ic_class2;
                else
                    tmpi->ic_class = cmp.internal_types[RT_I64];
                break;
            start:
                if (cc->pass == 2 && (!tmpc->size || !tmpc2->size))
                    LexWarn(cc, "Assign U0 ");
                start:
                    case IC_MUL_EQU:
                        if (tmpi2->ic_code == IC_IMM_I64 && tmpc->raw_type != RT_F64 && tmpc2->raw_type != RT_F64)
                        {
                            if (i = tmpi2->ic_data)
                            {
                                if (Bsf(i) == Bsr(i))
                                {
                                    tmpi2->ic_data = Bsf(i);
                                    tmpi->ic_code = IC_SHL_EQU;
                                }
                            }
                        }
                        break;

                    case IC_DIV_EQU:
                        if (tmpi2->ic_code == IC_IMM_I64 && tmpc->raw_type != RT_F64 && tmpc2->raw_type != RT_F64 &&
                            (i = tmpi2->ic_data) && Bsf(i) == Bsr(i))
                        {
                            tmpi2->ic_data = Bsf(i);
                            tmpi->ic_code = IC_SHR_EQU;
                        }
                        break;

                    case IC_MOD_EQU:
                        if (tmpi2->ic_code == IC_IMM_I64 && tmpc->raw_type != RT_F64 && tmpc2->raw_type != RT_F64 &&
                            (i = tmpi2->ic_data) && Bsf(i) == Bsr(i))
                        {
                            tmpi2->ic_data = i - 1;
                            tmpi->ic_code = IC_AND_EQU;
                        }
                        break;

                    case IC_ADD_EQU:
                    case IC_SUB_EQU:
                        break;
                end:
                    if (tmpi2->ic_class->raw_type == RT_F64)
                        tmpi->ic_flags = tmpi->ic_flags | ICF_USE_F64;
                    if (tmpc->raw_type == RT_F64)
                    {
                        if (tmpc2->raw_type != RT_F64)
                            tmpi2->ic_flags |= ICF_RES_TO_F64;
                    }
                    break;

                case IC_ASSIGN:
                    if (tmpc->raw_type == RT_F64)
                    {
                        if (tmpc2->raw_type != RT_F64)
                            tmpi2->ic_flags |= ICF_RES_TO_F64;
                    }
                    else
                    {
                        if (tmpc2->raw_type == RT_F64)
                            tmpi2->ic_flags |= ICF_RES_TO_INT;
                    }
                    if (cc->pass == 2 && tmpi1->ic_class->raw_type != RT_F64)
                    {
                        if (tmpi1->ic_code == IC__PP)
                        {
                            tmpi->ic_code = IC_ASSIGN_PP;
                            tmpi->ic_flags |= tmpi1->ic_flags;
                            tmpi->t.class2 = tmpi1->ic_class;
                            OptSetNOP1(tmpi1);
                        }
                        else if (tmpi1->ic_code == IC__MM)
                        {
                            tmpi->ic_code = IC_ASSIGN_MM;
                            tmpi->ic_flags |= tmpi1->ic_flags;
                            tmpi->t.class2 = tmpi1->ic_class;
                            OptSetNOP1(tmpi1);
                        }
                    }
                    break;

                case IC_SHL_EQU:
                case IC_SHR_EQU:
                case IC_AND_EQU:
                case IC_OR_EQU:
                case IC_XOR_EQU:
                    if (tmpc2->raw_type == RT_F64)
                        tmpi2->ic_flags |= ICF_RES_TO_INT;
                    break;
            end:
                break;

            case IC_ENTER:
            case IC_LEAVE:
                tmpi->ic_data = -cc->htc.fun->size;
                break;

            case IC_ADD_RSP:
                if (tmpi1 = OptLag(tmpi))
                {
                    if (tmpi1->ic_code == IC_ADD_RSP)
                    {
                        tmpi->ic_data += tmpi1->ic_data;
                        tmpi->ic_flags |= tmpi1->ic_flags;
                        OptSetNOP1(tmpi1);
                    }
                }
            case IC_ADD_RSP1:
                break;

            case IC_BSF:
                if (tmpi1->ic_code == IC_IMM_I64)
                {
                    tmpi1->ic_data = Bsf(tmpi1->ic_data);
                    tmpi_push = tmpi1;
                    OptSetNOP1(OptLag(tmpi1));  //CALL_START
                    tmpi2 = OptLead1(tmpi);
                    tmpi1->ic_flags |= tmpi->ic_flags | tmpi2->ic_flags;
                    OptSetNOP1(tmpi2);          //CALL_END
                    OptSetNOP1(tmpi);           //BSF
                }
                break;

            case IC_BSR:
                if (tmpi1->ic_code == IC_IMM_I64)
                {
                    tmpi1->ic_data = Bsr(tmpi1->ic_data);
                    tmpi_push = tmpi1;
                    OptSetNOP1(OptLag(tmpi1));  //CALL_START
                    tmpi2=OptLead1(tmpi);
                    tmpi1->ic_flags |= tmpi->ic_flags | tmpi2->ic_flags;
                    OptSetNOP1(tmpi2);          //CALL_END
                    OptSetNOP1(tmpi);           //BSR
                }
                break;

            case IC_POPCNT:
                if (tmpi1->ic_code == IC_IMM_I64)
                {
                    tmpi1->ic_data = PopCount(tmpi1->ic_data);
                    tmpi_push = tmpi1;
                    OptSetNOP1(OptLag(tmpi1));  //CALL_START
                    tmpi2 = OptLead1(tmpi);
                    tmpi1->ic_flags |= tmpi->ic_flags | tmpi2->ic_flags;
                    OptSetNOP1(tmpi2);          //CALL_END
                    OptSetNOP1(tmpi);           //POPCNT
                }
                break;

            case IC_LBTS:
            case IC_LBTR:
            case IC_LBTC:
                tmpi->ic_flags |= ICF_LOCK;
                break;

            case IC_TO_I64:
                if (tmpi1->ic_code == IC_IMM_F64)
                {
                    tmpi2 = tmpi1->last;
                    while (tmpi2->ic_code != IC_CALL_START)
                        tmpi2 = tmpi2->last;
                    OptSetNOP1(tmpi2);

                    tmpi2 = tmpi->next;
                    while (tmpi2->ic_code != IC_CALL_END)
                        tmpi2 = tmpi2->next;

                    tmpi->ic_flags |= tmpi1->ic_flags & ~ICF_RES_TO_INT | tmpi2->ic_flags;
                    OptSetNOP1(tmpi2);

                    tmpi->ic_code = IC_IMM_I64;
                    tmpi->ic_data = ToI64(tmpi1->ic_data(F64));
                    tmpi->ic_class = cmp.internal_types[RT_I64];
                    tmpi->ic_class2 = cmp.internal_types[RT_I64];
                    OptSetNOP1(tmpi1);
                }
                else if (tmpi1->ic_code == IC_IMM_I64)
                {
                    tmpi2 = tmpi1->last;
                    while (tmpi2->ic_code != IC_CALL_START)
                        tmpi2 = tmpi2->last;
                    OptSetNOP1(tmpi2);

                    tmpi2 = tmpi->next;
                    while (tmpi2->ic_code != IC_CALL_END)
                        tmpi2 = tmpi2->next;

                    tmpi->ic_flags |= tmpi1->ic_flags & ~ICF_RES_TO_F64 | tmpi2->ic_flags;
                    OptSetNOP1(tmpi2);

                    tmpi->ic_code = IC_IMM_I64;
                    tmpi->ic_data = tmpi1->ic_data;
                    tmpi->ic_class = cmp.internal_types[RT_I64];
                    tmpi->ic_class2 = cmp.internal_types[RT_I64];
                    OptSetNOP1(tmpi1);
                }
                if (tmpi1->ic_flags & ICF_RES_TO_F64)
                {
                    i = 0;
                    tmpi2 = tmpi1->last;
                    while (TRUE)
                    {
                        if (tmpi2->ic_code == IC_CALL_START)
                        {
                            if (!i)
                                break;
                            i--;
                        }
                        else if (tmpi2->ic_code == IC_CALL_END)
                            i++;
                        tmpi2 = tmpi2->last;
                    }
                    OptSetNOP1(tmpi2);

                    tmpi2 = tmpi1->next;
                    while (tmpi2->ic_code != IC_CALL_END)
                        tmpi2 = tmpi2->next;

                    tmpi1->ic_flags = tmpi->ic_flags | tmpi1->ic_flags & ~(ICF_RES_TO_F64 | ICF_PUSH_RES) | tmpi2->ic_flags;
                    OptSetNOP1(tmpi2);

                    tmpi1->ic_class = cmp.internal_types[RT_I64];
                    tmpi1->ic_class2 = cmp.internal_types[RT_I64];
                    tmpi_push = tmpi1;
                    OptSetNOP1(tmpi);
                }
                break;

            case IC_TO_F64:
                if (tmpi1->ic_code == IC_IMM_I64)
                {
                    tmpi2 = tmpi1->last;
                    while (tmpi2->ic_code != IC_CALL_START)
                        tmpi2 = tmpi2->last;
                    OptSetNOP1(tmpi2);

                    tmpi2 = tmpi->next;
                    while (tmpi2->ic_code != IC_CALL_END)
                        tmpi2 = tmpi2->next;

                    tmpi->ic_flags |= tmpi1->ic_flags & ~ICF_RES_TO_F64 | tmpi2->ic_flags;
                    OptSetNOP1(tmpi2);

                    tmpi->ic_code = IC_IMM_F64;
                    tmpi->ic_data(F64) = ToF64(tmpi1->ic_data);
                    tmpi->ic_class = cmp.internal_types[RT_F64];
                    tmpi->ic_class2 = cmp.internal_types[RT_F64];
                    OptSetNOP1(tmpi1);
                }
                else if (tmpi1->ic_code == IC_IMM_F64)
                {
                    tmpi2 = tmpi1->last;
                    while (tmpi2->ic_code != IC_CALL_START)
                        tmpi2 = tmpi2->last;
                    OptSetNOP1(tmpi2);

                    tmpi2 = tmpi->next;
                    while (tmpi2->ic_code != IC_CALL_END)
                        tmpi2 = tmpi2->next;

                    tmpi->ic_flags |= tmpi1->ic_flags & ~ICF_RES_TO_INT | tmpi2->ic_flags;
                    OptSetNOP1(tmpi2);

                    tmpi->ic_code = IC_IMM_F64;
                    tmpi->ic_data = tmpi1->ic_data;
                    tmpi->ic_class = cmp.internal_types[RT_F64];
                    tmpi->ic_class2 = cmp.internal_types[RT_F64];
                    OptSetNOP1(tmpi1);
                }
                if (tmpi1->ic_flags & ICF_RES_TO_INT)
                {
                    i = 0;
                    tmpi2 = tmpi1->last;
                    while (TRUE)
                    {
                        if (tmpi2->ic_code == IC_CALL_START)
                        {
                            if (!i)
                                break;
                            i--;
                        }
                        else if (tmpi2->ic_code == IC_CALL_END)
                            i++;
                        tmpi2 = tmpi2->last;
                    }
                    OptSetNOP1(tmpi2);

                    tmpi2 = tmpi1->next;
                    while (tmpi2->ic_code != IC_CALL_END)
                        tmpi2 = tmpi2->next;

                    tmpi1->ic_flags = tmpi->ic_flags | tmpi1->ic_flags & ~(ICF_RES_TO_INT | ICF_PUSH_RES) | tmpi2->ic_flags;
                    OptSetNOP1(tmpi2);

                    tmpi1->ic_class = cmp.internal_types[RT_F64];
                    tmpi1->ic_class2 = cmp.internal_types[RT_F64];
                    tmpi_push = tmpi1;
                    OptSetNOP1(tmpi);
                }
                break;

            case IC_TO_BOOL:
                if (tmpi1->ic_code == IC_IMM_I64 || tmpi1->ic_code == IC_IMM_F64)
                {
                    tmpi2 = tmpi1->last;
                    while (tmpi2->ic_code != IC_CALL_START)
                        tmpi2 = tmpi2->last;
                    OptSetNOP1(tmpi2);

                    tmpi2 = tmpi->next;
                    while (tmpi2->ic_code != IC_CALL_END)
                        tmpi2 = tmpi2->next;

                    tmpi->ic_flags |= tmpi1->ic_flags & ~ICF_RES_TO_F64 | tmpi2->ic_flags;
                    OptSetNOP1(tmpi2);

                    tmpi->ic_code = IC_IMM_I64;
                    tmpi->ic_data = ToBool(tmpi1->ic_data);
                    tmpi->ic_class = cmp.internal_types[RT_I64];
                    tmpi->ic_class2 = cmp.internal_types[RT_I64];
                    OptSetNOP1(tmpi1);
                }
                break;

            case IC_BR_ZERO:
                tmpi_push = OptBrZero(cc, tmpi);
                break;

            case IC_BR_NOT_ZERO:
                tmpi_push = OptBrNotZero(cc, tmpi);
                break;

            case IC_NOP1:
                if (tmpi->ic_flags & ICF_PUSH_RES)
                {
                    tmpi1 = tmpi;
                    do
                        tmpi1 = tmpi1->last;
                    while (tmpi1->ic_code == IC_NOP1);

                    tmpi1->ic_flags |= ICF_PUSH_RES;
                    tmpi->ic_flags &= ~ICF_PUSH_RES;
                }
                break;

            case IC_NOP2:
                ps->ptr += tmpi->ic_data << 1;
                break;

            case IC_LABEL:
                lb = OptLabelFwd(tmpi->ic_data);
                lb1 = tmpi->ic_data;
                while (lb2 = lb1->forward)
                {
                    lb1->forward = lb;
                    lb1 = lb2;
                }
                if (tmpi1 = OptLag(tmpi))
                {
                    if (tmpi1->ic_code == IC_JMP)
                    {
                        lb1 = tmpi1->ic_data;
                        while (lb1->forward)
                            lb1 = lb1->forward;
                        if (lb1 == lb)
                        {
                            tmpi->ic_flags |= tmpi1->ic_flags;
                            OptSetNOP1(tmpi1);
                        }
                    }
                    else if (tmpi1->ic_code == IC_LABEL)
                    {
                        lb1 = tmpi1->ic_data;
                        if (!lb1->forward)
                            lb1->forward = lb;
                        if (tmpi1 = OptLag(tmpi1))
                        {
                            if (tmpi1->ic_code == IC_JMP)
                            {
                                lb1 = tmpi1->ic_data;
                                while (lb1->forward)
                                    lb1 = lb1->forward;
                                if (lb1 == lb)
                                {
                                    tmpi->ic_flags |= tmpi1->ic_flags;
                                    OptSetNOP1(tmpi1);
                                }
                            }
                        }
                    }
                }
                break;

            case IC_JMP:
                if (tmpi1 = OptLag(tmpi))
                {
                    if (tmpi1->ic_code == IC_LABEL)
                    {
                        lb = OptLabelFwd(tmpi->ic_data);
                        lb1 = OptLabelFwd(tmpi1->ic_data);
                        if (lb != lb1)
                            lb1->forward = lb;
                    }
                }
                break;

            case IC_STR_CONST:
            case IC_RBP:
            case IC_MOV_FS:
            case IC_MOV_GS:
            case IC_RIP:
            case IC_SIZEOF:
            case IC_SQR:
            case IC_ABS:
            case IC_SQRT:
            case IC_SIN:
            case IC_COS:
            case IC_TAN:
            case IC_ATAN:
            case IC_BR_CARRY:
            case IC_BR_NOT_CARRY:
            case IC_BR_EQU_EQU ...IC_BR_LESS_EQU:
            case IC_BR_EQU_EQU2...IC_BR_LESS_EQU2:
            case IC_BR_OR_OR_NOT_ZERO:
            case IC_BR_OR_OR_ZERO:
            case IC_BR_AND_AND_NOT_ZERO:
            case IC_BR_AND_AND_ZERO:
            case IC_BR_AND_NOT_ZERO:
            case IC_BR_AND_ZERO:
            case IC_BR_MM_NOT_ZERO:
            case IC_BR_MM_ZERO:
            case IC_BR_BT:
            case IC_BR_BTS:
            case IC_BR_BTR:
            case IC_BR_BTC:
            case IC_BR_NOT_BT:
            case IC_BR_NOT_BTS:
            case IC_BR_NOT_BTR:
            case IC_BR_NOT_BTC:
            case IC_END:
            case IC_ADDR:
            case IC_RET:
            case IC_END_EXP:
            case IC_CALL_START:
            case IC_CALL_END:
            case IC_CALL_END2:
            case IC_PUSH_REGS:
            case IC_POP_REGS:
            case IC_SUB_CALL:
            case IC_CALL:
            case IC_CALL_INDIRECT:
            case IC_CALL_INDIRECT2:
            case IC_CALL_EXTERN:
            case IC_CALL_IMPORT:
            case IC_PUSH:
            case IC_POP:
            case IC_INVLPG:
            case IC_CLFLUSH:
            case IC_RFLAGS_GET:
            case IC_CARRY:
            case IC_RBP_GET:
            case IC_RSP_GET:
            case IC_RAX_GET:
            case IC_RETURN_VAL:
            case IC_RETURN_VAL2:
            case IC_ABS_ADDR:
            case IC_HEAP_GLOBAL:
            case IC_ADDR_IMPORT:
            case IC_GET_LABEL:
            case IC_TYPE:
            case IC_RDTSC:
            case IC_RFLAGS_SET:
            case IC_RBP_SET:
            case IC_RSP_SET:
            case IC_RAX_SET:
            case IC_SIGN_I64:
            case IC_TOUPPER:
            case IC_ABS_I64:
            case IC_MIN_I64:
            case IC_MAX_I64:
            case IC_MIN_U64:
            case IC_MAX_U64:
            case IC_MOD_U64:
            case IC_SQR_I64:
            case IC_SQR_U64:
            case IC_SWAP_U8:
            case IC_SWAP_U16:
            case IC_SWAP_U32:
            case IC_SWAP_I64:
            case IC_IN_U32:
            case IC_IN_U16:
            case IC_IN_U8:
            case IC_STRLEN:
            case IC_BT:
            case IC_BTS:
            case IC_BTR:
            case IC_BTC:
            case IC_QUEUE_INIT:
            case IC_QUEUE_REMOVE:
            case IC_QUEUE_INSERT:
            case IC_QUEUE_INSERT_REV:
            case IC_OUT_U32:
            case IC_OUT_U16:
            case IC_OUT_U8:
            case IC_NOBOUND_SWITCH:
            case IC_SWITCH:
            case IC_ASM:
                break;

            default:
                "Pass:%d Missing IC handler\n", cc->pass;
                ICPut(cc, tmpi);
                LexExcept(cc, "Compiler Optimization Error at ");
        }
        if (intermediate_code_table[code].arg_count == IS_2_ARG)
        {
            if (tmpi_push->ic_precedence & ~ASSOC_MASK == PREC_ASSIGN)
                OptFixSizeOf(tmpi2, tmpi_push, tmpi1->ic_class - 1);
            else
            {
                OptFixSizeOf(tmpi1, tmpi_push, tmpi2->ic_class);
                OptFixSizeOf(tmpi2, tmpi_push, tmpi1->ic_class);
            }
        }
        if (intermediate_code_table[tmpi_push->ic_code].res_count)
        {
            ParsePush(ps, tmpi->ic_class2);
            ParsePush(ps, tmpi_push);
        }
        if (tmpi->ic_class)
        {
            if (tmpi->ic_class->raw_type == RT_F64)
                tmpi->ic_flags &= ~ICF_RES_TO_F64;
            else
                tmpi->ic_flags &= ~ICF_RES_TO_INT;
            if (code > IC_END_EXP)
                last_with_class = tmpi;
        }
        tmpi = tmpi->next;
    }
    if (ps->ptr > 2)
    {
        "Pass: %d Stack: %08X\n", cc->pass,ps->ptr;
        LexExcept(cc, "Compiler Optimization Error at ");
    }
//This is for determining type conversions for passing args to functions.
    return last_with_class;
}