Example #1
0
const Vector<GPRReg>& gprsInPriorityOrder()
{
    static Vector<GPRReg>* result;
    static std::once_flag once;
    std::call_once(
        once,
        [] {
            result = new Vector<GPRReg>();
            RegisterSet all = RegisterSet::allGPRs();
            all.exclude(RegisterSet::stackRegisters());
            all.exclude(RegisterSet::reservedHardwareRegisters());
            RegisterSet calleeSave = RegisterSet::calleeSaveRegisters();
            all.forEach(
                [&] (Reg reg) {
                    if (!calleeSave.get(reg))
                        result->append(reg.gpr());
                });
            all.forEach(
                [&] (Reg reg) {
                    if (calleeSave.get(reg))
                        result->append(reg.gpr());
                });
        });
    return *result;
}
Example #2
0
const Vector<FPRReg>& fprsInPriorityOrder()
{
    static Vector<FPRReg>* result;
    static std::once_flag once;
    std::call_once(
        once,
        [] {
            result = new Vector<FPRReg>();
            RegisterSet all = RegisterSet::allFPRs();
            RegisterSet calleeSave = RegisterSet::calleeSaveRegisters();
            all.forEach(
                [&] (Reg reg) {
                    if (!calleeSave.get(reg))
                        result->append(reg.fpr());
                });
            all.forEach(
                [&] (Reg reg) {
                    if (calleeSave.get(reg))
                        result->append(reg.fpr());
                });
        });
    return *result;
}
void fixPartialRegisterStalls(Code& code)
{
    if (!isX86())
        return;

    PhaseScope phaseScope(code, "fixPartialRegisterStalls");

    Vector<BasicBlock*> candidates;

    for (BasicBlock* block : code) {
        for (const Inst& inst : *block) {
            if (hasPartialXmmRegUpdate(inst)) {
                candidates.append(block);
                break;
            }
        }
    }

    // Fortunately, Partial Stalls are rarely used. Return early if no block
    // cares about them.
    if (candidates.isEmpty())
        return;

    // For each block, this provides the distance to the last instruction setting each register
    // on block *entry*.
    IndexMap<BasicBlock, FPDefDistance> lastDefDistance(code.size());

    // Blocks with dirty distance at head.
    IndexSet<BasicBlock> dirty;

    // First, we compute the local distance for each block and push it to the successors.
    for (BasicBlock* block : code) {
        FPDefDistance localDistance;

        unsigned distanceToBlockEnd = block->size();
        for (Inst& inst : *block)
            updateDistances(inst, localDistance, distanceToBlockEnd);

        for (BasicBlock* successor : block->successorBlocks()) {
            if (lastDefDistance[successor].updateFromPrecessor(localDistance))
                dirty.add(successor);
        }
    }

    // Now we propagate the minimums accross blocks.
    bool changed;
    do {
        changed = false;

        for (BasicBlock* block : code) {
            if (!dirty.remove(block))
                continue;

            // Little shortcut: if the block is big enough, propagating it won't add any information.
            if (block->size() >= minimumSafeDistance)
                continue;

            unsigned blockSize = block->size();
            FPDefDistance& blockDistance = lastDefDistance[block];
            for (BasicBlock* successor : block->successorBlocks()) {
                if (lastDefDistance[successor].updateFromPrecessor(blockDistance, blockSize)) {
                    dirty.add(successor);
                    changed = true;
                }
            }
        }
    } while (changed);

    // Finally, update each block as needed.
    InsertionSet insertionSet(code);
    for (BasicBlock* block : candidates) {
        unsigned distanceToBlockEnd = block->size();
        FPDefDistance& localDistance = lastDefDistance[block];

        for (unsigned i = 0; i < block->size(); ++i) {
            Inst& inst = block->at(i);

            if (hasPartialXmmRegUpdate(inst)) {
                RegisterSet defs;
                RegisterSet uses;
                inst.forEachTmp([&] (Tmp& tmp, Arg::Role role, Arg::Type) {
                    if (tmp.isFPR()) {
                        if (Arg::isDef(role))
                            defs.set(tmp.fpr());
                        if (Arg::isAnyUse(role))
                            uses.set(tmp.fpr());
                    }
                });
                // We only care about values we define but not use. Otherwise we have to wait
                // for the value to be resolved anyway.
                defs.exclude(uses);

                defs.forEach([&] (Reg reg) {
                    if (localDistance.distance[MacroAssembler::fpRegisterIndex(reg.fpr())] < minimumSafeDistance)
                        insertionSet.insert(i, MoveZeroToDouble, inst.origin, Tmp(reg));
                });
            }

            updateDistances(inst, localDistance, distanceToBlockEnd);
        }
        insertionSet.execute(block);
    }
}
void logRegisterPressure(Code& code)
{
    const unsigned totalColumns = 200;
    const unsigned registerColumns = 100;
    
    RegLiveness liveness(code);

    for (BasicBlock* block : code) {
        RegLiveness::LocalCalc localCalc(liveness, block);

        block->dumpHeader(WTF::dataFile());

        Vector<CString> instDumps;
        for (unsigned instIndex = block->size(); instIndex--;) {
            Inst& inst = block->at(instIndex);
            Inst* prevInst = block->get(instIndex - 1);

            localCalc.execute(instIndex);

            RegisterSet set;
            set.setAll(localCalc.live());
            Inst::forEachDefWithExtraClobberedRegs<Reg>(
                prevInst, &inst,
                [&] (Reg reg, Arg::Role, Arg::Type, Arg::Width) {
                    set.set(reg);
                });

            StringPrintStream instOut;
            StringPrintStream lineOut;
            lineOut.print("   ");
            if (set.numberOfSetRegisters()) {
                set.forEach(
                    [&] (Reg reg) {
                        CString text = toCString(" ", reg);
                        if (text.length() + lineOut.length() > totalColumns) {
                            instOut.print(lineOut.toCString(), "\n");
                            lineOut.reset();
                            lineOut.print("       ");
                        }
                        lineOut.print(text);
                    });
                lineOut.print(":");
            }
            if (lineOut.length() > registerColumns) {
                instOut.print(lineOut.toCString(), "\n");
                lineOut.reset();
            }
            while (lineOut.length() < registerColumns)
                lineOut.print(" ");
            lineOut.print(" ");
            lineOut.print(inst);
            instOut.print(lineOut.toCString(), "\n");
            instDumps.append(instOut.toCString());
        }

        for (unsigned i = instDumps.size(); i--;)
            dataLog(instDumps[i]);
        
        block->dumpFooter(WTF::dataFile());
    }
}