示例#1
0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Peephole::DoOneIteration(Function* function) {
    bool changed = false;
    int position = 0;
    
    while(position < worklist_.Count()) {
        // Get the instruction at the current position and try to simplify it.
        Instruction* instr = worklist_[position++];

        // Branching instructions don't have any resulting operand,
        // and report a simplification by returning 'true'.
        if(instr->IsBranching()) {
            changed |= ProcessBranching(instr);
            continue;
        }

        // For all other kinds of instructions.
        // If the result is 'nullptr' nothing could be simplified.
        auto result = Simplify(instr);
        if(result == nullptr) continue;

        if(result->IsUndefinedConstant()) {
            if(HandleUndefinedResult(instr)) {
                // The instruction should not be considered below.
                continue;
            }
        }

        // Replace the previous result operand with the new one
        // in all instructions that use it as a source operand.
        instr->GetDestinationOp()->ReplaceWith(result);
        InstructionSimplified(instr, result);
        
        HandleSpecialCases(instr, result);
        changed = true;
#if 1
		IRPrinter(function).Dump();
#endif
    }
	
	// Some instructions may be dead now; delete them here, so that
	// the next iteration doesn't consider them anymore. Note that 
    // this is necessary, else we would enter an infinite loop simplifying
    // the same instructions again and again...
	if(changed) DeleteDeadInstructions(function);
    return changed;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AggregateCopyPropagation::ReplaceWithOriginal(LoadInstr* instr, 
                                                   TOperandToIdDict& availableCopies,
                                                   BitVector& killSet) {
    if(availableCopies.Count() == 0) {
        return;
    }

    // Try to replace each operand with the original one
    // (the one from which the copy was made).
    Instruction* lastInstr = nullptr;
    auto candidateOp = GetBaseOperand(instr->SourceOp(), &lastInstr);

    // Give up if we couldn't find a candidate,
    // or if the candidate is an instruction whose result
    // is used in more than one place.
    if((candidateOp == nullptr) || (lastInstr == nullptr) || 
       (lastInstr->GetDestinationOp()->HasSingleUser() == false)) {
        return;
    }
        
    // We can replace the operand if it's a copy
    // (found in 'availableCopies') and the source or copy
    // was not killed until this point.
    CopySetInfo info;

    if(GetOldestAvailable(candidateOp, availableCopies, killSet, info)) {
        if(info.IsCopy) {
            // Replace the operand with the original.
            auto originalOp = info.Source;
            lastInstr->ReplaceSourceOp(0, originalOp);
            info.Replacements++;
            CopyPropagated(instr);
        }
        else if(instr->HasDestinationOp()) {
            // The load itself is replaced by the value
            // to which the record/array was set.
            auto requiredType = instr->GetDestinationOp()->GetType();
            auto constantOp = CreateConstant(requiredType, info);
            instr->GetDestinationOp()->ReplaceWith(constantOp);
            info.Replacements++;
            CopyPropagated(instr);
        }
    }
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AggregateCopyPropagation::ReplaceWithOriginal(CallInstr* instr, 
                                                   TOperandToIdDict& availableCopies,
                                                   BitVector& killSet) {
    // Check if any of the arguments can be replaced 
    // with the original operand.
    for(int i = 0; i < instr->ArgumentCount(); i++) {
        auto argument = instr->GetArgument(i);
        Instruction* lastInstr = nullptr;
        auto candidateOp = GetBaseOperand(argument, &lastInstr);

        // Give up if we couldn't find a candidate,
        // or if the candidate is used by an instruction 
        // whose result is used in more than one place.
        if((candidateOp == nullptr) || 
           (lastInstr && (lastInstr->GetDestinationOp()->HasSingleUser() == false))) {
           return;
        }

        // Check if this is a copy.
        CopySetInfo info;

        if(GetOldestAvailable(candidateOp, availableCopies, killSet, info)) {
            if(info.IsCopy) {
                // Replace the operand with the original.
                auto originalOp = info.Source;
                info.Replacements++;
                CopyPropagated(instr);

                // If the copy is used by an instruction, we modify
                // that instruction, else we replace the call argument.
                if(lastInstr) {
                    lastInstr->ReplaceSourceOp(0, originalOp);
                }
                else instr->ReplaceArgument(i, originalOp);
            }
        }
    }
}