Add a hack to avoid some horrible code in some cases by always emitting

token chains first.  For this C function:

int test() {
  int i;
  for (i = 0; i < 100000; ++i)
    foo();
}

Instead of emitting this (condition before call)

.LBB_test_1:    ; no_exit
        addi r30, r30, 1
        lis r2, 1
        ori r2, r2, 34464
        cmpw cr2, r30, r2
        bl L_foo$stub
        bne cr2, .LBB_test_1    ; no_exit

Emit this:

.LBB_test_1:    ; no_exit
        bl L_foo$stub
        addi r30, r30, 1
        lis r2, 1
        ori r2, r2, 34464
        cmpw cr0, r30, r2
        bne cr0, .LBB_test_1    ; no_exit

Which makes it so we don't have to save/restore cr2 in the prolog/epilog of
the function.

This also makes the code much more similar to what the pattern isel produces.

llvm-svn: 23135
This commit is contained in:
Chris Lattner 2005-08-29 23:21:29 +00:00
parent 0d45ee4a06
commit f7e5ec84c6
1 changed files with 31 additions and 12 deletions

View File

@ -97,6 +97,7 @@ unsigned SimpleSched::Emit(SDOperand Op) {
while (NodeOperands &&
Op.getOperand(NodeOperands-1).getValueType() == MVT::Flag)
--NodeOperands;
if (NodeOperands && // Ignore chain if it exists.
Op.getOperand(NodeOperands-1).getValueType() == MVT::Other)
--NodeOperands;
@ -125,18 +126,24 @@ unsigned SimpleSched::Emit(SDOperand Op) {
}
}
// Emit all of the operands of this instruction, adding them to the
// If there is a token chain operand, emit it first, as a hack to get avoid
// really bad cases.
if (Op.getNumOperands() > NodeOperands &&
Op.getOperand(NodeOperands).getValueType() == MVT::Other)
Emit(Op.getOperand(NodeOperands));
// Emit all of the actual operands of this instruction, adding them to the
// instruction as appropriate.
for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) {
for (unsigned i = 0; i != NodeOperands; ++i) {
if (Op.getOperand(i).isTargetOpcode()) {
// Note that this case is redundant with the final else block, but we
// include it because it is the most common and it makes the logic
// simpler here.
unsigned R = Emit(Op.getOperand(i));
// Add an operand, unless this corresponds to a chain or flag node.
MVT::ValueType VT = Op.getOperand(i).getValueType();
if (VT != MVT::Other && VT != MVT::Flag)
MI->addRegOperand(R, MachineOperand::Use);
assert(Op.getOperand(i).getValueType() != MVT::Other &&
Op.getOperand(i).getValueType() != MVT::Flag &&
"Chain and flag operands should occur at end of operand list!");
MI->addRegOperand(Emit(Op.getOperand(i)), MachineOperand::Use);
} else if (ConstantSDNode *C =
dyn_cast<ConstantSDNode>(Op.getOperand(i))) {
MI->addZeroExtImm64Operand(C->getValue());
@ -159,14 +166,26 @@ unsigned SimpleSched::Emit(SDOperand Op) {
dyn_cast<ExternalSymbolSDNode>(Op.getOperand(i))) {
MI->addExternalSymbolOperand(ES->getSymbol(), false);
} else {
unsigned R = Emit(Op.getOperand(i));
// Add an operand, unless this corresponds to a chain or flag node.
MVT::ValueType VT = Op.getOperand(i).getValueType();
if (VT != MVT::Other && VT != MVT::Flag)
MI->addRegOperand(R, MachineOperand::Use);
assert(Op.getOperand(i).getValueType() != MVT::Other &&
Op.getOperand(i).getValueType() != MVT::Flag &&
"Chain and flag operands should occur at end of operand list!");
MI->addRegOperand(Emit(Op.getOperand(i)), MachineOperand::Use);
}
}
// Finally, if this node has any flag operands, we *must* emit them last, to
// avoid emitting operations that might clobber the flags.
if (Op.getNumOperands() > NodeOperands) {
unsigned i = NodeOperands;
if (Op.getOperand(i).getValueType() == MVT::Other)
++i; // the chain is already selected.
for (; i != Op.getNumOperands(); ++i) {
assert(Op.getOperand(i).getValueType() == MVT::Flag &&
"Must be flag operands!");
Emit(Op.getOperand(i));
}
}
// Now that we have emitted all operands, emit this instruction itself.
if ((II.Flags & M_USES_CUSTOM_DAG_SCHED_INSERTION) == 0) {
BB->insert(BB->end(), MI);