[llvm-commits] [llvm] r119129 - in /llvm/trunk/utils/TableGen: CodeEmitterGen.cpp CodeEmitterGen.h
Chris Lattner
sabre at nondot.org
Sun Nov 14 22:59:17 PST 2010
Author: lattner
Date: Mon Nov 15 00:59:17 2010
New Revision: 119129
URL: http://llvm.org/viewvc/llvm-project?rev=119129&view=rev
Log:
split the giant encoder loop into two new helper functions.
Modified:
llvm/trunk/utils/TableGen/CodeEmitterGen.cpp
llvm/trunk/utils/TableGen/CodeEmitterGen.h
Modified: llvm/trunk/utils/TableGen/CodeEmitterGen.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeEmitterGen.cpp?rev=119129&r1=119128&r2=119129&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CodeEmitterGen.cpp (original)
+++ llvm/trunk/utils/TableGen/CodeEmitterGen.cpp Mon Nov 15 00:59:17 2010
@@ -61,7 +61,7 @@
// If the VarBitInit at position 'bit' matches the specified variable then
// return the variable bit position. Otherwise return -1.
int CodeEmitterGen::getVariableBit(const std::string &VarName,
- BitsInit *BI, int bit) {
+ BitsInit *BI, int bit) {
if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(BI->getBit(bit)))
if (VarInit *VI = dynamic_cast<VarInit*>(VBI->getVariable()))
if (VI->getName() == VarName)
@@ -70,6 +70,123 @@
return -1;
}
+void CodeEmitterGen::
+AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName,
+ unsigned &NumberedOp,
+ std::string &Case, CodeGenTarget &Target) {
+ bool gotOp = false;
+ CodeGenInstruction &CGI = Target.getInstruction(R);
+
+ for (int bit = BI->getNumBits()-1; bit >= 0; ) {
+ int varBit = getVariableBit(VarName, BI, bit);
+
+ // If this bit isn't from a variable, skip it.
+ if (varBit == -1) {
+ --bit;
+ continue;
+ }
+
+ // Figure out the consequtive range of bits covered by this operand, in
+ // order to generate better encoding code.
+ int beginInstBit = bit;
+ int beginVarBit = varBit;
+ int N = 1;
+ for (--bit; bit >= 0;) {
+ varBit = getVariableBit(VarName, BI, bit);
+ if (varBit == -1 || varBit != (beginVarBit - N)) break;
+ ++N;
+ --bit;
+ }
+
+ if (!gotOp) {
+ // If the operand matches by name, reference according to that
+ // operand number. Non-matching operands are assumed to be in
+ // order.
+ unsigned OpIdx;
+ if (CGI.Operands.hasOperandNamed(VarName, OpIdx)) {
+ // Get the machine operand number for the indicated operand.
+ OpIdx = CGI.Operands[OpIdx].MIOperandNo;
+ assert(!CGI.Operands.isFlatOperandNotEmitted(OpIdx) &&
+ "Explicitly used operand also marked as not emitted!");
+ } else {
+ /// If this operand is not supposed to be emitted by the
+ /// generated emitter, skip it.
+ while (CGI.Operands.isFlatOperandNotEmitted(NumberedOp))
+ ++NumberedOp;
+ OpIdx = NumberedOp++;
+ }
+ std::pair<unsigned, unsigned> SO =CGI.Operands.getSubOperandNumber(OpIdx);
+ std::string &EncoderMethodName = CGI.Operands[SO.first].EncoderMethodName;
+
+ // If the source operand has a custom encoder, use it. This will
+ // get the encoding for all of the suboperands.
+ if (!EncoderMethodName.empty()) {
+ // A custom encoder has all of the information for the
+ // sub-operands, if there are more than one, so only
+ // query the encoder once per source operand.
+ if (SO.second == 0) {
+ Case += " // op: " + VarName + "\n"
+ + " op = " + EncoderMethodName + "(MI, "
+ + utostr(OpIdx);
+ if (MCEmitter)
+ Case += ", Fixups";
+ Case += ");\n";
+ }
+ } else {
+ Case += " // op: " + VarName + "\n" +
+ " op = getMachineOpValue(MI, MI.getOperand(" +
+ utostr(OpIdx) + ")";
+ if (MCEmitter)
+ Case += ", Fixups";
+ Case += ");\n";
+ }
+ gotOp = true;
+ }
+
+ unsigned opMask = ~0U >> (32-N);
+ int opShift = beginVarBit - N + 1;
+ opMask <<= opShift;
+ opShift = beginInstBit - beginVarBit;
+
+ if (opShift > 0) {
+ Case += " Value |= (op & " + utostr(opMask) + "U) << " +
+ itostr(opShift) + ";\n";
+ } else if (opShift < 0) {
+ Case += " Value |= (op & " + utostr(opMask) + "U) >> " +
+ itostr(-opShift) + ";\n";
+ } else {
+ Case += " Value |= op & " + utostr(opMask) + "U;\n";
+ }
+ }
+}
+
+
+std::string CodeEmitterGen::getInstructionCase(Record *R,
+ CodeGenTarget &Target) {
+ std::string Case;
+
+ BitsInit *BI = R->getValueAsBitsInit("Inst");
+ const std::vector<RecordVal> &Vals = R->getValues();
+ unsigned NumberedOp = 0;
+
+ // Loop over all of the fields in the instruction, determining which are the
+ // operands to the instruction.
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
+ // Ignore fixed fields in the record, we're looking for values like:
+ // bits<5> RST = { ?, ?, ?, ?, ? };
+ if (Vals[i].getPrefix() || Vals[i].getValue()->isComplete())
+ continue;
+
+ AddCodeToMergeInOperand(R, BI, Vals[i].getName(), NumberedOp, Case, Target);
+ }
+
+ std::string PostEmitter = R->getValueAsString("PostEncoderMethod");
+ if (!PostEmitter.empty())
+ Case += " Value = " + PostEmitter + "(MI, Value);\n";
+
+ return Case;
+}
+
void CodeEmitterGen::run(raw_ostream &o) {
CodeGenTarget Target;
std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
@@ -107,12 +224,11 @@
BitsInit *BI = R->getValueAsBitsInit("Inst");
- // Start by filling in fixed values...
+ // Start by filling in fixed values.
unsigned Value = 0;
for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
- if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) {
+ if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1)))
Value |= B->getValue() << (e-i-1);
- }
}
o << " " << Value << "U," << '\t' << "// " << R->getName() << "\n";
}
@@ -128,115 +244,9 @@
if (R->getValueAsString("Namespace") == "TargetOpcode")
continue;
const std::string &InstName = R->getName();
- std::string Case("");
-
- BitsInit *BI = R->getValueAsBitsInit("Inst");
- const std::vector<RecordVal> &Vals = R->getValues();
- CodeGenInstruction &CGI = Target.getInstruction(R);
-
- // Loop over all of the fields in the instruction, determining which are the
- // operands to the instruction.
- unsigned NumberedOp = 0;
- for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
- // Ignore fixed fields.
- if (Vals[i].getPrefix() || Vals[i].getValue()->isComplete())
- continue;
-
- // 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 std::string &VarName = Vals[i].getName();
- bool gotOp = false;
-
- for (int bit = BI->getNumBits()-1; bit >= 0; ) {
- int varBit = getVariableBit(VarName, BI, bit);
-
- // If this bit isn't from a variable, skip it.
- if (varBit == -1) {
- --bit;
- continue;
- }
-
- int beginInstBit = bit;
- int beginVarBit = varBit;
- int N = 1;
-
- for (--bit; bit >= 0;) {
- varBit = getVariableBit(VarName, BI, bit);
- if (varBit == -1 || varBit != (beginVarBit - N)) break;
- ++N;
- --bit;
- }
-
- if (!gotOp) {
- // If the operand matches by name, reference according to that
- // operand number. Non-matching operands are assumed to be in
- // order.
- unsigned OpIdx;
- if (CGI.Operands.hasOperandNamed(VarName, OpIdx)) {
- // Get the machine operand number for the indicated operand.
- OpIdx = CGI.Operands[OpIdx].MIOperandNo;
- assert (!CGI.Operands.isFlatOperandNotEmitted(OpIdx) &&
- "Explicitly used operand also marked as not emitted!");
- } else {
- /// If this operand is not supposed to be emitted by the
- /// generated emitter, skip it.
- while (CGI.Operands.isFlatOperandNotEmitted(NumberedOp))
- ++NumberedOp;
- OpIdx = NumberedOp++;
- }
- std::pair<unsigned, unsigned> SO =
- CGI.Operands.getSubOperandNumber(OpIdx);
- std::string &EncoderMethodName =
- CGI.Operands[SO.first].EncoderMethodName;
-
- // If the source operand has a custom encoder, use it. This will
- // get the encoding for all of the suboperands.
- if (!EncoderMethodName.empty()) {
- // A custom encoder has all of the information for the
- // sub-operands, if there are more than one, so only
- // query the encoder once per source operand.
- if (SO.second == 0) {
- Case += " // op: " + VarName + "\n"
- + " op = " + EncoderMethodName + "(MI, "
- + utostr(OpIdx);
- if (MCEmitter)
- Case += ", Fixups";
- Case += ");\n";
- }
- } else {
- Case += " // op: " + VarName + "\n"
- + " op = getMachineOpValue(MI, MI.getOperand("
- + utostr(OpIdx) + ")";
- if (MCEmitter)
- Case += ", Fixups";
- Case += ");\n";
- }
- gotOp = true;
- }
-
- unsigned opMask = ~0U >> (32-N);
- int opShift = beginVarBit - N + 1;
- opMask <<= opShift;
- opShift = beginInstBit - beginVarBit;
-
- if (opShift > 0) {
- Case += " Value |= (op & " + utostr(opMask) + "U) << "
- + itostr(opShift) + ";\n";
- } else if (opShift < 0) {
- Case += " Value |= (op & " + utostr(opMask) + "U) >> "
- + itostr(-opShift) + ";\n";
- } else {
- Case += " Value |= op & " + utostr(opMask) + "U;\n";
- }
- }
- }
-
- std::string PostEmitter = R->getValueAsString("PostEncoderMethod");
- if (!PostEmitter.empty())
- Case += " Value = " + PostEmitter + "(MI, Value);\n";
+ std::string Case = getInstructionCase(R, Target);
- std::vector<std::string> &InstList = CaseMap[Case];
- InstList.push_back(InstName);
+ CaseMap[Case].push_back(InstName);
}
// Emit initial function code
Modified: llvm/trunk/utils/TableGen/CodeEmitterGen.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeEmitterGen.h?rev=119129&r1=119128&r2=119129&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CodeEmitterGen.h (original)
+++ llvm/trunk/utils/TableGen/CodeEmitterGen.h Mon Nov 15 00:59:17 2010
@@ -23,6 +23,7 @@
class RecordVal;
class BitsInit;
+class CodeGenTarget;
class CodeEmitterGen : public TableGenBackend {
RecordKeeper &Records;
@@ -36,6 +37,12 @@
void emitGetValueBit(raw_ostream &o, const std::string &Namespace);
void reverseBits(std::vector<Record*> &Insts);
int getVariableBit(const std::string &VarName, BitsInit *BI, int bit);
+ std::string getInstructionCase(Record *R, CodeGenTarget &Target);
+ void
+ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName,
+ unsigned &NumberedOp,
+ std::string &Case, CodeGenTarget &Target);
+
};
} // End llvm namespace
More information about the llvm-commits
mailing list