bool Emitter::bundling()

in vm/jitrino/src/codegenerator/ipf/IpfEmitter.cpp [817:1052]


bool Emitter::bundling(int bbindex) {
    EmitterBb * bb = bbs->at(bbindex);
    InstVector & insts = bb->insts;
    long   sizebb = insts.size();
    if (sizebb==0) return true;

    vectorbool * stops = bb->stops;
    BundleVector * bundles = bb->bundles;
    BundleDescription tmp = {0,0,0};
    int   iTmpl=-1;
    Inst *inst0=NULL, *inst1=NULL, *inst2=NULL, *inst3=NULL;
    bool  stop0=false, stop1=false, stop2=false, stop3=false;
    bool  stop0_f=false, stop1_f=false, stop2_f=false, stop3_f=false; // inst is first in group
    bool  stop0_l=false, stop1_l=false, stop2_l=false; // inst is last in group
    int   it0=0, it1=0, it2=0, it3=0; // insts type
    long  i0, i1, i2, i3;

    for ( i0=0 ; i0 < sizebb ; ) {
        inst0=Encoder::resolvePseudo(cfg, insts[i0]);
        if (Encoder::isIgnoreInst(inst0)) { i0++; continue; }
        stop0=stops->at(i0);

        for ( i1=i0+1 ; i1<sizebb ; ) {
            inst1=Encoder::resolvePseudo(cfg, insts[i1]);
            if (Encoder::isIgnoreInst(inst1)) { i1++; continue; }
            stop1=stops->at(i1);
            break;
        }
        if ( i1 >= sizebb ) { inst1=NULL; }

        for ( i2=i1+1 ; i2<sizebb ; ) {
            inst2=Encoder::resolvePseudo(cfg, insts[i2]);
            if (Encoder::isIgnoreInst(inst2)) { i2++; continue; }
            stop2=stops->at(i2);
            break;
        }
        if ( i2 >= sizebb ) { inst2=NULL; }

        for ( i3=i2+1 ; i3<sizebb ; ) {
            inst3=Encoder::resolvePseudo(cfg, insts[i3]);
            if (Encoder::isIgnoreInst(inst3)) { i3++; continue; }
            stop3=stops->at(i3);
            break;
        }
        if ( i3 >= sizebb ) { inst3=NULL; }

        it0 = Encoder::getInstType(inst0);
        it1 = Encoder::getInstType(inst1);
        it2 = Encoder::getInstType(inst2);
        it3 = Encoder::getInstType(inst3);

        stop0_l = (it0 & IT_GL)==IT_GL;
        stop1_l = (it1 & IT_GL)==IT_GL;
        stop2_l = (it2 & IT_GL)==IT_GL;
        stop0_f = (it0 & IT_GF)==IT_GF;
        stop1_f = (it1 & IT_GF)==IT_GF;
        stop2_f = (it2 & IT_GF)==IT_GF;
        stop3_f = (it3 & IT_GF)==IT_GF;

        /*********************************************
         * Special case for br.call
         * br.ret will return to next bundle, so
         * all instructions after br.call must be nop
         *********************************************/
        if (inst0->getInstCode()==INST_BR || inst0->getInstCode()==INST_BR13) {
            CompVector & cmpls0 = inst0->getComps();
            if (cmpls0.size()>0 && cmpls0[0]==CMPLT_BTYPE_CALL) {
                inst1=NULL;
                inst2=NULL;
            }
        } else if (inst1!=NULL && (inst1->getInstCode()==INST_BR || inst1->getInstCode()==INST_BR13)) {
            CompVector & cmpls1 = inst1->getComps();
            if (cmpls1.size()>0 && cmpls1[0]==CMPLT_BTYPE_CALL) {
                inst2=NULL;
            }
        }

        /*********************************************
         * Special case for inst0==LX type (brl,...)
         *********************************************/
        if ( Encoder::getInstType(inst0->getInstCode()) & IT_L ) {
            inst1=NULL;
            inst2=NULL;
            getTmpl(bbindex, tmp, NULL, inst0, NULL
                , false, false, stop0 || stop0_l || stop1_f);
            iTmpl=findTmpl(tmp);
            if( iTmpl>=0 ) {
                bundles->addBundle(iTmpl, NULL, inst0, NULL);
                i0 += 1;
                continue;
            }
            IPF_ERR << "BUNDLING ERROR: CAN'T FIND TEMPLATE !\n";
            IPF_ERR << "BUNDLING ERROR: " << IrPrinter::toString(inst0) << "\n";
            IPF_ASSERT(0);
        }

        /********************************
         * Special case for inst1==LX type (brl,...)
         ********************************/
        if (inst1!=NULL && (Encoder::getInstType(inst1->getInstCode()) & IT_L)) {
            inst2=NULL;
            getTmpl(bbindex, tmp, inst0, inst1, NULL
                , stop0 || stop0_l || stop1_f, false, stop1 || stop1_l || stop2_f);
            iTmpl=findTmpl(tmp);
            if( iTmpl>=0 ) {
                bundles->addBundle(iTmpl, inst0, inst1, NULL);
                i0 = i1 + 1;
                continue;
            }
            inst1=NULL;
        }

        /********************************
         * inst1!=NULL && inst2!=NULL
         ********************************/
        if (inst1!=NULL && inst2!=NULL) {
            getTmpl(bbindex, tmp, inst0, inst1, inst2
                , stop0 || stop0_l || stop1_f, stop1 || stop1_l || stop2_f, stop2 || stop2_l || stop3_f);
            iTmpl=findTmpl(tmp);
            if( iTmpl>=0 ) {
                bundles->addBundle(iTmpl, inst0, inst1, inst2);
                i0 = i2 + 1;
                continue;
            }
        }

        /********************************
         * inst2==NULL && inst1!=LX type (brl,...)
         ********************************/
        if (inst1!=NULL) {
            getTmpl(bbindex, tmp, inst0, inst1, NULL
                , stop0 || stop0_l || stop1_f, stop1 || stop1_l || stop2_f, false);
            iTmpl=findTmpl(tmp);
            if( iTmpl>=0 ) {
                bundles->addBundle(iTmpl, inst0, inst1, NULL);
                i0 = i1 + 1;
                continue;
            }
            getTmpl(bbindex, tmp, inst0, inst1, NULL
                , stop0 || stop0_l || stop1_f, false, stop1 || stop1_l || stop2_f);
            iTmpl=findTmpl(tmp);
            if( iTmpl>=0 ) {
                bundles->addBundle(iTmpl, inst0, inst1, NULL);
                i0 = i1 + 1;
                continue;
            }

            getTmpl(bbindex, tmp, inst0, NULL, inst1
                , stop0 || stop0_l || stop1_f, false, stop1 || stop1_l || stop2_f);
            iTmpl=findTmpl(tmp);
            if( iTmpl>=0 ) {
                bundles->addBundle(iTmpl, inst0, NULL, inst1);
                i0 = i1 + 1;
                continue;
            }
            getTmpl(bbindex, tmp, inst0, NULL, inst1
                , false, stop0 || stop0_l || stop1_f, stop1 || stop1_l || stop2_f);
            iTmpl=findTmpl(tmp);
            if( iTmpl>=0 ) {
                bundles->addBundle(iTmpl, inst0, NULL, inst1);
                i0 = i1 + 1;
                continue;
            }

            getTmpl(bbindex, tmp, NULL, inst0, inst1
                , false, stop0 || stop0_l || stop1_f, stop1 || stop1_l || stop2_f);
            iTmpl=findTmpl(tmp);
            if( iTmpl>=0 ) {
                bundles->addBundle(iTmpl, NULL,inst0, inst1);
                i0 = i1 + 1;
                continue;
            }
        }

        /********************************
         * inst1==NULL
         ********************************/
        getTmpl(bbindex, tmp, inst0, NULL, NULL
            , stop0 || stop0_l || stop1_f, false, false);
        iTmpl=findTmpl(tmp);
        if( iTmpl>=0 ) {
            bundles->addBundle(iTmpl, inst0, NULL, NULL);
            i0 += 1;
            continue;
        }
        getTmpl(bbindex, tmp, inst0, NULL, NULL
            , false, stop0 || stop0_l || stop1_f, false);
        iTmpl=findTmpl(tmp);
        if( iTmpl>=0 ) {
            bundles->addBundle(iTmpl, inst0, NULL, NULL);
            i0 += 1;
            continue;
        }
        getTmpl(bbindex, tmp, inst0, NULL, NULL
            , false, false, stop0 || stop0_l || stop1_f);
        iTmpl=findTmpl(tmp);
        if( iTmpl>=0 ) {
            bundles->addBundle(iTmpl, inst0, NULL, NULL);
            i0 += 1;
            continue;
        }

        getTmpl(bbindex, tmp, NULL, inst0, NULL
            , false, stop0 || stop0_l || stop1_f, false);
        iTmpl=findTmpl(tmp);
        if( iTmpl>=0 ) {
            bundles->addBundle(iTmpl, NULL, inst0, NULL);
            i0 += 1;
            continue;
        }
        getTmpl(bbindex, tmp, NULL, inst0, NULL
            , false, false, stop0 || stop0_l || stop1_f);
        iTmpl=findTmpl(tmp);
        if( iTmpl>=0 ) {
            bundles->addBundle(iTmpl, NULL, inst0, NULL);
            i0 += 1;
            continue;
        }

        getTmpl(bbindex, tmp, NULL, NULL, inst0
            , false, false, stop0 || stop0_l || stop1_f);
        iTmpl=findTmpl(tmp);
        if( iTmpl>=0 ) {
            bundles->addBundle(iTmpl, NULL, NULL, inst0);
            i0 += 1;
            continue;
        }

        IPF_ERR << "ERROR: CAN'T FIND TEMPLATE !!!\n";
        IPF_ASSERT(0);

        i0++;
    }

    return true;
}