diff options
author | Dan Gohman <gohman@apple.com> | 2008-04-03 00:02:49 +0000 |
---|---|---|
committer | Dan Gohman <gohman@apple.com> | 2008-04-03 00:02:49 +0000 |
commit | ee4fa1977dd3a495a8857eef924ee5961db765c6 (patch) | |
tree | b915aca8885f38aa53adbffbbbf6d9750d19506c | |
parent | 271515a46d265f9dea123797d20a2140f54d35d3 (diff) | |
download | external_llvm-ee4fa1977dd3a495a8857eef924ee5961db765c6.zip external_llvm-ee4fa1977dd3a495a8857eef924ee5961db765c6.tar.gz external_llvm-ee4fa1977dd3a495a8857eef924ee5961db765c6.tar.bz2 |
Move instruction flag inference out of InstrInfoEmitter and into
CodeGenDAGPatterns, where it can be used in other tablegen backends.
This allows the inference to be done for DAGISelEmitter so that it
gets accurate mayLoad/mayStore/isSimpleLoad flags.
This brings MemOperand functionality back to where it was before
48329. However, it doesn't solve the problem of anonymous patterns
which expand to code that does loads or stores.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@49123 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | utils/TableGen/CodeGenDAGPatterns.cpp | 148 | ||||
-rw-r--r-- | utils/TableGen/CodeGenDAGPatterns.h | 5 | ||||
-rw-r--r-- | utils/TableGen/CodeGenIntrinsics.h | 2 | ||||
-rw-r--r-- | utils/TableGen/CodeGenTarget.cpp | 12 | ||||
-rw-r--r-- | utils/TableGen/CodeGenTarget.h | 4 | ||||
-rw-r--r-- | utils/TableGen/DAGISelEmitter.h | 1 | ||||
-rw-r--r-- | utils/TableGen/InstrInfoEmitter.cpp | 137 | ||||
-rw-r--r-- | utils/TableGen/InstrInfoEmitter.h | 6 |
8 files changed, 163 insertions, 152 deletions
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index a570c8f..8c46b35 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -965,7 +965,7 @@ static bool OnlyOnRHSOfCommutative(TreePatternNode *N) { /// that can never possibly work), and to prevent the pattern permuter from /// generating stuff that is useless. bool TreePatternNode::canPatternMatch(std::string &Reason, - CodeGenDAGPatterns &CDP){ + const CodeGenDAGPatterns &CDP) { if (isLeaf()) return true; for (unsigned i = 0, e = getNumChildren(); i != e; ++i) @@ -1226,6 +1226,11 @@ CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : Records(R) { // Generate variants. For example, commutative patterns can match // multiple ways. Add them to PatternsToMatch as well. GenerateVariants(); + + // Infer instruction flags. For example, we can detect loads, + // stores, and side effects in many cases by examining an + // instruction's pattern. + InferInstructionFlags(); } CodeGenDAGPatterns::~CodeGenDAGPatterns() { @@ -1558,6 +1563,131 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, InstImpInputs, InstImpResults); } +//===----------------------------------------------------------------------===// +// Instruction Analysis +//===----------------------------------------------------------------------===// + +class InstAnalyzer { + const CodeGenDAGPatterns &CDP; + bool &mayStore; + bool &mayLoad; + bool &HasSideEffects; +public: + InstAnalyzer(const CodeGenDAGPatterns &cdp, + bool &maystore, bool &mayload, bool &hse) + : CDP(cdp), mayStore(maystore), mayLoad(mayload), HasSideEffects(hse){ + } + + /// Analyze - Analyze the specified instruction, returning true if the + /// instruction had a pattern. + bool Analyze(Record *InstRecord) { + const TreePattern *Pattern = CDP.getInstruction(InstRecord).getPattern(); + if (Pattern == 0) { + HasSideEffects = 1; + return false; // No pattern. + } + + // FIXME: Assume only the first tree is the pattern. The others are clobber + // nodes. + AnalyzeNode(Pattern->getTree(0)); + return true; + } + +private: + void AnalyzeNode(const TreePatternNode *N) { + if (N->isLeaf()) { + if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) { + Record *LeafRec = DI->getDef(); + // Handle ComplexPattern leaves. + if (LeafRec->isSubClassOf("ComplexPattern")) { + const ComplexPattern &CP = CDP.getComplexPattern(LeafRec); + if (CP.hasProperty(SDNPMayStore)) mayStore = true; + if (CP.hasProperty(SDNPMayLoad)) mayLoad = true; + if (CP.hasProperty(SDNPSideEffect)) HasSideEffects = true; + } + } + return; + } + + // Analyze children. + for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) + AnalyzeNode(N->getChild(i)); + + // Ignore set nodes, which are not SDNodes. + if (N->getOperator()->getName() == "set") + return; + + // Get information about the SDNode for the operator. + const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N->getOperator()); + + // Notice properties of the node. + if (OpInfo.hasProperty(SDNPMayStore)) mayStore = true; + if (OpInfo.hasProperty(SDNPMayLoad)) mayLoad = true; + if (OpInfo.hasProperty(SDNPSideEffect)) HasSideEffects = true; + + if (const CodeGenIntrinsic *IntInfo = N->getIntrinsicInfo(CDP)) { + // If this is an intrinsic, analyze it. + if (IntInfo->ModRef >= CodeGenIntrinsic::ReadArgMem) + mayLoad = true;// These may load memory. + + if (IntInfo->ModRef >= CodeGenIntrinsic::WriteArgMem) + mayStore = true;// Intrinsics that can write to memory are 'mayStore'. + + if (IntInfo->ModRef >= CodeGenIntrinsic::WriteMem) + // WriteMem intrinsics can have other strange effects. + HasSideEffects = true; + } + } + +}; + +static void InferFromPattern(const CodeGenInstruction &Inst, + bool &MayStore, bool &MayLoad, + bool &HasSideEffects, + const CodeGenDAGPatterns &CDP) { + MayStore = MayLoad = HasSideEffects = false; + + bool HadPattern = + InstAnalyzer(CDP, MayStore, MayLoad, HasSideEffects).Analyze(Inst.TheDef); + + // InstAnalyzer only correctly analyzes mayStore/mayLoad so far. + if (Inst.mayStore) { // If the .td file explicitly sets mayStore, use it. + // If we decided that this is a store from the pattern, then the .td file + // entry is redundant. + if (MayStore) + fprintf(stderr, + "Warning: mayStore flag explicitly set on instruction '%s'" + " but flag already inferred from pattern.\n", + Inst.TheDef->getName().c_str()); + MayStore = true; + } + + if (Inst.mayLoad) { // If the .td file explicitly sets mayLoad, use it. + // If we decided that this is a load from the pattern, then the .td file + // entry is redundant. + if (MayLoad) + fprintf(stderr, + "Warning: mayLoad flag explicitly set on instruction '%s'" + " but flag already inferred from pattern.\n", + Inst.TheDef->getName().c_str()); + MayLoad = true; + } + + if (Inst.neverHasSideEffects) { + if (HadPattern) + fprintf(stderr, "Warning: neverHasSideEffects set on instruction '%s' " + "which already has a pattern\n", Inst.TheDef->getName().c_str()); + HasSideEffects = false; + } + + if (Inst.hasSideEffects) { + if (HasSideEffects) + fprintf(stderr, "Warning: hasSideEffects set on instruction '%s' " + "which already inferred this.\n", Inst.TheDef->getName().c_str()); + HasSideEffects = true; + } +} + /// ParseInstructions - Parse all of the instructions, inlining and resolving /// any fragments involved. This populates the Instructions list with fully /// resolved instructions. @@ -1791,6 +1921,22 @@ void CodeGenDAGPatterns::ParseInstructions() { } } + +void CodeGenDAGPatterns::InferInstructionFlags() { + std::map<std::string, CodeGenInstruction> &InstrDescs = + Target.getInstructions(); + for (std::map<std::string, CodeGenInstruction>::iterator + II = InstrDescs.begin(), E = InstrDescs.end(); II != E; ++II) { + CodeGenInstruction &InstInfo = II->second; + // Determine properties of the instruction from its pattern. + bool MayStore, MayLoad, HasSideEffects; + InferFromPattern(InstInfo, MayStore, MayLoad, HasSideEffects, *this); + InstInfo.mayStore = MayStore; + InstInfo.mayLoad = MayLoad; + InstInfo.hasSideEffects = HasSideEffects; + } +} + void CodeGenDAGPatterns::ParsePatterns() { std::vector<Record*> Patterns = Records.getAllDerivedDefinitions("Pattern"); diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index 6000e55..0d29eb5 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -17,7 +17,6 @@ #include <set> -#include "TableGenBackend.h" #include "CodeGenTarget.h" #include "CodeGenIntrinsics.h" @@ -277,7 +276,7 @@ public: // Higher level manipulation routines. /// canPatternMatch - If it is impossible for this pattern to match on this /// target, fill in Reason and return false. Otherwise, return true. - bool canPatternMatch(std::string &Reason, CodeGenDAGPatterns &CDP); + bool canPatternMatch(std::string &Reason, const CodeGenDAGPatterns &CDP); }; @@ -467,6 +466,7 @@ public: CodeGenDAGPatterns(RecordKeeper &R); ~CodeGenDAGPatterns(); + CodeGenTarget &getTargetInfo() { return Target; } const CodeGenTarget &getTargetInfo() const { return Target; } Record *getSDNodeNamed(const std::string &Name) const; @@ -556,6 +556,7 @@ private: void ParseDefaultOperands(); void ParseInstructions(); void ParsePatterns(); + void InferInstructionFlags(); void GenerateVariants(); void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, diff --git a/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h index 036882c..4515ebc 100644 --- a/utils/TableGen/CodeGenIntrinsics.h +++ b/utils/TableGen/CodeGenIntrinsics.h @@ -49,7 +49,7 @@ namespace llvm { // types. bool isOverloaded; - CodeGenIntrinsic(Record *R, CodeGenTarget *CGT); + CodeGenIntrinsic(Record *R); }; /// LoadIntrinsics - Read all of the intrinsics defined in the specified diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index da34ebf..78d39ee 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -394,20 +394,12 @@ std::vector<CodeGenIntrinsic> llvm::LoadIntrinsics(const RecordKeeper &RC) { std::vector<CodeGenIntrinsic> Result; - // If we are in the context of a target .td file, get the target info so that - // we can decode the current intptr_t. - CodeGenTarget *CGT = 0; - if (Records.getClass("Target") && - Records.getAllDerivedDefinitions("Target").size() == 1) - CGT = new CodeGenTarget(); - for (unsigned i = 0, e = I.size(); i != e; ++i) - Result.push_back(CodeGenIntrinsic(I[i], CGT)); - delete CGT; + Result.push_back(CodeGenIntrinsic(I[i])); return Result; } -CodeGenIntrinsic::CodeGenIntrinsic(Record *R, CodeGenTarget *CGT) { +CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { TheDef = R; std::string DefName = R->getName(); ModRef = WriteMem; diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h index a14f630..b066b6a 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -145,6 +145,10 @@ public: if (Instructions.empty()) ReadInstructions(); return Instructions; } + std::map<std::string, CodeGenInstruction> &getInstructions() { + if (Instructions.empty()) ReadInstructions(); + return Instructions; + } CodeGenInstruction &getInstruction(const std::string &Name) const { const std::map<std::string, CodeGenInstruction> &Insts = getInstructions(); diff --git a/utils/TableGen/DAGISelEmitter.h b/utils/TableGen/DAGISelEmitter.h index 534326e..1b47bcc 100644 --- a/utils/TableGen/DAGISelEmitter.h +++ b/utils/TableGen/DAGISelEmitter.h @@ -14,6 +14,7 @@ #ifndef DAGISEL_EMITTER_H #define DAGISEL_EMITTER_H +#include "TableGenBackend.h" #include "CodeGenDAGPatterns.h" #include <set> diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index cc03c6a..57d72b4 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -138,131 +138,6 @@ void InstrInfoEmitter::EmitOperandInfo(std::ostream &OS, } //===----------------------------------------------------------------------===// -// Instruction Analysis -//===----------------------------------------------------------------------===// - -class InstAnalyzer { - const CodeGenDAGPatterns &CDP; - bool &mayStore; - bool &mayLoad; - bool &HasSideEffects; -public: - InstAnalyzer(const CodeGenDAGPatterns &cdp, - bool &maystore, bool &mayload, bool &hse) - : CDP(cdp), mayStore(maystore), mayLoad(mayload), HasSideEffects(hse){ - } - - /// Analyze - Analyze the specified instruction, returning true if the - /// instruction had a pattern. - bool Analyze(Record *InstRecord) { - const TreePattern *Pattern = CDP.getInstruction(InstRecord).getPattern(); - if (Pattern == 0) { - HasSideEffects = 1; - return false; // No pattern. - } - - // FIXME: Assume only the first tree is the pattern. The others are clobber - // nodes. - AnalyzeNode(Pattern->getTree(0)); - return true; - } - -private: - void AnalyzeNode(const TreePatternNode *N) { - if (N->isLeaf()) { - if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) { - Record *LeafRec = DI->getDef(); - // Handle ComplexPattern leaves. - if (LeafRec->isSubClassOf("ComplexPattern")) { - const ComplexPattern &CP = CDP.getComplexPattern(LeafRec); - if (CP.hasProperty(SDNPMayStore)) mayStore = true; - if (CP.hasProperty(SDNPMayLoad)) mayLoad = true; - if (CP.hasProperty(SDNPSideEffect)) HasSideEffects = true; - } - } - return; - } - - // Analyze children. - for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) - AnalyzeNode(N->getChild(i)); - - // Ignore set nodes, which are not SDNodes. - if (N->getOperator()->getName() == "set") - return; - - // Get information about the SDNode for the operator. - const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N->getOperator()); - - // Notice properties of the node. - if (OpInfo.hasProperty(SDNPMayStore)) mayStore = true; - if (OpInfo.hasProperty(SDNPMayLoad)) mayLoad = true; - if (OpInfo.hasProperty(SDNPSideEffect)) HasSideEffects = true; - - if (const CodeGenIntrinsic *IntInfo = N->getIntrinsicInfo(CDP)) { - // If this is an intrinsic, analyze it. - if (IntInfo->ModRef >= CodeGenIntrinsic::ReadArgMem) - mayLoad = true;// These may load memory. - - if (IntInfo->ModRef >= CodeGenIntrinsic::WriteArgMem) - mayStore = true;// Intrinsics that can write to memory are 'mayStore'. - - if (IntInfo->ModRef >= CodeGenIntrinsic::WriteMem) - // WriteMem intrinsics can have other strange effects. - HasSideEffects = true; - } - } - -}; - -void InstrInfoEmitter::InferFromPattern(const CodeGenInstruction &Inst, - bool &MayStore, bool &MayLoad, - bool &HasSideEffects) { - MayStore = MayLoad = HasSideEffects = false; - - bool HadPattern = - InstAnalyzer(CDP, MayStore, MayLoad, HasSideEffects).Analyze(Inst.TheDef); - - // InstAnalyzer only correctly analyzes mayStore/mayLoad so far. - if (Inst.mayStore) { // If the .td file explicitly sets mayStore, use it. - // If we decided that this is a store from the pattern, then the .td file - // entry is redundant. - if (MayStore) - fprintf(stderr, - "Warning: mayStore flag explicitly set on instruction '%s'" - " but flag already inferred from pattern.\n", - Inst.TheDef->getName().c_str()); - MayStore = true; - } - - if (Inst.mayLoad) { // If the .td file explicitly sets mayLoad, use it. - // If we decided that this is a load from the pattern, then the .td file - // entry is redundant. - if (MayLoad) - fprintf(stderr, - "Warning: mayLoad flag explicitly set on instruction '%s'" - " but flag already inferred from pattern.\n", - Inst.TheDef->getName().c_str()); - MayLoad = true; - } - - if (Inst.neverHasSideEffects) { - if (HadPattern) - fprintf(stderr, "Warning: neverHasSideEffects set on instruction '%s' " - "which already has a pattern\n", Inst.TheDef->getName().c_str()); - HasSideEffects = false; - } - - if (Inst.hasSideEffects) { - if (HasSideEffects) - fprintf(stderr, "Warning: hasSideEffects set on instruction '%s' " - "which already inferred this.\n", Inst.TheDef->getName().c_str()); - HasSideEffects = true; - } -} - - -//===----------------------------------------------------------------------===// // Main Output. //===----------------------------------------------------------------------===// @@ -273,7 +148,7 @@ void InstrInfoEmitter::run(std::ostream &OS) { EmitSourceFileHeader("Target Instruction Descriptors", OS); OS << "namespace llvm {\n\n"; - CodeGenTarget Target; + CodeGenTarget &Target = CDP.getTargetInfo(); const std::string &TargetName = Target.getName(); Record *InstrInfo = Target.getInstructionSet(); @@ -321,10 +196,6 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, std::map<std::vector<Record*>, unsigned> &EmittedLists, const OperandInfoMapTy &OpInfo, std::ostream &OS) { - // Determine properties of the instruction from its pattern. - bool mayStore, mayLoad, HasSideEffects; - InferFromPattern(Inst, mayStore, mayLoad, HasSideEffects); - int MinOperands = 0; if (!Inst.OperandList.empty()) // Each logical operand can be multiple MI operands. @@ -344,8 +215,8 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, if (Inst.hasDelaySlot) OS << "|(1<<TID::DelaySlot)"; if (Inst.isCall) OS << "|(1<<TID::Call)"; if (Inst.isSimpleLoad) OS << "|(1<<TID::SimpleLoad)"; - if (mayLoad) OS << "|(1<<TID::MayLoad)"; - if (mayStore) OS << "|(1<<TID::MayStore)"; + if (Inst.mayLoad) OS << "|(1<<TID::MayLoad)"; + if (Inst.mayStore) OS << "|(1<<TID::MayStore)"; if (Inst.isPredicable) OS << "|(1<<TID::Predicable)"; if (Inst.isConvertibleToThreeAddress) OS << "|(1<<TID::ConvertibleTo3Addr)"; if (Inst.isCommutable) OS << "|(1<<TID::Commutable)"; @@ -356,7 +227,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, if (Inst.usesCustomDAGSchedInserter) OS << "|(1<<TID::UsesCustomDAGSchedInserter)"; if (Inst.isVariadic) OS << "|(1<<TID::Variadic)"; - if (HasSideEffects) OS << "|(1<<TID::UnmodeledSideEffects)"; + if (Inst.hasSideEffects) OS << "|(1<<TID::UnmodeledSideEffects)"; OS << ", 0"; // Emit all of the target-specific flags... diff --git a/utils/TableGen/InstrInfoEmitter.h b/utils/TableGen/InstrInfoEmitter.h index 977d3db..2dd3a0f 100644 --- a/utils/TableGen/InstrInfoEmitter.h +++ b/utils/TableGen/InstrInfoEmitter.h @@ -29,7 +29,7 @@ class CodeGenInstruction; class InstrInfoEmitter : public TableGenBackend { RecordKeeper &Records; - const CodeGenDAGPatterns CDP; + CodeGenDAGPatterns CDP; std::map<std::string, unsigned> ItinClassMap; public: @@ -41,10 +41,6 @@ public: private: typedef std::map<std::vector<std::string>, unsigned> OperandInfoMapTy; - // Instruction analysis. - void InferFromPattern(const CodeGenInstruction &Inst, - bool &MayStore, bool &MayLoad, bool &HasSideEffects); - void emitRecord(const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo, std::map<std::vector<Record*>, unsigned> &EL, |