Ejemplo n.º 1
0
/* SSA doesn't work well when there are dead paths */
static void removeDeadBlock(BLOCK *b)
{
    if (b->pred == NULL && !b->alwayslive)
    {
        BLOCKLIST *bl = b->succ;
        while (bl)
        {
            unlinkBlock(bl->block, b);
            bl = bl->next;
        }
		if (b->critical)
		{
			b->critical = FALSE;
			blockArray[b->blocknum] = 0;
		}
        if (b->head != b->tail && b->head->fwd != b->tail)
        {   QUAD *p = b->head->fwd;
            QUAD *q = b->tail->fwd;
            while (q != p)
            {
                if (p->dc.opcode != i_dbgblock && p->dc.opcode != i_dbgblockend 
                    && p->dc.opcode != i_var && p->dc.opcode != i_func && p->dc.opcode != i_label)
                {
                    RemoveInstruction(p);
                }
                p = p->fwd;
            }
        }
    }
}
Ejemplo n.º 2
0
/* SSA doesn't work well when there are dead paths */
static void removeDeadBlock(BLOCK *b)
{
    if (b->pred == NULL)
    {
        BLOCKLIST *bl = b->succ;
        while (bl)
        {
            unlinkBlock(bl->block, b);
            bl = bl->next;
        }
        if (b->head != b->tail && b->head->fwd != b->tail)
        {   QUAD *p = b->head->fwd;
            QUAD *q = b->tail->fwd;
            while (q != p)
            {
                if (p->dc.opcode != i_dbgblock && p->dc.opcode != i_dbgblockend 
                    && p->dc.opcode != i_var && p->dc.opcode != i_func)
                {
                    RemoveInstruction(p);
                }
                p = p->fwd;
            }
        }
    }
}
Ejemplo n.º 3
0
void weed_goto(void)
{
    BOOLEAN killing = FALSE;
    QUAD *head = intermed_head;
    BLOCK *b = head->block;
    while (head)
    {
        QUAD *next = head->fwd;
        if (head->block != b)
        {
            killing = FALSE;
            b = head->block;
        }
        if (killing)
        {
            if (head->dc.opcode != i_block && head->dc.opcode != i_blockend
                && head->dc.opcode != i_dbgblock && head->dc.opcode != i_dbgblockend && head->dc.opcode != i_var
                && head->dc.opcode != i_label && !head->ignoreMe)
                RemoveInstruction(head);
        }
        else if (head->dc.opcode == i_goto)
            killing = TRUE;
        head = next;
    }
}
Ejemplo n.º 4
0
static BOOLEAN peep(BLOCK *b, BOOLEAN branches)
/*
 * ICODE peep main routine
 */
{
    QUAD *head = b->head;
    BLOCKLIST *bl;
    BOOLEAN changed = FALSE;
    if (b->visiteddfst)
        return changed;
    b->visiteddfst = TRUE;
    while (head != b->tail->fwd)
    {
        int rv = FALSE;
        switch (head->dc.opcode)
        {
            case i_goto:
                if (branches && !functionHasAssembly)
                {
                    kill_dupgoto(b, head);
                    kill_brtonext(b, head);
                }
                break;
            case i_jc:
            case i_jnc:
            case i_jbe:
            case i_ja:
            case i_je:
            case i_jne:
            case i_jge:
            case i_jg:
            case i_jle:
            case i_jl:
                if (branches && !functionHasAssembly)
                {
                       kill_jumpover(b, head);
                    kill_brtonext(b, head);
                }
                break;
            case i_label:
                if (branches)
                {
                    kill_labeledgoto(b, head);
                }
                break;
            case i_nop: /* just kill it */
                RemoveInstruction(head);
                break;
            case i_assn:
                rv = peep_assn(b, head);
                break;
            default:
                break;
        }
        changed |= !!rv;
        if (rv <=0)
            head = head->fwd;
    }
    return changed;
}
Ejemplo n.º 5
0
static void RemoveDuplicateGotos(void)
{
    QUAD *head = intermed_head;
    while (head)
    {
        if (head->dc.opcode == i_goto)
        {
            while (head->fwd && head->fwd->dc.opcode == i_goto)
                RemoveInstruction(head->fwd);
        }
        head = head->fwd;
    }
}
Ejemplo n.º 6
0
static void kill_dupgoto(BLOCK *b, QUAD *head)
{
    (void)b;
    head = head->fwd;
    while (head && head->dc.opcode != i_label)
    {
        if (head->dc.opcode != i_block && head->dc.opcode != i_blockend 
            && head->dc.opcode != i_dbgblock && head->dc.opcode != i_dbgblockend && head->dc.opcode != i_var
            && head->dc.opcode != i_label && !head->ignoreMe)
            RemoveInstruction(head);
        head = head->fwd;
    }
}
Ejemplo n.º 7
0
static void kill_brtonext(BLOCK *b, QUAD *head)
/*
 * branches to the next statement get wiped
 */
{
    QUAD *temp;
    (void)b;
    while (TRUE)
    {
        switch (head->dc.opcode)
        {
            case i_jc:
            case i_jnc:
            case i_jbe:
            case i_ja:
            case i_je:
            case i_jne:
            case i_jge:
            case i_jg:
            case i_jle:
            case i_jl:
                if (chosenAssembler->msil)
                    return;
            case i_goto:
                temp = head->fwd;
                while (temp && (temp->dc.opcode == i_label || temp->ignoreMe 
                    || temp->dc.opcode == i_block || temp->dc.opcode == i_blockend))
                {
                    if (temp->dc.opcode == i_label && temp->dc.v.label == head
                        ->dc.v.label)
                    {
                        RemoveInstruction(head);
                        return;
                    }
                    temp = temp->fwd;
                }
            default:
                return ;
        }
    }
}
Ejemplo n.º 8
0
static int peep_assn(BLOCK *b, QUAD *head)
{
    (void)b;
    if (head->temps == (TEMP_LEFT | TEMP_ANS) && !(head->dc.right) && 
        head->dc.left->size == head->ans->size &&
        head->dc.left->mode == i_direct && head->ans->mode == i_direct && !head->dc.left->bits)
    {
        int t0 = head->ans->offset->v.sp->value.i;
        int t1 = head->dc.left->offset->v.sp->value.i;
        if (!isset(occursInAbnormal, t0) && !isset(occursInAbnormal,t1))
        {
            if (t0 == t1)
            {
                RemoveInstruction(head);			
                return -1;
            }
        }
    }
    if (!(chosenAssembler->arch->denyopts & DO_NOOPTCONVERSION))
    {
        if (head->temps == (TEMP_LEFT | TEMP_ANS) && 
            head->dc.left->size != head->ans->size)
        {
            if (head->back->dc.opcode == i_assn)
            {
                if (head->back->ans->size == head->back->dc.left->size && head->back->ans == head->dc.left)
                    if (head->back->dc.left->mode != i_immed && !head->back->dc.left->bits)
                    {
                        head->dc.left = head->back->dc.left;
                        if ((!head->dc.left->offset || head->dc.left->offset->type != en_tempref)
                            && (!head->dc.left->offset2 || head->dc.left->offset2->type != en_tempref))						
                            head->temps &= ~TEMP_LEFT;
                        return -1;
                    }
            }
        }
    }
    return 0;
}
Ejemplo n.º 9
0
static void MoveBlockTo(BLOCK *b)
{
    BLOCK *prev = b->pred->block;
    BLOCK *succ = b->succ->block;
    QUAD *head;
    QUAD *tail = prev->tail;
    QUAD *jmp = Alloc(sizeof(QUAD));
    QUAD *insert = b->tail;
    int label = nextLabel++;
    if (b->tail->dc.opcode == i_blockend)
        RemoveInstruction(b->tail);
    // insert a jump at the end of the block
    jmp->dc.opcode = i_goto;
    jmp->block = b;
    jmp->dc.v.label = label;
    jmp->fwd = b->tail->fwd;
    jmp->back = b->tail;
    if (jmp->fwd)
        jmp->fwd->back = jmp;
    jmp->back->fwd = jmp;
    b->tail = jmp;
    
    InsertLabel(succ, label);
    
    // unlink
    if (b->head == criticalThunks)
        criticalThunks = b->tail->fwd;
    if (b->head->back)
        b->head->back->fwd = b->tail->fwd;
    if (b->tail->fwd)
        b->tail->fwd->back = b->head->back;
    
    // relink
    prev->tail->fwd->back = b->tail;
    b->tail->fwd = prev->tail->fwd;
    prev->tail->fwd = b->head;
    b->head->back = prev->tail;
}
Ejemplo n.º 10
0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void IndirectCallPromotion::PromoteCallWithMultipleTargets(CallInstr* instr,
                                                           CallSite* callSite,
                                                           CallEdgeList& targetEdges, 
                                                           int promotedTargets, 
                                                           bool hasUnpromotedTargets) {
    // Split the block that contains the 'call' before it.
    // If the called functions return values this block will contain
    // a 'phi' that combines them.
    auto originalBlock = instr->ParentBlock();
    auto& symbols = originalBlock->ParentFunction()->Symbols();
    auto continuationName = BlockUtils::CreateUniqueName("#indir_prom_cont", symbols);
    auto continuationBlock = instr->ParentBlock()->SplitAt(instr, continuationName);

    // Any incoming 'phi' operand from the original block
    // is now incoming from 'continuationBlock'.
    for(int i = 0; i < continuationBlock->SuccessorCount(); i++) {
        BlockUtils::ReplacePhiOperandsBlock(continuationBlock->SuccessorAt(i),
                                            originalBlock, continuationBlock);
    }

    // For each potential target we create a test block
    // and a block that contains the actual call. For the first target
    // the test block is not created (the block where the original call
    // was found is used) and for the last one too, but only if we have
    // no unpromoted targets. If we have we create an "else" block 
    // where we move the original call (otherwise the call is deleted).
    BlockList testBlocks;
    BlockList callBlocks;
    CallList createdCalls;
    Block* previousBlock; // Used to insert the blocks in order.

    // Remove the 'goto' to 'continuationBlock'.
    originalBlock->RemoveInstruction(originalBlock->LastInstruction());

    for(int i = 0; i < targetEdges.Count(); i++) {
        DebugValidator::IsFalse(targetEdges[i].Callee()->IsNodeGroup());
        auto targetCallNode = static_cast<CallNode*>(targetEdges[i].Callee());
        auto targetFunctionRef = targetCallNode->GetFunctionReference();

        // Create the test block.
        Block* testBlock = nullptr;
        auto targetComparison = CreateTargetComparison(instr->TargetOp(),
                                                       targetFunctionRef);

        if(i == 0) {
            // The first comparison is inserted in the original block.
            testBlock = originalBlock;
        }
        else if((i < (targetEdges.Count() - 1)) || hasUnpromotedTargets) {
            // Create a new block for the other comparisons.
            testBlock = CreateTestBlock(symbols, previousBlock);
        }

        if(testBlock) {
            testBlock->InsertInstruction(targetComparison);
            testBlocks.Add(testBlock);
            previousBlock = testBlock;
        }

        // Create the call block.
        Block* callBlock = CreateCallBlock(symbols, previousBlock);
        auto callInstr = CreateTargetCall(targetFunctionRef, instr);
        createdCalls.Add(callInstr);

        callBlock->InsertInstruction(callInstr);
        callBlock->InsertInstruction(CreateGoto(continuationBlock));
        callBlocks.Add(callBlock);
        previousBlock = callBlock;
    }

    // If there are calls to unpromoted targets (or to Unknown)
    // create a block where the original 'call' is cloned.
    // This block is executed if none of the known targets match.
    if(hasUnpromotedTargets) {
        auto unknownBlock = CreateCallBlock(symbols, previousBlock);
        callBlocks.Add(unknownBlock);

        auto callInstr = CreateTargetCall(instr->TargetOp(), instr);
        createdCalls.Add(callInstr);

        unknownBlock->InsertInstruction(callInstr);
        unknownBlock->InsertInstruction(CreateGoto(continuationBlock));
    }

    // Connect the generated blocks so that the targets
    // are tested in a linear order, most frequently called first.
    ConnectGeneratedBlocks(testBlocks, callBlocks);

    // Create a 'phi' in the continuation block that merges
    // the values returned by each of the created calls.
    MergeReturnedValues(callBlocks, continuationBlock, instr);

    // Create a new call site for each new call
    // and delete the one associated with the original one.
    UpdateCallGraph(createdCalls, instr);
    
    // The original 'call' is no longer needed.
    instr->RemoveFromBlock(true /* free */);
}
Ejemplo n.º 11
0
void RemoveCriticalThunks(void)
{
    int i;
    for (i=0; i < blockCount; i++)
    {
        BLOCK *b = blockArray[i];
        if (b && i != exitBlock && !b->critical && !b->dead)
        {
            QUAD *bjmp = beforeJmp(b->tail, FALSE);
            if (bjmp->dc.opcode == i_coswitch)
            {
                
                QUAD *i = bjmp;
                BLOCKLIST *sl = b->succ;
                while (sl)
                {
                    BLOCK *s = sl->block;
                    if (s->critical)
                    {
                        s->critical = FALSE;
                        if (s->head->fwd != s->tail)
                        {
                            int lbl = nextLabel++;
                            MoveBlockTo(s);
                            InsertLabel(s, lbl);
                            i->dc.v.label = lbl;
                        }
                        else
                        {
                            UnlinkCritical(s);
                        }
                    }
                    i = i->fwd;
                    sl = sl->next;
                }
            }
            else if (bjmp->dc.opcode >= i_jne && bjmp->dc.opcode <= i_jge)
            {
                BLOCK *s = b->succ->block;
                BLOCK *n = b->succ->next->block;
                if (s->critical)
                {
                    s->critical = FALSE;
                    if (s->head->fwd != s->tail)
                    {
                        MoveBlockTo(s);
                        if (n->critical)
                        {
                            n->critical = FALSE;
                            if (n->head->fwd != n->tail)
                            {
                                int lbl = nextLabel++;
                                InsertLabel(b->succ->block, lbl);
                                bjmp->dc.v.label = lbl;
                                SwapBranchSense(bjmp);
                                MoveBlockTo(n);
                            }
                            else
                            {
                                UnlinkCritical(n);
                            }
                        }
                    }
                    else 
                    {
                        UnlinkCritical(s);
                        if (n->critical)
                        {
                            n->critical = FALSE;
                            if (n->head->fwd != n->tail)
                            {
                                int lbl = nextLabel ++;
                                bjmp->dc.v.label = lbl;
                                InsertLabel(b->succ->block, lbl);			
                                SwapBranchSense(bjmp);
                                MoveBlockTo(n);
                            }
                            else
                            {
                                UnlinkCritical(n);
                            }
                        }
                    }
                }
                else if (n->critical)
                {
                    n->critical = FALSE;
                    if (n->head->fwd != n->tail)
                    {
                        int lbl = nextLabel ++;
                        bjmp->dc.v.label = lbl;
                        InsertLabel(b->succ->block, lbl);			
                        SwapBranchSense(bjmp);
                        MoveBlockTo(n);
                    }
                    else
                    {
                        UnlinkCritical(n);
                    }
                }
            }
            else if (b->succ->block->critical)
            {
                BLOCK *s = b->succ->block;
                s->critical = FALSE;
                if (b->succ->next)
                    diag("RemoveCritical - invalid flow");
                if (s->head->fwd != s->tail)
                {
                    MoveBlockTo(s);
                    if (bjmp->dc.opcode == i_goto)
                    {
                        RemoveInstruction(bjmp);
                    }
                }
                else
                {
                    UnlinkCritical(s);
                }
            }
        }
    }
}
Ejemplo n.º 12
0
static void scan_gotos(QUAD *head)
/*
 * make a list of goto statements
 */
{
    while (head)
    {
        switch (head->dc.opcode)
        {
            case i_jc:
            case i_jnc:
            case i_jbe:
            case i_ja:
            case i_je:
            case i_jne:
            case i_jge:
            case i_jg:
            case i_jle:
            case i_jl:
                if (head->dc.left->mode == i_immed && head->dc.right->mode == i_immed && !(chosenAssembler->msil))
                {
                    if (isintconst(head->dc.left->offset) && isintconst(head->dc.right->offset))
                    {
                        LLONG_TYPE l = head->dc.left->offset->v.i;
                        LLONG_TYPE r = head->dc.right->offset->v.i;
                        int ok ;
                        switch (head->dc.opcode)
                        {
                            case i_jc:
                                ok = (ULLONG_TYPE)l < (ULLONG_TYPE)r;
                                break ;
                            case i_jnc:
                                ok = (ULLONG_TYPE)l >= (ULLONG_TYPE)r;
                                break ;
                            case i_jbe:
                                ok = (ULLONG_TYPE)l <= (ULLONG_TYPE)r;
                                break ;
                            case i_ja:
                                ok = (ULLONG_TYPE)l > (ULLONG_TYPE)r;
                                break ;
                            case i_je:
                                ok = l == r;
                                break ;
                            case i_jne:
                                ok = l != r;
                                break ;
                            case i_jge:
                                ok = l >= r;
                                break ;
                            case i_jg:
                                ok = l > r;
                                break ;
                            case i_jle:
                                ok = l <= r;
                                break ;
                            case i_jl:
                                ok = l < r;
                                break ;
                            default:
                                break;
                        }
                        if (ok)
                        {
                            head->dc.opcode = i_goto;
                            head->dc.left = head->dc.right = NULL;
                            head->temps &= ~(TEMP_LEFT | TEMP_RIGHT);
                        }
                        else
                            RemoveInstruction(head);
                    }
                }
            case i_swbranch:
            case i_coswitch:
            case i_goto:
                golist[head->dc.v.label - firstLabel] = head;
                break;
            default:
                break;
        }
        head = head->fwd;
    }
}
Ejemplo n.º 13
0
void kill_jumpover(BLOCK *b, QUAD *head)
/*
 * Conditionnal jumps over gotos get squashed here
 */
{
    int newtype;
    QUAD *newhead = head->fwd;
    (void)b;
    while (newhead->dc.opcode == i_block || newhead->dc.opcode == i_blockend || 
           newhead->dc.opcode == i_dbgblock || newhead->dc.opcode == i_dbgblockend ||
           newhead->ignoreMe)
    {
        newhead = newhead->fwd;
    }
    /* if followed by while will be voided by intervening labels */
    if (newhead->dc.opcode == i_goto)
    {
        QUAD *fwd = newhead->fwd;
        while (fwd->dc.opcode == i_block || fwd->dc.opcode == i_blockend ||
               newhead->dc.opcode == i_dbgblock || newhead->dc.opcode == i_dbgblockend ||
               fwd->dc.opcode == i_label || fwd->ignoreMe)
        {
            if (fwd->dc.opcode == i_label && head->dc.v.label == fwd->dc.v.label)
                break;
            fwd = fwd->fwd;
        }
                
        if (fwd->dc.opcode != i_label)
            return;
        /* if it was a goto and we are branching around it, 
         * swap the conditional type and 
         * put the new label in the goto statement 
         */
        head->dc.v.label = newhead->dc.v.label;
        RemoveInstruction(newhead);
        switch (head->dc.opcode)
        {
            case i_jc:
                newtype = i_jnc;
                break;
            case i_jnc:
                newtype = i_jc;
                break;
            case i_jbe:
                newtype = i_ja;
                break;
            case i_ja:
                newtype = i_jbe;
                break;
            case i_je:
                newtype = i_jne;
                break;
            case i_jne:
                newtype = i_je;
                break;
            case i_jge:
                newtype = i_jl;
                break;
            case i_jg:
                newtype = i_jle;
                break;
            case i_jle:
                newtype = i_jg;
                break;
            case i_jl:
                newtype = i_jge;
                break;
            default:
                break;
        }
        /* remove the goto */
        head->dc.opcode = newtype;
        while (1) {
            while (newhead && (newhead->dc.opcode == i_block || newhead->ignoreMe 
                   || newhead->dc.opcode == i_dbgblock || newhead->dc.opcode == i_dbgblockend
                   || newhead->dc.opcode == i_blockend)) {
                newhead = newhead->fwd;
            }
            if (!newhead || newhead->dc.opcode != i_goto)
                break;
            RemoveInstruction(newhead);
            newhead = newhead->fwd;
        }
    }
}
Ejemplo n.º 14
0
void removeDead(BLOCK *b)
{
    static BRIGGS_SET *live;
    BITINT *p;
    int j,k;
    QUAD *tail;
    BLOCKLIST *bl;
    BOOL done = FALSE;
    if (b == blockArray[0])
    {
        int i;
        liveVariables();
        live = briggsAlloc(tempCount);
        for (i=0; i < blockCount; i++)
            if (blockArray[i])
            {
                QUAD *tail = blockArray[i]->head;
                while (tail != blockArray[i]->tail->fwd)
                {
                    tail->live = tail->alwayslive;
                    tail = tail->fwd;
                }
                blockArray[i]->visiteddfst = FALSE;
            }
    }
    b->visiteddfst = TRUE;
    briggsClear(live);
    p = b->liveOut;
    for (j=0; j < (tempCount + BITINTBITS-1)/BITINTBITS; j++,p++)
        if (*p)
            for (k=0; k < BITINTBITS; k++)
                if (*p & (1 << k))
                {
                    briggsSet(live, j*BITINTBITS + k);
                }
    tail = b->tail;
    while (tail != b->head->back)
    {
        markLiveInstruction(live, tail);
        tail = tail->back;
    }
    bl = b->succ;
    while (bl)
    {
        if (!bl->block->visiteddfst)
            removeDead(bl->block);
        bl = bl->next;
    }
    if (b == blockArray[0])
    {
        QUAD *head = intermed_head;
        BOOL changed = FALSE;
        int i;
        for (i=0; i < blockCount; i++)
        {
            BLOCK *b1 = blockArray[i];
            if (b1)
            {
                QUAD *head = b1->head;
                while (head != b1->tail->fwd)
                {
                    if (!head->live)
                    {
                        if (head->dc.opcode != i_block && !head->ignoreMe && head->dc.opcode != i_label)
                        {
                            changed = TRUE;
                            RemoveInstruction(head);
                            if (head->dc.opcode == i_coswitch || head->dc.opcode >= i_jne && head->dc.opcode <= i_jge)//FIXME && ||
                            {
                                BLOCKLIST *bl = head->block->succ->next;
                                head->block->succ->next = NULL;
                                while (bl)
                                {
                                    if (bl->block->critical)
                                        UnlinkCritical(bl->block);
                                    bl = bl->next;
                                }
                            }
                        }
                    }
                    head = head->fwd;
                }
            }
        }
        if (changed)
        {
            removeDead(b);
        }
    }
}