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
This commit is contained in:
Dan Gohman 2008-04-03 00:02:49 +00:00
parent 271515a46d
commit ee4fa1977d
8 changed files with 163 additions and 152 deletions

View File

@ -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");

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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();

View File

@ -14,6 +14,7 @@
#ifndef DAGISEL_EMITTER_H
#define DAGISEL_EMITTER_H
#include "TableGenBackend.h"
#include "CodeGenDAGPatterns.h"
#include <set>

View File

@ -137,131 +137,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...

View File

@ -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,