forked from OSchip/llvm-project
[TableGen] Avoid leaking TreePatternNodes by using shared_ptr.
By using std::shared_ptr for TreePatternNode, we can avoid leaking them. Reviewers: craig.topper, dsanders, stoklund, tstellar, zturner Reviewed By: dsanders Differential Revision: https://reviews.llvm.org/D47463 llvm-svn: 333591
This commit is contained in:
parent
50603518a0
commit
75e87c3f2a
|
@ -1564,7 +1564,7 @@ bool TreePatternNode::hasProperTypeByHwMode() const {
|
|||
for (const TypeSetByHwMode &S : Types)
|
||||
if (!S.isDefaultOnly())
|
||||
return true;
|
||||
for (TreePatternNode *C : Children)
|
||||
for (const TreePatternNodePtr &C : Children)
|
||||
if (C->hasProperTypeByHwMode())
|
||||
return true;
|
||||
return false;
|
||||
|
@ -1574,7 +1574,7 @@ bool TreePatternNode::hasPossibleType() const {
|
|||
for (const TypeSetByHwMode &S : Types)
|
||||
if (!S.isPossible())
|
||||
return false;
|
||||
for (TreePatternNode *C : Children)
|
||||
for (const TreePatternNodePtr &C : Children)
|
||||
if (!C->hasPossibleType())
|
||||
return false;
|
||||
return true;
|
||||
|
@ -1587,7 +1587,7 @@ bool TreePatternNode::setDefaultMode(unsigned Mode) {
|
|||
if (S.get(DefaultMode).empty())
|
||||
return false;
|
||||
}
|
||||
for (TreePatternNode *C : Children)
|
||||
for (const TreePatternNodePtr &C : Children)
|
||||
if (!C->setDefaultMode(Mode))
|
||||
return false;
|
||||
return true;
|
||||
|
@ -1644,13 +1644,6 @@ MVT::SimpleValueType SDNodeInfo::getKnownType(unsigned ResNo) const {
|
|||
// TreePatternNode implementation
|
||||
//
|
||||
|
||||
TreePatternNode::~TreePatternNode() {
|
||||
#if 0 // FIXME: implement refcounted tree nodes!
|
||||
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
|
||||
delete getChild(i);
|
||||
#endif
|
||||
}
|
||||
|
||||
static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) {
|
||||
if (Operator->getName() == "set" ||
|
||||
Operator->getName() == "implicit")
|
||||
|
@ -1783,16 +1776,17 @@ bool TreePatternNode::isIsomorphicTo(const TreePatternNode *N,
|
|||
|
||||
/// clone - Make a copy of this tree and all of its children.
|
||||
///
|
||||
TreePatternNode *TreePatternNode::clone() const {
|
||||
TreePatternNode *New;
|
||||
TreePatternNodePtr TreePatternNode::clone() const {
|
||||
TreePatternNodePtr New;
|
||||
if (isLeaf()) {
|
||||
New = new TreePatternNode(getLeafValue(), getNumTypes());
|
||||
New = std::make_shared<TreePatternNode>(getLeafValue(), getNumTypes());
|
||||
} else {
|
||||
std::vector<TreePatternNode*> CChildren;
|
||||
std::vector<TreePatternNodePtr> CChildren;
|
||||
CChildren.reserve(Children.size());
|
||||
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
|
||||
CChildren.push_back(getChild(i)->clone());
|
||||
New = new TreePatternNode(getOperator(), CChildren, getNumTypes());
|
||||
New = std::make_shared<TreePatternNode>(getOperator(), CChildren,
|
||||
getNumTypes());
|
||||
}
|
||||
New->setName(getName());
|
||||
New->Types = Types;
|
||||
|
@ -1813,8 +1807,8 @@ void TreePatternNode::RemoveAllTypes() {
|
|||
|
||||
/// SubstituteFormalArguments - Replace the formal arguments in this tree
|
||||
/// with actual values specified by ArgMap.
|
||||
void TreePatternNode::
|
||||
SubstituteFormalArguments(std::map<std::string, TreePatternNode*> &ArgMap) {
|
||||
void TreePatternNode::SubstituteFormalArguments(
|
||||
std::map<std::string, TreePatternNodePtr> &ArgMap) {
|
||||
if (isLeaf()) return;
|
||||
|
||||
for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
|
||||
|
@ -1826,7 +1820,7 @@ SubstituteFormalArguments(std::map<std::string, TreePatternNode*> &ArgMap) {
|
|||
if (isa<UnsetInit>(Val) || (isa<DefInit>(Val) &&
|
||||
cast<DefInit>(Val)->getDef()->getName() == "node")) {
|
||||
// We found a use of a formal argument, replace it with its value.
|
||||
TreePatternNode *NewChild = ArgMap[Child->getName()];
|
||||
TreePatternNodePtr NewChild = ArgMap[Child->getName()];
|
||||
assert(NewChild && "Couldn't find formal argument!");
|
||||
assert((Child->getPredicateFns().empty() ||
|
||||
NewChild->getPredicateFns() == Child->getPredicateFns()) &&
|
||||
|
@ -1843,19 +1837,20 @@ SubstituteFormalArguments(std::map<std::string, TreePatternNode*> &ArgMap) {
|
|||
/// InlinePatternFragments - If this pattern refers to any pattern
|
||||
/// fragments, inline them into place, giving us a pattern without any
|
||||
/// PatFrag references.
|
||||
TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
|
||||
TreePatternNodePtr TreePatternNode::InlinePatternFragments(TreePatternNodePtr T,
|
||||
TreePattern &TP) {
|
||||
if (TP.hasError())
|
||||
return nullptr;
|
||||
|
||||
if (isLeaf())
|
||||
return this; // nothing to do.
|
||||
return T; // nothing to do.
|
||||
Record *Op = getOperator();
|
||||
|
||||
if (!Op->isSubClassOf("PatFrag")) {
|
||||
// Just recursively inline children nodes.
|
||||
for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
|
||||
TreePatternNode *Child = getChild(i);
|
||||
TreePatternNode *NewChild = Child->InlinePatternFragments(TP);
|
||||
TreePatternNodePtr Child = getChildShared(i);
|
||||
TreePatternNodePtr NewChild = Child->InlinePatternFragments(Child, TP);
|
||||
|
||||
assert((Child->getPredicateFns().empty() ||
|
||||
NewChild->getPredicateFns() == Child->getPredicateFns()) &&
|
||||
|
@ -1863,7 +1858,7 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
|
|||
|
||||
setChild(i, NewChild);
|
||||
}
|
||||
return this;
|
||||
return T;
|
||||
}
|
||||
|
||||
// Otherwise, we found a reference to a fragment. First, look up its
|
||||
|
@ -1874,10 +1869,10 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
|
|||
if (Frag->getNumArgs() != Children.size()) {
|
||||
TP.error("'" + Op->getName() + "' fragment requires " +
|
||||
Twine(Frag->getNumArgs()) + " operands!");
|
||||
return nullptr;
|
||||
return {nullptr};
|
||||
}
|
||||
|
||||
TreePatternNode *FragTree = Frag->getOnlyTree()->clone();
|
||||
TreePatternNodePtr FragTree = Frag->getOnlyTree()->clone();
|
||||
|
||||
TreePredicateFn PredFn(Frag);
|
||||
if (!PredFn.isAlwaysTrue())
|
||||
|
@ -1886,9 +1881,11 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
|
|||
// Resolve formal arguments to their actual value.
|
||||
if (Frag->getNumArgs()) {
|
||||
// Compute the map of formal to actual arguments.
|
||||
std::map<std::string, TreePatternNode*> ArgMap;
|
||||
for (unsigned i = 0, e = Frag->getNumArgs(); i != e; ++i)
|
||||
ArgMap[Frag->getArgName(i)] = getChild(i)->InlinePatternFragments(TP);
|
||||
std::map<std::string, TreePatternNodePtr> ArgMap;
|
||||
for (unsigned i = 0, e = Frag->getNumArgs(); i != e; ++i) {
|
||||
TreePatternNodePtr Child = getChildShared(i);
|
||||
ArgMap[Frag->getArgName(i)] = Child->InlinePatternFragments(Child, TP);
|
||||
}
|
||||
|
||||
FragTree->SubstituteFormalArguments(ArgMap);
|
||||
}
|
||||
|
@ -1901,12 +1898,9 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
|
|||
for (const TreePredicateFn &Pred : getPredicateFns())
|
||||
FragTree->addPredicateFn(Pred);
|
||||
|
||||
// Get a new copy of this fragment to stitch into here.
|
||||
//delete this; // FIXME: implement refcounting!
|
||||
|
||||
// The fragment we inlined could have recursive inlining that is needed. See
|
||||
// if there are any pattern fragments in it and inline them as needed.
|
||||
return FragTree->InlinePatternFragments(TP);
|
||||
return FragTree->InlinePatternFragments(FragTree, TP);
|
||||
}
|
||||
|
||||
/// getImplicitType - Check to see if the specified record has an implicit
|
||||
|
@ -2508,10 +2502,10 @@ TreePattern::TreePattern(Record *TheRec, DagInit *Pat, bool isInput,
|
|||
Trees.push_back(ParseTreePattern(Pat, ""));
|
||||
}
|
||||
|
||||
TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput,
|
||||
CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp),
|
||||
isInputPattern(isInput), HasError(false),
|
||||
Infer(*this) {
|
||||
TreePattern::TreePattern(Record *TheRec, TreePatternNodePtr Pat, bool isInput,
|
||||
CodeGenDAGPatterns &cdp)
|
||||
: TheRecord(TheRec), CDP(cdp), isInputPattern(isInput), HasError(false),
|
||||
Infer(*this) {
|
||||
Trees.push_back(Pat);
|
||||
}
|
||||
|
||||
|
@ -2524,8 +2518,8 @@ void TreePattern::error(const Twine &Msg) {
|
|||
}
|
||||
|
||||
void TreePattern::ComputeNamedNodes() {
|
||||
for (TreePatternNode *Tree : Trees)
|
||||
ComputeNamedNodes(Tree);
|
||||
for (TreePatternNodePtr &Tree : Trees)
|
||||
ComputeNamedNodes(Tree.get());
|
||||
}
|
||||
|
||||
void TreePattern::ComputeNamedNodes(TreePatternNode *N) {
|
||||
|
@ -2536,8 +2530,8 @@ void TreePattern::ComputeNamedNodes(TreePatternNode *N) {
|
|||
ComputeNamedNodes(N->getChild(i));
|
||||
}
|
||||
|
||||
|
||||
TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
|
||||
TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit,
|
||||
StringRef OpName) {
|
||||
if (DefInit *DI = dyn_cast<DefInit>(TheInit)) {
|
||||
Record *R = DI->getDef();
|
||||
|
||||
|
@ -2551,7 +2545,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
|
|||
OpName);
|
||||
|
||||
// Input argument?
|
||||
TreePatternNode *Res = new TreePatternNode(DI, 1);
|
||||
TreePatternNodePtr Res = std::make_shared<TreePatternNode>(DI, 1);
|
||||
if (R->getName() == "node" && !OpName.empty()) {
|
||||
if (OpName.empty())
|
||||
error("'node' argument requires a name to match with operand list");
|
||||
|
@ -2566,7 +2560,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
|
|||
if (isa<UnsetInit>(TheInit)) {
|
||||
if (OpName.empty())
|
||||
error("'?' argument requires a name to match with operand list");
|
||||
TreePatternNode *Res = new TreePatternNode(TheInit, 1);
|
||||
TreePatternNodePtr Res = std::make_shared<TreePatternNode>(TheInit, 1);
|
||||
Args.push_back(OpName);
|
||||
Res->setName(OpName);
|
||||
return Res;
|
||||
|
@ -2575,7 +2569,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
|
|||
if (IntInit *II = dyn_cast<IntInit>(TheInit)) {
|
||||
if (!OpName.empty())
|
||||
error("Constant int argument should not have a name!");
|
||||
return new TreePatternNode(II, 1);
|
||||
return std::make_shared<TreePatternNode>(II, 1);
|
||||
}
|
||||
|
||||
if (BitsInit *BI = dyn_cast<BitsInit>(TheInit)) {
|
||||
|
@ -2601,8 +2595,8 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
|
|||
if (Dag->getNumArgs() != 1)
|
||||
error("Type cast only takes one operand!");
|
||||
|
||||
TreePatternNode *New = ParseTreePattern(Dag->getArg(0),
|
||||
Dag->getArgNameStr(0));
|
||||
TreePatternNodePtr New =
|
||||
ParseTreePattern(Dag->getArg(0), Dag->getArgNameStr(0));
|
||||
|
||||
// Apply the type cast.
|
||||
assert(New->getNumTypes() == 1 && "FIXME: Unhandled");
|
||||
|
@ -2650,7 +2644,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
|
|||
error("Cannot use '" + Operator->getName() + "' in an output pattern!");
|
||||
}
|
||||
|
||||
std::vector<TreePatternNode*> Children;
|
||||
std::vector<TreePatternNodePtr> Children;
|
||||
|
||||
// Parse all the operands.
|
||||
for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i)
|
||||
|
@ -2677,13 +2671,14 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
|
|||
else // Otherwise, no chain.
|
||||
Operator = getDAGPatterns().get_intrinsic_wo_chain_sdnode();
|
||||
|
||||
TreePatternNode *IIDNode = new TreePatternNode(IntInit::get(IID), 1);
|
||||
TreePatternNodePtr IIDNode =
|
||||
std::make_shared<TreePatternNode>(IntInit::get(IID), 1);
|
||||
Children.insert(Children.begin(), IIDNode);
|
||||
}
|
||||
|
||||
if (Operator->isSubClassOf("ComplexPattern")) {
|
||||
for (unsigned i = 0; i < Children.size(); ++i) {
|
||||
TreePatternNode *Child = Children[i];
|
||||
TreePatternNodePtr Child = Children[i];
|
||||
|
||||
if (Child->getName().empty())
|
||||
error("All arguments to a ComplexPattern must be named");
|
||||
|
@ -2702,7 +2697,8 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
|
|||
}
|
||||
}
|
||||
|
||||
TreePatternNode *Result = new TreePatternNode(Operator, Children, NumResults);
|
||||
TreePatternNodePtr Result =
|
||||
std::make_shared<TreePatternNode>(Operator, Children, NumResults);
|
||||
Result->setName(OpName);
|
||||
|
||||
if (Dag->getName()) {
|
||||
|
@ -2718,7 +2714,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
|
|||
/// more type generic things and have useless type casts fold away.
|
||||
///
|
||||
/// This returns true if any change is made.
|
||||
static bool SimplifyTree(TreePatternNode *&N) {
|
||||
static bool SimplifyTree(TreePatternNodePtr &N) {
|
||||
if (N->isLeaf())
|
||||
return false;
|
||||
|
||||
|
@ -2728,7 +2724,7 @@ static bool SimplifyTree(TreePatternNode *&N) {
|
|||
N->getExtType(0).isValueTypeByHwMode(false) &&
|
||||
N->getExtType(0) == N->getChild(0)->getExtType(0) &&
|
||||
N->getName().empty()) {
|
||||
N = N->getChild(0);
|
||||
N = N->getChildShared(0);
|
||||
SimplifyTree(N);
|
||||
return true;
|
||||
}
|
||||
|
@ -2736,7 +2732,7 @@ static bool SimplifyTree(TreePatternNode *&N) {
|
|||
// Walk all children.
|
||||
bool MadeChange = false;
|
||||
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
|
||||
TreePatternNode *Child = N->getChild(i);
|
||||
TreePatternNodePtr Child = N->getChildShared(i);
|
||||
MadeChange |= SimplifyTree(Child);
|
||||
N->setChild(i, Child);
|
||||
}
|
||||
|
@ -2756,7 +2752,7 @@ InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) {
|
|||
bool MadeChange = true;
|
||||
while (MadeChange) {
|
||||
MadeChange = false;
|
||||
for (TreePatternNode *&Tree : Trees) {
|
||||
for (TreePatternNodePtr &Tree : Trees) {
|
||||
MadeChange |= Tree->ApplyTypeConstraints(*this, false);
|
||||
MadeChange |= SimplifyTree(Tree);
|
||||
}
|
||||
|
@ -2784,7 +2780,7 @@ InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) {
|
|||
// changing the type of the input register in this case. This allows
|
||||
// us to match things like:
|
||||
// def : Pat<(v1i64 (bitconvert(v2i32 DPR:$src))), (v1i64 DPR:$src)>;
|
||||
if (Node == Trees[0] && Node->isLeaf()) {
|
||||
if (Node == Trees[0].get() && Node->isLeaf()) {
|
||||
DefInit *DI = dyn_cast<DefInit>(Node->getLeafValue());
|
||||
if (DI && (DI->getDef()->isSubClassOf("RegisterClass") ||
|
||||
DI->getDef()->isSubClassOf("RegisterOperand")))
|
||||
|
@ -2815,7 +2811,7 @@ InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) {
|
|||
}
|
||||
|
||||
bool HasUnresolvedTypes = false;
|
||||
for (const TreePatternNode *Tree : Trees)
|
||||
for (const TreePatternNodePtr &Tree : Trees)
|
||||
HasUnresolvedTypes |= Tree->ContainsUnresolvedType(*this);
|
||||
return !HasUnresolvedTypes;
|
||||
}
|
||||
|
@ -2832,7 +2828,7 @@ void TreePattern::print(raw_ostream &OS) const {
|
|||
|
||||
if (Trees.size() > 1)
|
||||
OS << "[\n";
|
||||
for (const TreePatternNode *Tree : Trees) {
|
||||
for (const TreePatternNodePtr &Tree : Trees) {
|
||||
OS << "\t";
|
||||
Tree->print(OS);
|
||||
OS << "\n";
|
||||
|
@ -3048,9 +3044,9 @@ void CodeGenDAGPatterns::ParseDefaultOperands() {
|
|||
// Copy the operands over into a DAGDefaultOperand.
|
||||
DAGDefaultOperand DefaultOpInfo;
|
||||
|
||||
TreePatternNode *T = P.getTree(0);
|
||||
const TreePatternNodePtr &T = P.getTree(0);
|
||||
for (unsigned op = 0, e = T->getNumChildren(); op != e; ++op) {
|
||||
TreePatternNode *TPN = T->getChild(op);
|
||||
TreePatternNodePtr TPN = T->getChildShared(op);
|
||||
while (TPN->ApplyTypeConstraints(P, false))
|
||||
/* Resolve all types */;
|
||||
|
||||
|
@ -3069,8 +3065,8 @@ void CodeGenDAGPatterns::ParseDefaultOperands() {
|
|||
|
||||
/// HandleUse - Given "Pat" a leaf in the pattern, check to see if it is an
|
||||
/// instruction input. Return true if this is a real use.
|
||||
static bool HandleUse(TreePattern *I, TreePatternNode *Pat,
|
||||
std::map<std::string, TreePatternNode*> &InstInputs) {
|
||||
static bool HandleUse(TreePattern *I, TreePatternNodePtr Pat,
|
||||
std::map<std::string, TreePatternNodePtr> &InstInputs) {
|
||||
// No name -> not interesting.
|
||||
if (Pat->getName().empty()) {
|
||||
if (Pat->isLeaf()) {
|
||||
|
@ -3095,7 +3091,7 @@ static bool HandleUse(TreePattern *I, TreePatternNode *Pat,
|
|||
if (Rec->getName() == "srcvalue")
|
||||
return false;
|
||||
|
||||
TreePatternNode *&Slot = InstInputs[Pat->getName()];
|
||||
TreePatternNodePtr &Slot = InstInputs[Pat->getName()];
|
||||
if (!Slot) {
|
||||
Slot = Pat;
|
||||
return true;
|
||||
|
@ -3119,11 +3115,11 @@ static bool HandleUse(TreePattern *I, TreePatternNode *Pat,
|
|||
/// FindPatternInputsAndOutputs - Scan the specified TreePatternNode (which is
|
||||
/// part of "I", the instruction), computing the set of inputs and outputs of
|
||||
/// the pattern. Report errors if we see anything naughty.
|
||||
void CodeGenDAGPatterns::
|
||||
FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
|
||||
std::map<std::string, TreePatternNode*> &InstInputs,
|
||||
std::map<std::string, TreePatternNode*>&InstResults,
|
||||
std::vector<Record*> &InstImpResults) {
|
||||
void CodeGenDAGPatterns::FindPatternInputsAndOutputs(
|
||||
TreePattern *I, TreePatternNodePtr Pat,
|
||||
std::map<std::string, TreePatternNodePtr> &InstInputs,
|
||||
std::map<std::string, TreePatternNodePtr> &InstResults,
|
||||
std::vector<Record *> &InstImpResults) {
|
||||
if (Pat->isLeaf()) {
|
||||
bool isUse = HandleUse(I, Pat, InstInputs);
|
||||
if (!isUse && Pat->getTransformFn())
|
||||
|
@ -3151,8 +3147,8 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
|
|||
for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) {
|
||||
if (Pat->getChild(i)->getNumTypes() == 0)
|
||||
I->error("Cannot have void nodes inside of patterns!");
|
||||
FindPatternInputsAndOutputs(I, Pat->getChild(i), InstInputs, InstResults,
|
||||
InstImpResults);
|
||||
FindPatternInputsAndOutputs(I, Pat->getChildShared(i), InstInputs,
|
||||
InstResults, InstImpResults);
|
||||
}
|
||||
|
||||
// If this is a non-leaf node with no children, treat it basically as if
|
||||
|
@ -3174,7 +3170,7 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
|
|||
// Check the set destinations.
|
||||
unsigned NumDests = Pat->getNumChildren()-1;
|
||||
for (unsigned i = 0; i != NumDests; ++i) {
|
||||
TreePatternNode *Dest = Pat->getChild(i);
|
||||
TreePatternNodePtr Dest = Pat->getChildShared(i);
|
||||
if (!Dest->isLeaf())
|
||||
I->error("set destination should be a register!");
|
||||
|
||||
|
@ -3201,8 +3197,8 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
|
|||
}
|
||||
|
||||
// Verify and collect info from the computation.
|
||||
FindPatternInputsAndOutputs(I, Pat->getChild(NumDests),
|
||||
InstInputs, InstResults, InstImpResults);
|
||||
FindPatternInputsAndOutputs(I, Pat->getChildShared(NumDests), InstInputs,
|
||||
InstResults, InstImpResults);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -3224,7 +3220,7 @@ public:
|
|||
|
||||
void Analyze(const TreePattern *Pat) {
|
||||
// Assume only the first tree is the pattern. The others are clobber nodes.
|
||||
AnalyzeNode(Pat->getTree(0));
|
||||
AnalyzeNode(Pat->getTree(0).get());
|
||||
}
|
||||
|
||||
void Analyze(const PatternToMatch &Pat) {
|
||||
|
@ -3436,11 +3432,11 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(
|
|||
|
||||
// InstInputs - Keep track of all of the inputs of the instruction, along
|
||||
// with the record they are declared as.
|
||||
std::map<std::string, TreePatternNode*> InstInputs;
|
||||
std::map<std::string, TreePatternNodePtr> InstInputs;
|
||||
|
||||
// InstResults - Keep track of all the virtual registers that are 'set'
|
||||
// in the instruction, including what reg class they are.
|
||||
std::map<std::string, TreePatternNode*> InstResults;
|
||||
std::map<std::string, TreePatternNodePtr> InstResults;
|
||||
|
||||
std::vector<Record*> InstImpResults;
|
||||
|
||||
|
@ -3449,7 +3445,7 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(
|
|||
SmallString<32> TypesString;
|
||||
for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) {
|
||||
TypesString.clear();
|
||||
TreePatternNode *Pat = I->getTree(j);
|
||||
TreePatternNodePtr Pat = I->getTree(j);
|
||||
if (Pat->getNumTypes() != 0) {
|
||||
raw_svector_ostream OS(TypesString);
|
||||
for (unsigned k = 0, ke = Pat->getNumTypes(); k != ke; ++k) {
|
||||
|
@ -3477,7 +3473,7 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(
|
|||
|
||||
// Check that all of the results occur first in the list.
|
||||
std::vector<Record*> Results;
|
||||
SmallVector<TreePatternNode *, 2> ResNodes;
|
||||
SmallVector<TreePatternNodePtr, 2> ResNodes;
|
||||
for (unsigned i = 0; i != NumResults; ++i) {
|
||||
if (i == CGI.Operands.size())
|
||||
I->error("'" + InstResults.begin()->first +
|
||||
|
@ -3485,7 +3481,7 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(
|
|||
const std::string &OpName = CGI.Operands[i].Name;
|
||||
|
||||
// Check that it exists in InstResults.
|
||||
TreePatternNode *RNode = InstResults[OpName];
|
||||
TreePatternNodePtr RNode = InstResults[OpName];
|
||||
if (!RNode)
|
||||
I->error("Operand $" + OpName + " does not exist in operand list!");
|
||||
|
||||
|
@ -3508,9 +3504,9 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(
|
|||
|
||||
// Loop over the inputs next. Make a copy of InstInputs so we can destroy
|
||||
// the copy while we're checking the inputs.
|
||||
std::map<std::string, TreePatternNode*> InstInputsCheck(InstInputs);
|
||||
std::map<std::string, TreePatternNodePtr> InstInputsCheck(InstInputs);
|
||||
|
||||
std::vector<TreePatternNode*> ResultNodeOperands;
|
||||
std::vector<TreePatternNodePtr> ResultNodeOperands;
|
||||
std::vector<Record*> Operands;
|
||||
for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) {
|
||||
CGIOperandList::OperandInfo &Op = CGI.Operands[i];
|
||||
|
@ -3530,7 +3526,7 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(
|
|||
I->error("Operand $" + OpName +
|
||||
" does not appear in the instruction pattern");
|
||||
}
|
||||
TreePatternNode *InVal = InstInputsCheck[OpName];
|
||||
TreePatternNodePtr InVal = InstInputsCheck[OpName];
|
||||
InstInputsCheck.erase(OpName); // It occurred, remove from map.
|
||||
|
||||
if (InVal->isLeaf() && isa<DefInit>(InVal->getLeafValue())) {
|
||||
|
@ -3542,7 +3538,7 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(
|
|||
Operands.push_back(Op.Rec);
|
||||
|
||||
// Construct the result for the dest-pattern operand list.
|
||||
TreePatternNode *OpNode = InVal->clone();
|
||||
TreePatternNodePtr OpNode = InVal->clone();
|
||||
|
||||
// No predicate is useful on the result.
|
||||
OpNode->clearPredicateFns();
|
||||
|
@ -3550,9 +3546,10 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(
|
|||
// Promote the xform function to be an explicit node if set.
|
||||
if (Record *Xform = OpNode->getTransformFn()) {
|
||||
OpNode->setTransformFn(nullptr);
|
||||
std::vector<TreePatternNode*> Children;
|
||||
std::vector<TreePatternNodePtr> Children;
|
||||
Children.push_back(OpNode);
|
||||
OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes());
|
||||
OpNode = std::make_shared<TreePatternNode>(Xform, Children,
|
||||
OpNode->getNumTypes());
|
||||
}
|
||||
|
||||
ResultNodeOperands.push_back(OpNode);
|
||||
|
@ -3562,9 +3559,9 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(
|
|||
I->error("Input operand $" + InstInputsCheck.begin()->first +
|
||||
" occurs in pattern but not in operands list!");
|
||||
|
||||
TreePatternNode *ResultPattern =
|
||||
new TreePatternNode(I->getRecord(), ResultNodeOperands,
|
||||
GetNumNodeResults(I->getRecord(), *this));
|
||||
TreePatternNodePtr ResultPattern = std::make_shared<TreePatternNode>(
|
||||
I->getRecord(), ResultNodeOperands,
|
||||
GetNumNodeResults(I->getRecord(), *this));
|
||||
// Copy fully inferred output node types to instruction result pattern.
|
||||
for (unsigned i = 0; i != NumResults; ++i) {
|
||||
assert(ResNodes[i]->getNumTypes() == 1 && "FIXME: Unhandled");
|
||||
|
@ -3646,8 +3643,8 @@ void CodeGenDAGPatterns::ParseInstructions() {
|
|||
PatternRewriter(I);
|
||||
// FIXME: Assume only the first tree is the pattern. The others are clobber
|
||||
// nodes.
|
||||
TreePatternNode *Pattern = I->getTree(0);
|
||||
TreePatternNode *SrcPattern;
|
||||
TreePatternNodePtr Pattern = I->getTree(0);
|
||||
TreePatternNodePtr SrcPattern;
|
||||
if (Pattern->getOperator()->getName() == "set") {
|
||||
SrcPattern = Pattern->getChild(Pattern->getNumChildren()-1)->clone();
|
||||
} else{
|
||||
|
@ -3666,10 +3663,9 @@ void CodeGenDAGPatterns::ParseInstructions() {
|
|||
}
|
||||
}
|
||||
|
||||
typedef std::pair<TreePatternNode *, unsigned> NameRecord;
|
||||
|
||||
typedef std::pair<const TreePatternNode*, unsigned> NameRecord;
|
||||
|
||||
static void FindNames(const TreePatternNode *P,
|
||||
static void FindNames(TreePatternNode *P,
|
||||
std::map<std::string, NameRecord> &Names,
|
||||
TreePattern *PatternTop) {
|
||||
if (!P->getName().empty()) {
|
||||
|
@ -3929,10 +3925,10 @@ void CodeGenDAGPatterns::ParsePatterns() {
|
|||
if (hasNullFragReference(Tree))
|
||||
continue;
|
||||
|
||||
TreePattern *Pattern = new TreePattern(CurPattern, Tree, true, *this);
|
||||
TreePattern Pattern(CurPattern, Tree, true, *this);
|
||||
|
||||
// Inline pattern fragments into it.
|
||||
Pattern->InlinePatternFragments();
|
||||
Pattern.InlinePatternFragments();
|
||||
|
||||
ListInit *LI = CurPattern->getValueAsListInit("ResultInstrs");
|
||||
if (LI->empty()) continue; // no pattern.
|
||||
|
@ -3953,12 +3949,12 @@ void CodeGenDAGPatterns::ParsePatterns() {
|
|||
// Infer as many types as possible. If we cannot infer all of them, we
|
||||
// can never do anything with this pattern: report it to the user.
|
||||
InferredAllPatternTypes =
|
||||
Pattern->InferAllTypes(&Pattern->getNamedNodesMap());
|
||||
Pattern.InferAllTypes(&Pattern.getNamedNodesMap());
|
||||
|
||||
// Infer as many types as possible. If we cannot infer all of them, we
|
||||
// can never do anything with this pattern: report it to the user.
|
||||
InferredAllResultTypes =
|
||||
Result.InferAllTypes(&Pattern->getNamedNodesMap());
|
||||
Result.InferAllTypes(&Pattern.getNamedNodesMap());
|
||||
|
||||
IterateInference = false;
|
||||
|
||||
|
@ -3967,12 +3963,12 @@ void CodeGenDAGPatterns::ParsePatterns() {
|
|||
// is considered resolved), but the result knows it needs to be 32- or
|
||||
// 64-bits. Infer the other way for good measure.
|
||||
for (unsigned i = 0, e = std::min(Result.getTree(0)->getNumTypes(),
|
||||
Pattern->getTree(0)->getNumTypes());
|
||||
Pattern.getTree(0)->getNumTypes());
|
||||
i != e; ++i) {
|
||||
IterateInference = Pattern->getTree(0)->UpdateNodeType(
|
||||
IterateInference = Pattern.getTree(0)->UpdateNodeType(
|
||||
i, Result.getTree(0)->getExtType(i), Result);
|
||||
IterateInference |= Result.getTree(0)->UpdateNodeType(
|
||||
i, Pattern->getTree(0)->getExtType(i), Result);
|
||||
i, Pattern.getTree(0)->getExtType(i), Result);
|
||||
}
|
||||
|
||||
// If our iteration has converged and the input pattern's types are fully
|
||||
|
@ -3987,45 +3983,45 @@ void CodeGenDAGPatterns::ParsePatterns() {
|
|||
if (!IterateInference && InferredAllPatternTypes &&
|
||||
!InferredAllResultTypes)
|
||||
IterateInference =
|
||||
ForceArbitraryInstResultType(Result.getTree(0), Result);
|
||||
ForceArbitraryInstResultType(Result.getTree(0).get(), Result);
|
||||
} while (IterateInference);
|
||||
|
||||
// Verify that we inferred enough types that we can do something with the
|
||||
// pattern and result. If these fire the user has to add type casts.
|
||||
if (!InferredAllPatternTypes)
|
||||
Pattern->error("Could not infer all types in pattern!");
|
||||
Pattern.error("Could not infer all types in pattern!");
|
||||
if (!InferredAllResultTypes) {
|
||||
Pattern->dump();
|
||||
Pattern.dump();
|
||||
Result.error("Could not infer all types in pattern result!");
|
||||
}
|
||||
|
||||
// Validate that the input pattern is correct.
|
||||
std::map<std::string, TreePatternNode*> InstInputs;
|
||||
std::map<std::string, TreePatternNode*> InstResults;
|
||||
std::map<std::string, TreePatternNodePtr> InstInputs;
|
||||
std::map<std::string, TreePatternNodePtr> InstResults;
|
||||
std::vector<Record*> InstImpResults;
|
||||
for (unsigned j = 0, ee = Pattern->getNumTrees(); j != ee; ++j)
|
||||
FindPatternInputsAndOutputs(Pattern, Pattern->getTree(j),
|
||||
InstInputs, InstResults,
|
||||
InstImpResults);
|
||||
for (unsigned j = 0, ee = Pattern.getNumTrees(); j != ee; ++j)
|
||||
FindPatternInputsAndOutputs(&Pattern, Pattern.getTree(j), InstInputs,
|
||||
InstResults, InstImpResults);
|
||||
|
||||
// Promote the xform function to be an explicit node if set.
|
||||
TreePatternNode *DstPattern = Result.getOnlyTree();
|
||||
std::vector<TreePatternNode*> ResultNodeOperands;
|
||||
TreePatternNodePtr DstPattern = Result.getOnlyTree();
|
||||
std::vector<TreePatternNodePtr> ResultNodeOperands;
|
||||
for (unsigned ii = 0, ee = DstPattern->getNumChildren(); ii != ee; ++ii) {
|
||||
TreePatternNode *OpNode = DstPattern->getChild(ii);
|
||||
TreePatternNodePtr OpNode = DstPattern->getChildShared(ii);
|
||||
if (Record *Xform = OpNode->getTransformFn()) {
|
||||
OpNode->setTransformFn(nullptr);
|
||||
std::vector<TreePatternNode*> Children;
|
||||
std::vector<TreePatternNodePtr> Children;
|
||||
Children.push_back(OpNode);
|
||||
OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes());
|
||||
OpNode = std::make_shared<TreePatternNode>(Xform, Children,
|
||||
OpNode->getNumTypes());
|
||||
}
|
||||
ResultNodeOperands.push_back(OpNode);
|
||||
}
|
||||
DstPattern = Result.getOnlyTree();
|
||||
if (!DstPattern->isLeaf())
|
||||
DstPattern = new TreePatternNode(DstPattern->getOperator(),
|
||||
ResultNodeOperands,
|
||||
DstPattern->getNumTypes());
|
||||
DstPattern = std::make_shared<TreePatternNode>(DstPattern->getOperator(),
|
||||
ResultNodeOperands,
|
||||
DstPattern->getNumTypes());
|
||||
|
||||
for (unsigned i = 0, e = Result.getOnlyTree()->getNumTypes(); i != e; ++i)
|
||||
DstPattern->setType(i, Result.getOnlyTree()->getExtType(i));
|
||||
|
@ -4040,18 +4036,17 @@ void CodeGenDAGPatterns::ParsePatterns() {
|
|||
// that register class does not accept that type, the type inference
|
||||
// will lead to a contradiction, which is not an error however, but
|
||||
// a sign that this pattern will simply never match.
|
||||
if (Pattern->getTree(0)->hasPossibleType() &&
|
||||
if (Pattern.getTree(0)->hasPossibleType() &&
|
||||
Temp.getOnlyTree()->hasPossibleType()) {
|
||||
ListInit *Preds = CurPattern->getValueAsListInit("Predicates");
|
||||
int Complexity = CurPattern->getValueAsInt("AddedComplexity");
|
||||
if (PatternRewriter)
|
||||
PatternRewriter(Pattern);
|
||||
AddPatternToMatch(
|
||||
Pattern,
|
||||
PatternToMatch(
|
||||
CurPattern, makePredList(Preds), Pattern->getTree(0),
|
||||
Temp.getOnlyTree(), std::move(InstImpResults), Complexity,
|
||||
CurPattern->getID()));
|
||||
PatternRewriter(&Pattern);
|
||||
AddPatternToMatch(&Pattern,
|
||||
PatternToMatch(CurPattern, makePredList(Preds),
|
||||
Pattern.getTree(0), Temp.getOnlyTree(),
|
||||
std::move(InstImpResults), Complexity,
|
||||
CurPattern->getID()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4071,12 +4066,10 @@ void CodeGenDAGPatterns::ExpandHwModeBasedTypes() {
|
|||
std::vector<PatternToMatch> Copy = PatternsToMatch;
|
||||
PatternsToMatch.clear();
|
||||
|
||||
auto AppendPattern = [this,&ModeChecks](PatternToMatch &P, unsigned Mode) {
|
||||
TreePatternNode *NewSrc = P.SrcPattern->clone();
|
||||
TreePatternNode *NewDst = P.DstPattern->clone();
|
||||
auto AppendPattern = [this, &ModeChecks](PatternToMatch &P, unsigned Mode) {
|
||||
TreePatternNodePtr NewSrc = P.SrcPattern->clone();
|
||||
TreePatternNodePtr NewDst = P.DstPattern->clone();
|
||||
if (!NewSrc->setDefaultMode(Mode) || !NewDst->setDefaultMode(Mode)) {
|
||||
delete NewSrc;
|
||||
delete NewDst;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4089,7 +4082,7 @@ void CodeGenDAGPatterns::ExpandHwModeBasedTypes() {
|
|||
};
|
||||
|
||||
for (PatternToMatch &P : Copy) {
|
||||
TreePatternNode *SrcP = nullptr, *DstP = nullptr;
|
||||
TreePatternNodePtr SrcP = nullptr, DstP = nullptr;
|
||||
if (P.SrcPattern->hasProperTypeByHwMode())
|
||||
SrcP = P.SrcPattern;
|
||||
if (P.DstPattern->hasProperTypeByHwMode())
|
||||
|
@ -4101,9 +4094,9 @@ void CodeGenDAGPatterns::ExpandHwModeBasedTypes() {
|
|||
|
||||
std::set<unsigned> Modes;
|
||||
if (SrcP)
|
||||
collectModes(Modes, SrcP);
|
||||
collectModes(Modes, SrcP.get());
|
||||
if (DstP)
|
||||
collectModes(Modes, DstP);
|
||||
collectModes(Modes, DstP.get());
|
||||
|
||||
// The predicate for the default mode needs to be constructed for each
|
||||
// pattern separately.
|
||||
|
@ -4185,11 +4178,11 @@ static void DumpDepVars(MultipleUseVarSet &DepVars) {
|
|||
|
||||
/// CombineChildVariants - Given a bunch of permutations of each child of the
|
||||
/// 'operator' node, put them together in all possible ways.
|
||||
static void CombineChildVariants(TreePatternNode *Orig,
|
||||
const std::vector<std::vector<TreePatternNode*> > &ChildVariants,
|
||||
std::vector<TreePatternNode*> &OutVariants,
|
||||
CodeGenDAGPatterns &CDP,
|
||||
const MultipleUseVarSet &DepVars) {
|
||||
static void CombineChildVariants(
|
||||
TreePatternNodePtr Orig,
|
||||
const std::vector<std::vector<TreePatternNodePtr>> &ChildVariants,
|
||||
std::vector<TreePatternNodePtr> &OutVariants, CodeGenDAGPatterns &CDP,
|
||||
const MultipleUseVarSet &DepVars) {
|
||||
// Make sure that each operand has at least one variant to choose from.
|
||||
for (const auto &Variants : ChildVariants)
|
||||
if (Variants.empty())
|
||||
|
@ -4210,10 +4203,10 @@ static void CombineChildVariants(TreePatternNode *Orig,
|
|||
});
|
||||
#endif
|
||||
// Create the variant and add it to the output list.
|
||||
std::vector<TreePatternNode*> NewChildren;
|
||||
std::vector<TreePatternNodePtr> NewChildren;
|
||||
for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i)
|
||||
NewChildren.push_back(ChildVariants[i][Idxs[i]]);
|
||||
auto R = llvm::make_unique<TreePatternNode>(
|
||||
TreePatternNodePtr R = std::make_shared<TreePatternNode>(
|
||||
Orig->getOperator(), NewChildren, Orig->getNumTypes());
|
||||
|
||||
// Copy over properties.
|
||||
|
@ -4230,10 +4223,10 @@ static void CombineChildVariants(TreePatternNode *Orig,
|
|||
// (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a)
|
||||
// which are the same pattern. Ignore the dups.
|
||||
if (R->canPatternMatch(ErrString, CDP) &&
|
||||
none_of(OutVariants, [&](TreePatternNode *Variant) {
|
||||
return R->isIsomorphicTo(Variant, DepVars);
|
||||
none_of(OutVariants, [&](TreePatternNodePtr Variant) {
|
||||
return R->isIsomorphicTo(Variant.get(), DepVars);
|
||||
}))
|
||||
OutVariants.push_back(R.release());
|
||||
OutVariants.push_back(R);
|
||||
|
||||
// Increment indices to the next permutation by incrementing the
|
||||
// indices from last index backward, e.g., generate the sequence
|
||||
|
@ -4251,21 +4244,21 @@ static void CombineChildVariants(TreePatternNode *Orig,
|
|||
|
||||
/// CombineChildVariants - A helper function for binary operators.
|
||||
///
|
||||
static void CombineChildVariants(TreePatternNode *Orig,
|
||||
const std::vector<TreePatternNode*> &LHS,
|
||||
const std::vector<TreePatternNode*> &RHS,
|
||||
std::vector<TreePatternNode*> &OutVariants,
|
||||
static void CombineChildVariants(TreePatternNodePtr Orig,
|
||||
const std::vector<TreePatternNodePtr> &LHS,
|
||||
const std::vector<TreePatternNodePtr> &RHS,
|
||||
std::vector<TreePatternNodePtr> &OutVariants,
|
||||
CodeGenDAGPatterns &CDP,
|
||||
const MultipleUseVarSet &DepVars) {
|
||||
std::vector<std::vector<TreePatternNode*> > ChildVariants;
|
||||
std::vector<std::vector<TreePatternNodePtr>> ChildVariants;
|
||||
ChildVariants.push_back(LHS);
|
||||
ChildVariants.push_back(RHS);
|
||||
CombineChildVariants(Orig, ChildVariants, OutVariants, CDP, DepVars);
|
||||
}
|
||||
|
||||
|
||||
static void GatherChildrenOfAssociativeOpcode(TreePatternNode *N,
|
||||
std::vector<TreePatternNode *> &Children) {
|
||||
static void
|
||||
GatherChildrenOfAssociativeOpcode(TreePatternNodePtr N,
|
||||
std::vector<TreePatternNodePtr> &Children) {
|
||||
assert(N->getNumChildren()==2 &&"Associative but doesn't have 2 children!");
|
||||
Record *Operator = N->getOperator();
|
||||
|
||||
|
@ -4277,21 +4270,21 @@ static void GatherChildrenOfAssociativeOpcode(TreePatternNode *N,
|
|||
}
|
||||
|
||||
if (N->getChild(0)->isLeaf() || N->getChild(0)->getOperator() != Operator)
|
||||
Children.push_back(N->getChild(0));
|
||||
Children.push_back(N->getChildShared(0));
|
||||
else
|
||||
GatherChildrenOfAssociativeOpcode(N->getChild(0), Children);
|
||||
GatherChildrenOfAssociativeOpcode(N->getChildShared(0), Children);
|
||||
|
||||
if (N->getChild(1)->isLeaf() || N->getChild(1)->getOperator() != Operator)
|
||||
Children.push_back(N->getChild(1));
|
||||
Children.push_back(N->getChildShared(1));
|
||||
else
|
||||
GatherChildrenOfAssociativeOpcode(N->getChild(1), Children);
|
||||
GatherChildrenOfAssociativeOpcode(N->getChildShared(1), Children);
|
||||
}
|
||||
|
||||
/// GenerateVariantsOf - Given a pattern N, generate all permutations we can of
|
||||
/// the (potentially recursive) pattern by using algebraic laws.
|
||||
///
|
||||
static void GenerateVariantsOf(TreePatternNode *N,
|
||||
std::vector<TreePatternNode*> &OutVariants,
|
||||
static void GenerateVariantsOf(TreePatternNodePtr N,
|
||||
std::vector<TreePatternNodePtr> &OutVariants,
|
||||
CodeGenDAGPatterns &CDP,
|
||||
const MultipleUseVarSet &DepVars) {
|
||||
// We cannot permute leaves or ComplexPattern uses.
|
||||
|
@ -4306,14 +4299,14 @@ static void GenerateVariantsOf(TreePatternNode *N,
|
|||
// If this node is associative, re-associate.
|
||||
if (NodeInfo.hasProperty(SDNPAssociative)) {
|
||||
// Re-associate by pulling together all of the linked operators
|
||||
std::vector<TreePatternNode*> MaximalChildren;
|
||||
std::vector<TreePatternNodePtr> MaximalChildren;
|
||||
GatherChildrenOfAssociativeOpcode(N, MaximalChildren);
|
||||
|
||||
// Only handle child sizes of 3. Otherwise we'll end up trying too many
|
||||
// permutations.
|
||||
if (MaximalChildren.size() == 3) {
|
||||
// Find the variants of all of our maximal children.
|
||||
std::vector<TreePatternNode*> AVariants, BVariants, CVariants;
|
||||
std::vector<TreePatternNodePtr> AVariants, BVariants, CVariants;
|
||||
GenerateVariantsOf(MaximalChildren[0], AVariants, CDP, DepVars);
|
||||
GenerateVariantsOf(MaximalChildren[1], BVariants, CDP, DepVars);
|
||||
GenerateVariantsOf(MaximalChildren[2], CVariants, CDP, DepVars);
|
||||
|
@ -4323,12 +4316,12 @@ static void GenerateVariantsOf(TreePatternNode *N,
|
|||
// Within these forms, we can also permute A/B/C.
|
||||
|
||||
// Generate legal pair permutations of A/B/C.
|
||||
std::vector<TreePatternNode*> ABVariants;
|
||||
std::vector<TreePatternNode*> BAVariants;
|
||||
std::vector<TreePatternNode*> ACVariants;
|
||||
std::vector<TreePatternNode*> CAVariants;
|
||||
std::vector<TreePatternNode*> BCVariants;
|
||||
std::vector<TreePatternNode*> CBVariants;
|
||||
std::vector<TreePatternNodePtr> ABVariants;
|
||||
std::vector<TreePatternNodePtr> BAVariants;
|
||||
std::vector<TreePatternNodePtr> ACVariants;
|
||||
std::vector<TreePatternNodePtr> CAVariants;
|
||||
std::vector<TreePatternNodePtr> BCVariants;
|
||||
std::vector<TreePatternNodePtr> CBVariants;
|
||||
CombineChildVariants(N, AVariants, BVariants, ABVariants, CDP, DepVars);
|
||||
CombineChildVariants(N, BVariants, AVariants, BAVariants, CDP, DepVars);
|
||||
CombineChildVariants(N, AVariants, CVariants, ACVariants, CDP, DepVars);
|
||||
|
@ -4356,10 +4349,10 @@ static void GenerateVariantsOf(TreePatternNode *N,
|
|||
}
|
||||
|
||||
// Compute permutations of all children.
|
||||
std::vector<std::vector<TreePatternNode*> > ChildVariants;
|
||||
std::vector<std::vector<TreePatternNodePtr>> ChildVariants;
|
||||
ChildVariants.resize(N->getNumChildren());
|
||||
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
|
||||
GenerateVariantsOf(N->getChild(i), ChildVariants[i], CDP, DepVars);
|
||||
GenerateVariantsOf(N->getChildShared(i), ChildVariants[i], CDP, DepVars);
|
||||
|
||||
// Build all permutations based on how the children were formed.
|
||||
CombineChildVariants(N, ChildVariants, OutVariants, CDP, DepVars);
|
||||
|
@ -4388,7 +4381,7 @@ static void GenerateVariantsOf(TreePatternNode *N,
|
|||
// after those.
|
||||
assert(NC >= 3 &&
|
||||
"Commutative intrinsic should have at least 3 children!");
|
||||
std::vector<std::vector<TreePatternNode*> > Variants;
|
||||
std::vector<std::vector<TreePatternNodePtr>> Variants;
|
||||
Variants.push_back(ChildVariants[0]); // Intrinsic id.
|
||||
Variants.push_back(ChildVariants[2]);
|
||||
Variants.push_back(ChildVariants[1]);
|
||||
|
@ -4396,7 +4389,7 @@ static void GenerateVariantsOf(TreePatternNode *N,
|
|||
Variants.push_back(ChildVariants[i]);
|
||||
CombineChildVariants(N, Variants, OutVariants, CDP, DepVars);
|
||||
} else if (NC == N->getNumChildren()) {
|
||||
std::vector<std::vector<TreePatternNode*> > Variants;
|
||||
std::vector<std::vector<TreePatternNodePtr>> Variants;
|
||||
Variants.push_back(ChildVariants[1]);
|
||||
Variants.push_back(ChildVariants[0]);
|
||||
for (unsigned i = 2; i != NC; ++i)
|
||||
|
@ -4423,13 +4416,13 @@ void CodeGenDAGPatterns::GenerateVariants() {
|
|||
//
|
||||
for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
|
||||
MultipleUseVarSet DepVars;
|
||||
std::vector<TreePatternNode*> Variants;
|
||||
std::vector<TreePatternNodePtr> Variants;
|
||||
FindDepVars(PatternsToMatch[i].getSrcPattern(), DepVars);
|
||||
LLVM_DEBUG(errs() << "Dependent/multiply used variables: ");
|
||||
LLVM_DEBUG(DumpDepVars(DepVars));
|
||||
LLVM_DEBUG(errs() << "\n");
|
||||
GenerateVariantsOf(PatternsToMatch[i].getSrcPattern(), Variants, *this,
|
||||
DepVars);
|
||||
GenerateVariantsOf(PatternsToMatch[i].getSrcPatternShared(), Variants,
|
||||
*this, DepVars);
|
||||
|
||||
assert(!Variants.empty() && "Must create at least original variant!");
|
||||
if (Variants.size() == 1) // No additional variants for this pattern.
|
||||
|
@ -4439,7 +4432,7 @@ void CodeGenDAGPatterns::GenerateVariants() {
|
|||
PatternsToMatch[i].getSrcPattern()->dump(); errs() << "\n");
|
||||
|
||||
for (unsigned v = 0, e = Variants.size(); v != e; ++v) {
|
||||
TreePatternNode *Variant = Variants[v];
|
||||
TreePatternNodePtr Variant = Variants[v];
|
||||
|
||||
LLVM_DEBUG(errs() << " VAR#" << v << ": "; Variant->dump();
|
||||
errs() << "\n");
|
||||
|
@ -4465,7 +4458,7 @@ void CodeGenDAGPatterns::GenerateVariants() {
|
|||
// Otherwise, add it to the list of patterns we have.
|
||||
PatternsToMatch.push_back(PatternToMatch(
|
||||
PatternsToMatch[i].getSrcRecord(), PatternsToMatch[i].getPredicates(),
|
||||
Variant, PatternsToMatch[i].getDstPattern(),
|
||||
Variant, PatternsToMatch[i].getDstPatternShared(),
|
||||
PatternsToMatch[i].getDstRegs(),
|
||||
PatternsToMatch[i].getAddedComplexity(), Record::getNewUID()));
|
||||
}
|
||||
|
|
|
@ -43,6 +43,9 @@ class TreePatternNode;
|
|||
class CodeGenDAGPatterns;
|
||||
class ComplexPattern;
|
||||
|
||||
/// Shared pointer for TreePatternNode.
|
||||
using TreePatternNodePtr = std::shared_ptr<TreePatternNode>;
|
||||
|
||||
/// This represents a set of MVTs. Since the underlying type for the MVT
|
||||
/// is uint8_t, there are at most 256 values. To reduce the number of memory
|
||||
/// allocations and deallocations, represent the set as a sequence of bits.
|
||||
|
@ -552,9 +555,6 @@ private:
|
|||
};
|
||||
|
||||
|
||||
/// FIXME: TreePatternNode's can be shared in some cases (due to dag-shaped
|
||||
/// patterns), and as such should be ref counted. We currently just leak all
|
||||
/// TreePatternNode objects!
|
||||
class TreePatternNode {
|
||||
/// The type of each node result. Before and during type inference, each
|
||||
/// result may be a set of possible types. After (successful) type inference,
|
||||
|
@ -581,18 +581,18 @@ class TreePatternNode {
|
|||
/// it can be substituted into the resulting instruction on a pattern match.
|
||||
Record *TransformFn;
|
||||
|
||||
std::vector<TreePatternNode*> Children;
|
||||
std::vector<TreePatternNodePtr> Children;
|
||||
|
||||
public:
|
||||
TreePatternNode(Record *Op, const std::vector<TreePatternNode*> &Ch,
|
||||
TreePatternNode(Record *Op, std::vector<TreePatternNodePtr> &Ch,
|
||||
unsigned NumResults)
|
||||
: Operator(Op), Val(nullptr), TransformFn(nullptr), Children(Ch) {
|
||||
: Operator(Op), Val(nullptr), TransformFn(nullptr), Children(Ch) {
|
||||
Types.resize(NumResults);
|
||||
}
|
||||
TreePatternNode(Init *val, unsigned NumResults) // leaf ctor
|
||||
: Operator(nullptr), Val(val), TransformFn(nullptr) {
|
||||
Types.resize(NumResults);
|
||||
}
|
||||
~TreePatternNode();
|
||||
|
||||
bool hasName() const { return !Name.empty(); }
|
||||
const std::string &getName() const { return Name; }
|
||||
|
@ -626,15 +626,17 @@ public:
|
|||
Record *getOperator() const { assert(!isLeaf()); return Operator; }
|
||||
|
||||
unsigned getNumChildren() const { return Children.size(); }
|
||||
TreePatternNode *getChild(unsigned N) const { return Children[N]; }
|
||||
void setChild(unsigned i, TreePatternNode *N) {
|
||||
Children[i] = N;
|
||||
TreePatternNode *getChild(unsigned N) const { return Children[N].get(); }
|
||||
const TreePatternNodePtr &getChildShared(unsigned N) const {
|
||||
return Children[N];
|
||||
}
|
||||
void setChild(unsigned i, TreePatternNodePtr N) { Children[i] = N; }
|
||||
|
||||
/// hasChild - Return true if N is any of our children.
|
||||
bool hasChild(const TreePatternNode *N) const {
|
||||
for (unsigned i = 0, e = Children.size(); i != e; ++i)
|
||||
if (Children[i] == N) return true;
|
||||
if (Children[i].get() == N)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -694,7 +696,7 @@ public: // Higher level manipulation routines.
|
|||
|
||||
/// clone - Return a new copy of this tree.
|
||||
///
|
||||
TreePatternNode *clone() const;
|
||||
TreePatternNodePtr clone() const;
|
||||
|
||||
/// RemoveAllTypes - Recursively strip all the types of this tree.
|
||||
void RemoveAllTypes();
|
||||
|
@ -708,13 +710,14 @@ public: // Higher level manipulation routines.
|
|||
|
||||
/// SubstituteFormalArguments - Replace the formal arguments in this tree
|
||||
/// with actual values specified by ArgMap.
|
||||
void SubstituteFormalArguments(std::map<std::string,
|
||||
TreePatternNode*> &ArgMap);
|
||||
void
|
||||
SubstituteFormalArguments(std::map<std::string, TreePatternNodePtr> &ArgMap);
|
||||
|
||||
/// InlinePatternFragments - If this pattern refers to any pattern
|
||||
/// fragments, inline them into place, giving us a pattern without any
|
||||
/// PatFrag references.
|
||||
TreePatternNode *InlinePatternFragments(TreePattern &TP);
|
||||
TreePatternNodePtr InlinePatternFragments(TreePatternNodePtr T,
|
||||
TreePattern &TP);
|
||||
|
||||
/// ApplyTypeConstraints - Apply all of the type constraints relevant to
|
||||
/// this node and its children in the tree. This returns true if it makes a
|
||||
|
@ -759,11 +762,11 @@ class TreePattern {
|
|||
/// Trees - The list of pattern trees which corresponds to this pattern.
|
||||
/// Note that PatFrag's only have a single tree.
|
||||
///
|
||||
std::vector<TreePatternNode*> Trees;
|
||||
std::vector<TreePatternNodePtr> Trees;
|
||||
|
||||
/// NamedNodes - This is all of the nodes that have names in the trees in this
|
||||
/// pattern.
|
||||
StringMap<SmallVector<TreePatternNode*,1> > NamedNodes;
|
||||
StringMap<SmallVector<TreePatternNode *, 1>> NamedNodes;
|
||||
|
||||
/// TheRecord - The actual TableGen record corresponding to this pattern.
|
||||
///
|
||||
|
@ -802,21 +805,21 @@ public:
|
|||
CodeGenDAGPatterns &ise);
|
||||
TreePattern(Record *TheRec, DagInit *Pat, bool isInput,
|
||||
CodeGenDAGPatterns &ise);
|
||||
TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput,
|
||||
TreePattern(Record *TheRec, TreePatternNodePtr Pat, bool isInput,
|
||||
CodeGenDAGPatterns &ise);
|
||||
|
||||
/// getTrees - Return the tree patterns which corresponds to this pattern.
|
||||
///
|
||||
const std::vector<TreePatternNode*> &getTrees() const { return Trees; }
|
||||
const std::vector<TreePatternNodePtr> &getTrees() const { return Trees; }
|
||||
unsigned getNumTrees() const { return Trees.size(); }
|
||||
TreePatternNode *getTree(unsigned i) const { return Trees[i]; }
|
||||
void setTree(unsigned i, TreePatternNode *Tree) { Trees[i] = Tree; }
|
||||
TreePatternNode *getOnlyTree() const {
|
||||
const TreePatternNodePtr &getTree(unsigned i) const { return Trees[i]; }
|
||||
void setTree(unsigned i, TreePatternNodePtr Tree) { Trees[i] = Tree; }
|
||||
TreePatternNodePtr getOnlyTree() const {
|
||||
assert(Trees.size() == 1 && "Doesn't have exactly one pattern!");
|
||||
return Trees[0];
|
||||
}
|
||||
|
||||
const StringMap<SmallVector<TreePatternNode*,1> > &getNamedNodesMap() {
|
||||
const StringMap<SmallVector<TreePatternNode *, 1>> &getNamedNodesMap() {
|
||||
if (NamedNodes.empty())
|
||||
ComputeNamedNodes();
|
||||
return NamedNodes;
|
||||
|
@ -841,14 +844,14 @@ public:
|
|||
/// PatFrag references.
|
||||
void InlinePatternFragments() {
|
||||
for (unsigned i = 0, e = Trees.size(); i != e; ++i)
|
||||
Trees[i] = Trees[i]->InlinePatternFragments(*this);
|
||||
Trees[i] = Trees[i]->InlinePatternFragments(Trees[i], *this);
|
||||
}
|
||||
|
||||
/// InferAllTypes - Infer/propagate as many types throughout the expression
|
||||
/// patterns as possible. Return true if all types are inferred, false
|
||||
/// otherwise. Bail out if a type contradiction is found.
|
||||
bool InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> >
|
||||
*NamedTypes=nullptr);
|
||||
bool InferAllTypes(
|
||||
const StringMap<SmallVector<TreePatternNode *, 1>> *NamedTypes = nullptr);
|
||||
|
||||
/// error - If this is the first error in the current resolution step,
|
||||
/// print it and set the error flag. Otherwise, continue silently.
|
||||
|
@ -866,7 +869,7 @@ public:
|
|||
void dump() const;
|
||||
|
||||
private:
|
||||
TreePatternNode *ParseTreePattern(Init *DI, StringRef OpName);
|
||||
TreePatternNodePtr ParseTreePattern(Init *DI, StringRef OpName);
|
||||
void ComputeNamedNodes();
|
||||
void ComputeNamedNodes(TreePatternNode *N);
|
||||
};
|
||||
|
@ -900,7 +903,7 @@ inline bool TreePatternNode::UpdateNodeType(unsigned ResNo,
|
|||
/// DAGDefaultOperand - One of these is created for each OperandWithDefaultOps
|
||||
/// that has a set ExecuteAlways / DefaultOps field.
|
||||
struct DAGDefaultOperand {
|
||||
std::vector<TreePatternNode*> DefaultOps;
|
||||
std::vector<TreePatternNodePtr> DefaultOps;
|
||||
};
|
||||
|
||||
class DAGInstruction {
|
||||
|
@ -908,7 +911,8 @@ class DAGInstruction {
|
|||
std::vector<Record*> Results;
|
||||
std::vector<Record*> Operands;
|
||||
std::vector<Record*> ImpResults;
|
||||
TreePatternNode *ResultPattern;
|
||||
TreePatternNodePtr ResultPattern;
|
||||
|
||||
public:
|
||||
DAGInstruction(TreePattern *TP,
|
||||
const std::vector<Record*> &results,
|
||||
|
@ -923,7 +927,7 @@ public:
|
|||
unsigned getNumImpResults() const { return ImpResults.size(); }
|
||||
const std::vector<Record*>& getImpResults() const { return ImpResults; }
|
||||
|
||||
void setResultPattern(TreePatternNode *R) { ResultPattern = R; }
|
||||
void setResultPattern(TreePatternNodePtr R) { ResultPattern = R; }
|
||||
|
||||
Record *getResult(unsigned RN) const {
|
||||
assert(RN < Results.size());
|
||||
|
@ -940,7 +944,7 @@ public:
|
|||
return ImpResults[RN];
|
||||
}
|
||||
|
||||
TreePatternNode *getResultPattern() const { return ResultPattern; }
|
||||
TreePatternNodePtr getResultPattern() const { return ResultPattern; }
|
||||
};
|
||||
|
||||
/// This class represents a condition that has to be satisfied for a pattern
|
||||
|
@ -995,24 +999,24 @@ public:
|
|||
class PatternToMatch {
|
||||
public:
|
||||
PatternToMatch(Record *srcrecord, const std::vector<Predicate> &preds,
|
||||
TreePatternNode *src, TreePatternNode *dst,
|
||||
const std::vector<Record*> &dstregs,
|
||||
int complexity, unsigned uid, unsigned setmode = 0)
|
||||
: SrcRecord(srcrecord), SrcPattern(src), DstPattern(dst),
|
||||
Predicates(preds), Dstregs(std::move(dstregs)),
|
||||
AddedComplexity(complexity), ID(uid), ForceMode(setmode) {}
|
||||
TreePatternNodePtr src, TreePatternNodePtr dst,
|
||||
const std::vector<Record *> &dstregs, int complexity,
|
||||
unsigned uid, unsigned setmode = 0)
|
||||
: SrcRecord(srcrecord), SrcPattern(src), DstPattern(dst),
|
||||
Predicates(preds), Dstregs(std::move(dstregs)),
|
||||
AddedComplexity(complexity), ID(uid), ForceMode(setmode) {}
|
||||
|
||||
PatternToMatch(Record *srcrecord, std::vector<Predicate> &&preds,
|
||||
TreePatternNode *src, TreePatternNode *dst,
|
||||
std::vector<Record*> &&dstregs,
|
||||
int complexity, unsigned uid, unsigned setmode = 0)
|
||||
: SrcRecord(srcrecord), SrcPattern(src), DstPattern(dst),
|
||||
Predicates(preds), Dstregs(std::move(dstregs)),
|
||||
AddedComplexity(complexity), ID(uid), ForceMode(setmode) {}
|
||||
TreePatternNodePtr src, TreePatternNodePtr dst,
|
||||
std::vector<Record *> &&dstregs, int complexity, unsigned uid,
|
||||
unsigned setmode = 0)
|
||||
: SrcRecord(srcrecord), SrcPattern(src), DstPattern(dst),
|
||||
Predicates(preds), Dstregs(std::move(dstregs)),
|
||||
AddedComplexity(complexity), ID(uid), ForceMode(setmode) {}
|
||||
|
||||
Record *SrcRecord; // Originating Record for the pattern.
|
||||
TreePatternNode *SrcPattern; // Source pattern to match.
|
||||
TreePatternNode *DstPattern; // Resulting pattern.
|
||||
TreePatternNodePtr SrcPattern; // Source pattern to match.
|
||||
TreePatternNodePtr DstPattern; // Resulting pattern.
|
||||
std::vector<Predicate> Predicates; // Top level predicate conditions
|
||||
// to match.
|
||||
std::vector<Record*> Dstregs; // Physical register defs being matched.
|
||||
|
@ -1021,8 +1025,10 @@ public:
|
|||
unsigned ForceMode; // Force this mode in type inference when set.
|
||||
|
||||
Record *getSrcRecord() const { return SrcRecord; }
|
||||
TreePatternNode *getSrcPattern() const { return SrcPattern; }
|
||||
TreePatternNode *getDstPattern() const { return DstPattern; }
|
||||
TreePatternNode *getSrcPattern() const { return SrcPattern.get(); }
|
||||
TreePatternNodePtr getSrcPatternShared() const { return SrcPattern; }
|
||||
TreePatternNode *getDstPattern() const { return DstPattern.get(); }
|
||||
TreePatternNodePtr getDstPatternShared() const { return DstPattern; }
|
||||
const std::vector<Record*> &getDstRegs() const { return Dstregs; }
|
||||
int getAddedComplexity() const { return AddedComplexity; }
|
||||
const std::vector<Predicate> &getPredicates() const { return Predicates; }
|
||||
|
@ -1194,12 +1200,11 @@ private:
|
|||
std::vector<Predicate> makePredList(ListInit *L);
|
||||
|
||||
void AddPatternToMatch(TreePattern *Pattern, PatternToMatch &&PTM);
|
||||
void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
|
||||
std::map<std::string,
|
||||
TreePatternNode*> &InstInputs,
|
||||
std::map<std::string,
|
||||
TreePatternNode*> &InstResults,
|
||||
std::vector<Record*> &InstImpResults);
|
||||
void FindPatternInputsAndOutputs(
|
||||
TreePattern *I, TreePatternNodePtr Pat,
|
||||
std::map<std::string, TreePatternNodePtr> &InstInputs,
|
||||
std::map<std::string, TreePatternNodePtr> &InstResults,
|
||||
std::vector<Record *> &InstImpResults);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace {
|
|||
/// PatWithNoTypes - This is a clone of Pattern.getSrcPattern() that starts
|
||||
/// out with all of the types removed. This allows us to insert type checks
|
||||
/// as we scan the tree.
|
||||
TreePatternNode *PatWithNoTypes;
|
||||
TreePatternNodePtr PatWithNoTypes;
|
||||
|
||||
/// VariableMap - A map from variable names ('$dst') to the recorded operand
|
||||
/// number that they were captured as. These are biased by 1 to make
|
||||
|
@ -101,10 +101,6 @@ namespace {
|
|||
public:
|
||||
MatcherGen(const PatternToMatch &pattern, const CodeGenDAGPatterns &cgp);
|
||||
|
||||
~MatcherGen() {
|
||||
delete PatWithNoTypes;
|
||||
}
|
||||
|
||||
bool EmitMatcherCode(unsigned Variant);
|
||||
void EmitResultCode();
|
||||
|
||||
|
@ -521,7 +517,8 @@ bool MatcherGen::EmitMatcherCode(unsigned Variant) {
|
|||
}
|
||||
|
||||
// Emit the matcher for the pattern structure and types.
|
||||
EmitMatchCode(Pattern.getSrcPattern(), PatWithNoTypes, Pattern.ForceMode);
|
||||
EmitMatchCode(Pattern.getSrcPattern(), PatWithNoTypes.get(),
|
||||
Pattern.ForceMode);
|
||||
|
||||
// If the pattern has a predicate on it (e.g. only enabled when a subtarget
|
||||
// feature is around, do the check).
|
||||
|
@ -533,7 +530,7 @@ bool MatcherGen::EmitMatcherCode(unsigned Variant) {
|
|||
// because they are generally more expensive to evaluate and more difficult to
|
||||
// factor.
|
||||
for (unsigned i = 0, e = MatchedComplexPatterns.size(); i != e; ++i) {
|
||||
const TreePatternNode *N = MatchedComplexPatterns[i].first;
|
||||
auto N = MatchedComplexPatterns[i].first;
|
||||
|
||||
// Remember where the results of this match get stuck.
|
||||
if (N->isLeaf()) {
|
||||
|
@ -673,7 +670,7 @@ GetInstPatternNode(const DAGInstruction &Inst, const TreePatternNode *N) {
|
|||
// FIXME2?: Assume actual pattern comes before "implicit".
|
||||
TreePatternNode *InstPatNode;
|
||||
if (InstPat)
|
||||
InstPatNode = InstPat->getTree(0);
|
||||
InstPatNode = InstPat->getTree(0).get();
|
||||
else if (/*isRoot*/ N == Pattern.getDstPattern())
|
||||
InstPatNode = Pattern.getSrcPattern();
|
||||
else
|
||||
|
@ -784,7 +781,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
|
|||
const DAGDefaultOperand &DefaultOp
|
||||
= CGP.getDefaultOperand(OperandNode);
|
||||
for (unsigned i = 0, e = DefaultOp.DefaultOps.size(); i != e; ++i)
|
||||
EmitResultOperand(DefaultOp.DefaultOps[i], InstOps);
|
||||
EmitResultOperand(DefaultOp.DefaultOps[i].get(), InstOps);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue