return false;
for (unsigned i = 0, e = LegalTypes.size(); i != e; ++i)
- if (Pred == 0 || Pred(LegalTypes[i]))
+ if (!Pred || Pred(LegalTypes[i]))
TypeVec.push_back(LegalTypes[i]);
// If we have nothing that matches the predicate, bail out.
return false;
}
+/// hasScalarTypes - Return true if this TypeSet contains a scalar value type.
+bool EEVT::TypeSet::hasScalarTypes() const {
+ for (unsigned i = 0, e = TypeVec.size(); i != e; ++i)
+ if (isScalar(TypeVec[i]))
+ return true;
+ return false;
+}
+
/// hasVectorTypes - Return true if this TypeSet contains a vAny or a vector
/// value type.
bool EEVT::TypeSet::hasVectorTypes() const {
-/// EnforceSmallerThan - 'this' must be a smaller VT than Other. Update
-/// this an other based on this information.
+/// EnforceSmallerThan - 'this' must be a smaller VT than Other. For vectors
+/// this shoud be based on the element type. Update this and other based on
+/// this information.
bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
if (TP.hasError())
return false;
// If one contains vectors but the other doesn't pull vectors out.
if (!hasVectorTypes())
MadeChange |= Other.EnforceScalar(TP);
- if (!hasVectorTypes())
+ else if (!hasScalarTypes())
+ MadeChange |= Other.EnforceVector(TP);
+ if (!Other.hasVectorTypes())
MadeChange |= EnforceScalar(TP);
+ else if (!Other.hasScalarTypes())
+ MadeChange |= EnforceVector(TP);
- if (TypeVec.size() == 1 && Other.TypeVec.size() == 1) {
- // If we are down to concrete types, this code does not currently
- // handle nodes which have multiple types, where some types are
- // integer, and some are fp. Assert that this is not the case.
- assert(!(hasIntegerTypes() && hasFloatingPointTypes()) &&
- !(Other.hasIntegerTypes() && Other.hasFloatingPointTypes()) &&
- "SDTCisOpSmallerThanOp does not handle mixed int/fp types!");
-
- // Otherwise, if these are both vector types, either this vector
- // must have a larger bitsize than the other, or this element type
- // must be larger than the other.
- MVT Type(TypeVec[0]);
- MVT OtherType(Other.TypeVec[0]);
-
- if (hasVectorTypes() && Other.hasVectorTypes()) {
- if (Type.getSizeInBits() >= OtherType.getSizeInBits())
- if (Type.getVectorElementType().getSizeInBits()
- >= OtherType.getVectorElementType().getSizeInBits()) {
- TP.error("Type inference contradiction found, '" +
- getName() + "' element type not smaller than '" +
- Other.getName() +"'!");
- return false;
- }
- } else
- // For scalar types, the bitsize of this type must be larger
- // than that of the other.
- if (Type.getSizeInBits() >= OtherType.getSizeInBits()) {
- TP.error("Type inference contradiction found, '" +
- getName() + "' is not smaller than '" +
- Other.getName() +"'!");
- return false;
- }
- }
-
-
- // Handle int and fp as disjoint sets. This won't work for patterns
- // that have mixed fp/int types but those are likely rare and would
- // not have been accepted by this code previously.
+ // For vectors we need to ensure that smaller size doesn't produce larger
+ // vector and vice versa.
+ if (isConcrete() && isVector(getConcrete())) {
+ MVT IVT = getConcrete();
+ unsigned Size = IVT.getSizeInBits();
- // Okay, find the smallest type from the current set and remove it from the
- // largest set.
- MVT::SimpleValueType SmallestInt = MVT::LAST_VALUETYPE;
- for (unsigned i = 0, e = TypeVec.size(); i != e; ++i)
- if (isInteger(TypeVec[i])) {
- SmallestInt = TypeVec[i];
- break;
- }
- for (unsigned i = 1, e = TypeVec.size(); i != e; ++i)
- if (isInteger(TypeVec[i]) && TypeVec[i] < SmallestInt)
- SmallestInt = TypeVec[i];
+ // Only keep types that have at least as many bits.
+ TypeSet InputSet(Other);
- MVT::SimpleValueType SmallestFP = MVT::LAST_VALUETYPE;
- for (unsigned i = 0, e = TypeVec.size(); i != e; ++i)
- if (isFloatingPoint(TypeVec[i])) {
- SmallestFP = TypeVec[i];
- break;
- }
- for (unsigned i = 1, e = TypeVec.size(); i != e; ++i)
- if (isFloatingPoint(TypeVec[i]) && TypeVec[i] < SmallestFP)
- SmallestFP = TypeVec[i];
-
- int OtherIntSize = 0;
- int OtherFPSize = 0;
- for (SmallVectorImpl<MVT::SimpleValueType>::iterator TVI =
- Other.TypeVec.begin();
- TVI != Other.TypeVec.end();
- /* NULL */) {
- if (isInteger(*TVI)) {
- ++OtherIntSize;
- if (*TVI == SmallestInt) {
- TVI = Other.TypeVec.erase(TVI);
- --OtherIntSize;
+ for (unsigned i = 0; i != Other.TypeVec.size(); ++i) {
+ assert(isVector(Other.TypeVec[i]) && "EnforceVector didn't work");
+ if (MVT(Other.TypeVec[i]).getSizeInBits() < Size) {
+ Other.TypeVec.erase(Other.TypeVec.begin()+i--);
MadeChange = true;
- continue;
}
- } else if (isFloatingPoint(*TVI)) {
- ++OtherFPSize;
- if (*TVI == SmallestFP) {
- TVI = Other.TypeVec.erase(TVI);
- --OtherFPSize;
+ }
+
+ if (Other.TypeVec.empty()) { // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, forcing '" +
+ InputSet.getName() + "' to have at least as many bits as " +
+ getName() + "'");
+ return false;
+ }
+ } else if (Other.isConcrete() && isVector(Other.getConcrete())) {
+ MVT IVT = Other.getConcrete();
+ unsigned Size = IVT.getSizeInBits();
+
+ // Only keep types with the same or fewer total bits
+ TypeSet InputSet(*this);
+
+ for (unsigned i = 0; i != TypeVec.size(); ++i) {
+ assert(isVector(TypeVec[i]) && "EnforceVector didn't work");
+ if (MVT(TypeVec[i]).getSizeInBits() > Size) {
+ TypeVec.erase(TypeVec.begin()+i--);
MadeChange = true;
- continue;
}
}
- ++TVI;
+
+ if (TypeVec.empty()) { // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, forcing '" +
+ InputSet.getName() + "' to have the same or fewer bits than " +
+ Other.getName() + "'");
+ return false;
+ }
}
- // If this is the only type in the large set, the constraint can never be
- // satisfied.
- if ((Other.hasIntegerTypes() && OtherIntSize == 0) ||
- (Other.hasFloatingPointTypes() && OtherFPSize == 0)) {
- TP.error("Type inference contradiction found, '" +
- Other.getName() + "' has nothing larger than '" + getName() +"'!");
+ // This code does not currently handle nodes which have multiple types,
+ // where some types are integer, and some are fp. Assert that this is not
+ // the case.
+ assert(!(hasIntegerTypes() && hasFloatingPointTypes()) &&
+ !(Other.hasIntegerTypes() && Other.hasFloatingPointTypes()) &&
+ "SDTCisOpSmallerThanOp does not handle mixed int/fp types!");
+
+ if (TP.hasError())
return false;
+
+ // Okay, find the smallest scalar type from the other set and remove
+ // anything the same or smaller from the current set.
+ TypeSet InputSet(Other);
+ MVT::SimpleValueType Smallest = TypeVec[0];
+ for (unsigned i = 0; i != Other.TypeVec.size(); ++i) {
+ if (Other.TypeVec[i] <= Smallest) {
+ Other.TypeVec.erase(Other.TypeVec.begin()+i--);
+ MadeChange = true;
+ }
}
- // Okay, find the largest type in the Other set and remove it from the
- // current set.
- MVT::SimpleValueType LargestInt = MVT::Other;
- for (unsigned i = 0, e = Other.TypeVec.size(); i != e; ++i)
- if (isInteger(Other.TypeVec[i])) {
- LargestInt = Other.TypeVec[i];
- break;
- }
- for (unsigned i = 1, e = Other.TypeVec.size(); i != e; ++i)
- if (isInteger(Other.TypeVec[i]) && Other.TypeVec[i] > LargestInt)
- LargestInt = Other.TypeVec[i];
-
- MVT::SimpleValueType LargestFP = MVT::Other;
- for (unsigned i = 0, e = Other.TypeVec.size(); i != e; ++i)
- if (isFloatingPoint(Other.TypeVec[i])) {
- LargestFP = Other.TypeVec[i];
- break;
- }
- for (unsigned i = 1, e = Other.TypeVec.size(); i != e; ++i)
- if (isFloatingPoint(Other.TypeVec[i]) && Other.TypeVec[i] > LargestFP)
- LargestFP = Other.TypeVec[i];
-
- int IntSize = 0;
- int FPSize = 0;
- for (SmallVectorImpl<MVT::SimpleValueType>::iterator TVI =
- TypeVec.begin();
- TVI != TypeVec.end();
- /* NULL */) {
- if (isInteger(*TVI)) {
- ++IntSize;
- if (*TVI == LargestInt) {
- TVI = TypeVec.erase(TVI);
- --IntSize;
- MadeChange = true;
- continue;
- }
- } else if (isFloatingPoint(*TVI)) {
- ++FPSize;
- if (*TVI == LargestFP) {
- TVI = TypeVec.erase(TVI);
- --FPSize;
- MadeChange = true;
- continue;
- }
+ if (Other.TypeVec.empty()) {
+ TP.error("Type inference contradiction found, '" + InputSet.getName() +
+ "' has nothing larger than '" + getName() +"'!");
+ return false;
+ }
+
+ // Okay, find the largest scalar type from the other set and remove
+ // anything the same or larger from the current set.
+ InputSet = TypeSet(*this);
+ MVT::SimpleValueType Largest = Other.TypeVec[Other.TypeVec.size()-1];
+ for (unsigned i = 0; i != TypeVec.size(); ++i) {
+ if (TypeVec[i] >= Largest) {
+ TypeVec.erase(TypeVec.begin()+i--);
+ MadeChange = true;
}
- ++TVI;
}
- // If this is the only type in the small set, the constraint can never be
- // satisfied.
- if ((hasIntegerTypes() && IntSize == 0) ||
- (hasFloatingPointTypes() && FPSize == 0)) {
- TP.error("Type inference contradiction found, '" +
- getName() + "' has nothing smaller than '" + Other.getName()+"'!");
+ if (TypeVec.empty()) {
+ TP.error("Type inference contradiction found, '" + InputSet.getName() +
+ "' has nothing smaller than '" + Other.getName() +"'!");
return false;
}
/// vector type specified by VTOperand.
bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand,
TreePattern &TP) {
+ if (TP.hasError())
+ return false;
+
// "This" must be a vector and "VTOperand" must be a vector.
bool MadeChange = false;
MadeChange |= EnforceVector(TP);
MadeChange |= VTOperand.EnforceVector(TP);
- // "This" must be larger than "VTOperand."
- MadeChange |= VTOperand.EnforceSmallerThan(*this, TP);
+ // If one side is known to be integer or known to be FP but the other side has
+ // no information, get at least the type integrality info in there.
+ if (!hasFloatingPointTypes())
+ MadeChange |= VTOperand.EnforceInteger(TP);
+ else if (!hasIntegerTypes())
+ MadeChange |= VTOperand.EnforceFloatingPoint(TP);
+ if (!VTOperand.hasFloatingPointTypes())
+ MadeChange |= EnforceInteger(TP);
+ else if (!VTOperand.hasIntegerTypes())
+ MadeChange |= EnforceFloatingPoint(TP);
+
+ assert(!isCompletelyUnknown() && !VTOperand.isCompletelyUnknown() &&
+ "Should have a type list now");
// If we know the vector type, it forces the scalar types to agree.
+ // Also force one vector to have more elements than the other.
if (isConcrete()) {
MVT IVT = getConcrete();
+ unsigned NumElems = IVT.getVectorNumElements();
IVT = IVT.getVectorElementType();
EEVT::TypeSet EltTypeSet(IVT.SimpleTy, TP);
MadeChange |= VTOperand.EnforceVectorEltTypeIs(EltTypeSet, TP);
+
+ // Only keep types that have less elements than VTOperand.
+ TypeSet InputSet(VTOperand);
+
+ for (unsigned i = 0; i != VTOperand.TypeVec.size(); ++i) {
+ assert(isVector(VTOperand.TypeVec[i]) && "EnforceVector didn't work");
+ if (MVT(VTOperand.TypeVec[i]).getVectorNumElements() >= NumElems) {
+ VTOperand.TypeVec.erase(VTOperand.TypeVec.begin()+i--);
+ MadeChange = true;
+ }
+ }
+ if (VTOperand.TypeVec.empty()) { // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, forcing '" +
+ InputSet.getName() + "' to have less vector elements than '" +
+ getName() + "'");
+ return false;
+ }
} else if (VTOperand.isConcrete()) {
MVT IVT = VTOperand.getConcrete();
+ unsigned NumElems = IVT.getVectorNumElements();
IVT = IVT.getVectorElementType();
EEVT::TypeSet EltTypeSet(IVT.SimpleTy, TP);
MadeChange |= EnforceVectorEltTypeIs(EltTypeSet, TP);
+
+ // Only keep types that have more elements than 'this'.
+ TypeSet InputSet(*this);
+
+ for (unsigned i = 0; i != TypeVec.size(); ++i) {
+ assert(isVector(TypeVec[i]) && "EnforceVector didn't work");
+ if (MVT(TypeVec[i]).getVectorNumElements() <= NumElems) {
+ TypeVec.erase(TypeVec.begin()+i--);
+ MadeChange = true;
+ }
+ }
+ if (TypeVec.empty()) { // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, forcing '" +
+ InputSet.getName() + "' to have more vector elements than '" +
+ VTOperand.getName() + "'");
+ return false;
+ }
}
return MadeChange;
// Both RegisterClass and RegisterOperand operands derive their types from a
// register class def.
- Record *RC = 0;
+ Record *RC = nullptr;
if (Operand->isSubClassOf("RegisterClass"))
RC = Operand;
else if (Operand->isSubClassOf("RegisterOperand"))
// Get the result tree.
DagInit *Tree = Operator->getValueAsDag("Fragment");
- Record *Op = 0;
+ Record *Op = nullptr;
if (Tree)
if (DefInit *DI = dyn_cast<DefInit>(Tree->getOperator()))
Op = DI->getDef();
if (Operator->isSubClassOf("SDNodeXForm"))
return 1; // FIXME: Generalize SDNodeXForm
+ if (Operator->isSubClassOf("ValueType"))
+ return 1; // A type-cast of one result.
+
Operator->dump();
errs() << "Unhandled node in GetNumNodeResults\n";
exit(1);
TreePatternNode *Child = getChild(i);
if (Child->isLeaf()) {
Init *Val = Child->getLeafValue();
- if (isa<DefInit>(Val) &&
- cast<DefInit>(Val)->getDef()->getName() == "node") {
+ // Note that, when substituting into an output pattern, Val might be an
+ // UnsetInit.
+ 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()];
assert(NewChild && "Couldn't find formal argument!");
/// PatFrag references.
TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
if (TP.hasError())
- return 0;
+ return nullptr;
if (isLeaf())
return this; // nothing to do.
if (Frag->getNumArgs() != Children.size()) {
TP.error("'" + Op->getName() + "' fragment requires " +
utostr(Frag->getNumArgs()) + " operands!");
- return 0;
+ return nullptr;
}
TreePatternNode *FragTree = Frag->getOnlyTree()->clone();
if (getOperator() != CDP.get_intrinsic_void_sdnode() &&
getOperator() != CDP.get_intrinsic_w_chain_sdnode() &&
getOperator() != CDP.get_intrinsic_wo_chain_sdnode())
- return 0;
+ return nullptr;
unsigned IID = cast<IntInit>(getChild(0)->getLeafValue())->getValue();
return &CDP.getIntrinsicInfo(IID);
/// return the ComplexPattern information, otherwise return null.
const ComplexPattern *
TreePatternNode::getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const {
- if (!isLeaf()) return 0;
+ if (!isLeaf()) return nullptr;
DefInit *DI = dyn_cast<DefInit>(getLeafValue());
if (DI && DI->getDef()->isSubClassOf("ComplexPattern"))
return &CGP.getComplexPattern(DI->getDef());
- return 0;
+ return nullptr;
}
/// NodeHasProperty - Return true if this node has the specified property.
if (BitsInit *BI = dyn_cast<BitsInit>(TheInit)) {
// Turn this into an IntInit.
Init *II = BI->convertInitializerTo(IntRecTy::get());
- if (II == 0 || !isa<IntInit>(II))
+ if (!II || !isa<IntInit>(II))
error("Bits value must be constants!");
return ParseTreePattern(II, OpName);
}
ParsePatternFragments();
ParseDefaultOperands();
ParseInstructions();
+ ParsePatternFragments(/*OutFrags*/true);
ParsePatterns();
// Generate variants. For example, commutative patterns can match
/// inline fragments together as necessary, so that there are no references left
/// inside a pattern fragment to a pattern fragment.
///
-void CodeGenDAGPatterns::ParsePatternFragments() {
+void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) {
std::vector<Record*> Fragments = Records.getAllDerivedDefinitions("PatFrag");
// First step, parse all of the fragments.
for (unsigned i = 0, e = Fragments.size(); i != e; ++i) {
+ if (OutFrags != Fragments[i]->isSubClassOf("OutPatFrag"))
+ continue;
+
DagInit *Tree = Fragments[i]->getValueAsDag("Fragment");
- TreePattern *P = new TreePattern(Fragments[i], Tree, true, *this);
+ TreePattern *P =
+ new TreePattern(Fragments[i], Tree,
+ !Fragments[i]->isSubClassOf("OutPatFrag"), *this);
PatternFragments[Fragments[i]] = P;
// Validate the argument list, converting it to set, to discard duplicates.
// Now that we've parsed all of the tree fragments, do a closure on them so
// that there are not references to PatFrags left inside of them.
for (unsigned i = 0, e = Fragments.size(); i != e; ++i) {
+ if (OutFrags != Fragments[i]->isSubClassOf("OutPatFrag"))
+ continue;
+
TreePattern *ThePat = PatternFragments[Fragments[i]];
ThePat->InlinePatternFragments();
/* Resolve all types */;
if (TPN->ContainsUnresolvedType()) {
- PrintFatalError("Value #" + utostr(i) + " of OperandWithDefaultOps '" +
- DefaultOps[i]->getName() +"' doesn't have a concrete type!");
+ PrintFatalError("Value #" + Twine(i) + " of OperandWithDefaultOps '" +
+ DefaultOps[i]->getName() +
+ "' doesn't have a concrete type!");
}
DefaultOpInfo.DefaultOps.push_back(TPN);
}
// Check that all of the results occur first in the list.
std::vector<Record*> Results;
- TreePatternNode *Res0Node = 0;
+ TreePatternNode *Res0Node = nullptr;
for (unsigned i = 0; i != NumResults; ++i) {
if (i == CGI.Operands.size())
I->error("'" + InstResults.begin()->first +
// Check that it exists in InstResults.
TreePatternNode *RNode = InstResults[OpName];
- if (RNode == 0)
+ if (!RNode)
I->error("Operand $" + OpName + " does not exist in operand list!");
if (i == 0)
Res0Node = RNode;
Record *R = cast<DefInit>(RNode->getLeafValue())->getDef();
- if (R == 0)
+ if (!R)
I->error("Operand $" + OpName + " should be a set destination: all "
"outputs must occur before inputs in operand list!");
// Promote the xform function to be an explicit node if set.
if (Record *Xform = OpNode->getTransformFn()) {
- OpNode->setTransformFn(0);
+ OpNode->setTransformFn(nullptr);
std::vector<TreePatternNode*> Children;
Children.push_back(OpNode);
OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes());
std::vector<Record*> Instrs = Records.getAllDerivedDefinitions("Instruction");
for (unsigned i = 0, e = Instrs.size(); i != e; ++i) {
- ListInit *LI = 0;
+ ListInit *LI = nullptr;
if (isa<ListInit>(Instrs[i]->getValueInit("Pattern")))
LI = Instrs[i]->getValueAsListInit("Pattern");
// Create and insert the instruction.
std::vector<Record*> ImpResults;
Instructions.insert(std::make_pair(Instrs[i],
- DAGInstruction(0, Results, Operands, ImpResults)));
+ DAGInstruction(nullptr, Results, Operands, ImpResults)));
continue; // no pattern.
}
CodeGenInstruction &CGI = Target.getInstruction(Instrs[i]);
const DAGInstruction &DI = parseInstructionPattern(CGI, LI, Instructions);
+ (void)DI;
DEBUG(DI.getPattern()->dump());
}
E = Instructions.end(); II != E; ++II) {
DAGInstruction &TheInst = II->second;
TreePattern *I = TheInst.getPattern();
- if (I == 0) continue; // No pattern.
+ if (!I) continue; // No pattern.
// FIXME: Assume only the first tree is the pattern. The others are clobber
// nodes.
// they don't exist in the input pattern.
for (std::map<std::string, NameRecord>::iterator
I = DstNames.begin(), E = DstNames.end(); I != E; ++I) {
- if (SrcNames[I->first].first == 0)
+ if (SrcNames[I->first].first == nullptr)
Pattern->error("Pattern has input without matching name in output: $" +
I->first);
}
// name isn't used in the dest, and isn't used to tie two values together.
for (std::map<std::string, NameRecord>::iterator
I = SrcNames.begin(), E = SrcNames.end(); I != E; ++I)
- if (DstNames[I->first].first == 0 && SrcNames[I->first].second == 1)
+ if (DstNames[I->first].first == nullptr && SrcNames[I->first].second == 1)
Pattern->error("Pattern has dead named input: $" + I->first);
PatternsToMatch.push_back(PTM);
for (unsigned ii = 0, ee = DstPattern->getNumChildren(); ii != ee; ++ii) {
TreePatternNode *OpNode = DstPattern->getChild(ii);
if (Record *Xform = OpNode->getTransformFn()) {
- OpNode->setTransformFn(0);
+ OpNode->setTransformFn(nullptr);
std::vector<TreePatternNode*> Children;
Children.push_back(OpNode);
OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes());