diff options
author | Misha Brukman <brukman+llvm@gmail.com> | 2003-07-15 21:00:32 +0000 |
---|---|---|
committer | Misha Brukman <brukman+llvm@gmail.com> | 2003-07-15 21:00:32 +0000 |
commit | 7eac4766b156ad2965125a7ee3f1f4834dfbb00b (patch) | |
tree | 03ecb71eb0b878deb2ef5124a0aeb4002b31c826 /utils/TableGen/CodeEmitterGen.cpp | |
parent | 07d4516f92e866ec7900146789333a819f4f06df (diff) |
This optimization greatly enhances efficiency of creating new instructions by
masking and shifting operands directly into their place in the instruction,
instead of the old-fashioned way of ORing in each bit separately.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@7179 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils/TableGen/CodeEmitterGen.cpp')
-rw-r--r-- | utils/TableGen/CodeEmitterGen.cpp | 112 |
1 files changed, 106 insertions, 6 deletions
diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index 9d0d939c9d..8cb7979333 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -59,6 +59,7 @@ void CodeEmitterGen::createEmitter(std::ostream &o) { // unsigned op = 0; std::map<const std::string,unsigned> OpOrder; + std::map<const std::string,bool> OpContinuous; for (unsigned i = 0, e = Vals.size(); i != e; ++i) { if (Vals[i].getName() != "Inst" && !Vals[i].getValue()->isComplete() && @@ -71,6 +72,90 @@ void CodeEmitterGen::createEmitter(std::ostream &o) { <<" = getMachineOpValue(MI, MI.getOperand("<<op<<"));\n"; //<< " MachineOperand &op" << op <<" = MI.getOperand("<<op<<");\n"; OpOrder[Vals[i].getName()] = op++; + + // Is the operand continuous? If so, we can just mask and OR it in + // instead of doing it bit-by-bit, saving a lot in runtime cost. + const BitsInit *InstInit = BI; + int beginBitInVar = -1, endBitInVar = -1, + beginBitInInst = -1, endBitInInst = -1; + bool continuous = true; + + for (int bit = InstInit->getNumBits()-1; bit >= 0; --bit) { + if (VarBitInit *VBI = + dynamic_cast<VarBitInit*>(InstInit->getBit(bit))) { + TypedInit *TI = VBI->getVariable(); + if (VarInit *VI = dynamic_cast<VarInit*>(TI)) { + // only process the current variable + if (VI->getName() != Vals[i].getName()) + continue; + + if (beginBitInVar == -1) + beginBitInVar = VBI->getBitNum(); + + if (endBitInVar == -1) + endBitInVar = VBI->getBitNum(); + else { + if (endBitInVar == (int)VBI->getBitNum() + 1) + endBitInVar = VBI->getBitNum(); + else { + continuous = false; + break; + } + } + + if (beginBitInInst == -1) + beginBitInInst = bit; + if (endBitInInst == -1) + endBitInInst = bit; + else { + if (endBitInInst == bit + 1) + endBitInInst = bit; + else { + continuous = false; + break; + } + } + + // maintain same distance between bits in field and bits in + // instruction. if the relative distances stay the same + // throughout, + if ((beginBitInVar - (int)VBI->getBitNum()) != + (beginBitInInst - bit)) + { + continuous = false; + break; + } + } + } + } + + if (continuous) { + o << " // continuous: op" << OpOrder[Vals[i].getName()] << "\n"; + + // Mask off the right bits + // Low mask (ie. shift, if necessary) + if (endBitInVar != 0) { + o << " op" << OpOrder[Vals[i].getName()] + << " >>= endBitInVar;\n"; + beginBitInVar -= endBitInVar; + endBitInVar = 0; + } + + // High mask + o << " op" << OpOrder[Vals[i].getName()] + << " &= (1<<" << beginBitInVar+1 << ") - 1;\n"; + + // Shift the value to the correct place (according to place in instr) + if (endBitInInst != 0) + o << " op" << OpOrder[Vals[i].getName()] + << " <<= " << endBitInInst << ";\n"; + + // Just OR in the result + o << " Value |= op" << OpOrder[Vals[i].getName()] << ";\n"; + } + + // otherwise, will be taken care of in the loop below using this value: + OpContinuous[Vals[i].getName()] = continuous; } } @@ -81,18 +166,32 @@ void CodeEmitterGen::createEmitter(std::ostream &o) { // Scan through the field looking for bit initializers of the current // variable... for (int i = FieldInitializer->getNumBits()-1; i >= 0; --i) { - if (BitInit *BI=dynamic_cast<BitInit*>(FieldInitializer->getBit(i))){ + if (BitInit *BI=dynamic_cast<BitInit*>(FieldInitializer->getBit(i))) + { o << " // bit init: f: " << f << ", i: " << i << "\n"; - } else if (UnsetInit *UI = + } else if (UnsetInit *UI = dynamic_cast<UnsetInit*>(FieldInitializer->getBit(i))) { o << " // unset init: f: " << f << ", i: " << i << "\n"; } else if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(FieldInitializer->getBit(i))) { TypedInit *TI = VBI->getVariable(); if (VarInit *VI = dynamic_cast<VarInit*>(TI)) { - o << " Value |= getValueBit(op" << OpOrder[VI->getName()] - << ", " << VBI->getBitNum() - << ")" << " << " << i << ";\n"; + // If the bits of the field are laid out consecutively in the + // instruction, then instead of separately ORing in bits, just + // mask and shift the entire field for efficiency. + if (OpContinuous[VI->getName()]) { + // already taken care of in the loop above, thus there is no + // need to individually OR in the bits + + // for debugging, output the regular version anyway, commented + o << " // Value |= getValueBit(op" + << OpOrder[VI->getName()] << ", " << VBI->getBitNum() + << ")" << " << " << i << ";\n"; + } else { + o << " Value |= getValueBit(op" << OpOrder[VI->getName()] + << ", " << VBI->getBitNum() + << ")" << " << " << i << ";\n"; + } } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) { // FIXME: implement this! o << "FIELD INIT not implemented yet!\n"; @@ -100,7 +199,7 @@ void CodeEmitterGen::createEmitter(std::ostream &o) { o << "Error: UNIMPLEMENTED\n"; } } - } + } } else { // ignore annul and predict bits since no one sets them yet if (Vals[f].getName() == "annul" || Vals[f].getName() == "predict") { @@ -112,6 +211,7 @@ void CodeEmitterGen::createEmitter(std::ostream &o) { o << " break;\n" << " }\n"; } + o << " default:\n" << " DEBUG(std::cerr << \"Not supported instr: \" << MI << \"\\n\");\n" << " abort();\n" |