diff options
Diffstat (limited to 'utils/TableGen/CodeGenDAGPatterns.cpp')
-rw-r--r-- | utils/TableGen/CodeGenDAGPatterns.cpp | 110 |
1 files changed, 82 insertions, 28 deletions
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 96c90c9cf6bd..c8f710d66a03 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -1,9 +1,8 @@ //===- CodeGenDAGPatterns.cpp - Read DAG patterns from .td file -----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -68,8 +67,10 @@ static bool berase_if(MachineValueTypeSet &S, Predicate P) { // inference will apply to each mode separately. TypeSetByHwMode::TypeSetByHwMode(ArrayRef<ValueTypeByHwMode> VTList) { - for (const ValueTypeByHwMode &VVT : VTList) + for (const ValueTypeByHwMode &VVT : VTList) { insert(VVT); + AddrSpaces.push_back(VVT.PtrAddrSpace); + } } bool TypeSetByHwMode::isValueTypeByHwMode(bool AllowEmpty) const { @@ -86,9 +87,13 @@ ValueTypeByHwMode TypeSetByHwMode::getValueTypeByHwMode() const { assert(isValueTypeByHwMode(true) && "The type set has multiple types for at least one HW mode"); ValueTypeByHwMode VVT; + auto ASI = AddrSpaces.begin(); + for (const auto &I : *this) { MVT T = I.second.empty() ? MVT::Other : *I.second.begin(); VVT.getOrCreateTypeForMode(I.first, T); + if (ASI != AddrSpaces.end()) + VVT.PtrAddrSpace = *ASI++; } return VVT; } @@ -502,22 +507,14 @@ bool TypeInfer::EnforceSmallerThan(TypeSetByHwMode &Small, (A.getScalarSizeInBits() == B.getScalarSizeInBits() && A.getSizeInBits() < B.getSizeInBits()); }; - auto LE = [](MVT A, MVT B) -> bool { + auto LE = [<](MVT A, MVT B) -> bool { // This function is used when removing elements: when a vector is compared // to a non-vector, it should return false (to avoid removal). if (A.isVector() != B.isVector()) return false; - // Note on the < comparison below: - // X86 has patterns like - // (set VR128X:$dst, (v16i8 (X86vtrunc (v4i32 VR128X:$src1)))), - // where the truncated vector is given a type v16i8, while the source - // vector has type v4i32. They both have the same size in bits. - // The minimal type in the result is obviously v16i8, and when we remove - // all types from the source that are smaller-or-equal than v8i16, the - // only source type would also be removed (since it's equal in size). - return A.getScalarSizeInBits() <= B.getScalarSizeInBits() || - A.getSizeInBits() < B.getSizeInBits(); + return LT(A, B) || (A.getScalarSizeInBits() == B.getScalarSizeInBits() && + A.getSizeInBits() == B.getSizeInBits()); }; for (unsigned M : Modes) { @@ -957,13 +954,33 @@ std::string TreePredicateFn::getPredCode() const { } if (isLoad() || isStore() || isAtomic()) { - StringRef SDNodeName = - isLoad() ? "LoadSDNode" : isStore() ? "StoreSDNode" : "AtomicSDNode"; + if (ListInit *AddressSpaces = getAddressSpaces()) { + Code += "unsigned AddrSpace = cast<MemSDNode>(N)->getAddressSpace();\n" + " if ("; + + bool First = true; + for (Init *Val : AddressSpaces->getValues()) { + if (First) + First = false; + else + Code += " && "; + + IntInit *IntVal = dyn_cast<IntInit>(Val); + if (!IntVal) { + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "AddressSpaces element must be integer"); + } + + Code += "AddrSpace != " + utostr(IntVal->getValue()); + } + + Code += ")\nreturn false;\n"; + } Record *MemoryVT = getMemoryVT(); if (MemoryVT) - Code += ("if (cast<" + SDNodeName + ">(N)->getMemoryVT() != MVT::" + + Code += ("if (cast<MemSDNode>(N)->getMemoryVT() != MVT::" + MemoryVT->getName() + ") return false;\n") .str(); } @@ -1152,6 +1169,14 @@ Record *TreePredicateFn::getMemoryVT() const { return nullptr; return R->getValueAsDef("MemoryVT"); } + +ListInit *TreePredicateFn::getAddressSpaces() const { + Record *R = getOrigPatFragRecord()->getRecord(); + if (R->isValueUnset("AddressSpaces")) + return nullptr; + return R->getValueAsListInit("AddressSpaces"); +} + Record *TreePredicateFn::getScalarMemoryVT() const { Record *R = getOrigPatFragRecord()->getRecord(); if (R->isValueUnset("ScalarMemoryVT")) @@ -1276,6 +1301,17 @@ std::string TreePredicateFn::getCodeToRunOnSDNode() const { // PatternToMatch implementation // +static bool isImmAllOnesAllZerosMatch(const TreePatternNode *P) { + if (!P->isLeaf()) + return false; + DefInit *DI = dyn_cast<DefInit>(P->getLeafValue()); + if (!DI) + return false; + + Record *R = DI->getDef(); + return R->getName() == "immAllOnesV" || R->getName() == "immAllZerosV"; +} + /// getPatternSize - Return the 'size' of this pattern. We want to match large /// patterns before small ones. This is used to determine the size of a /// pattern. @@ -1315,6 +1351,8 @@ static unsigned getPatternSize(const TreePatternNode *P, Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2). else if (Child->getComplexPatternInfo(CGP)) Size += getPatternSize(Child, CGP); + else if (isImmAllOnesAllZerosMatch(Child)) + Size += 4; // Matches a build_vector(+3) and a predicate (+1). else if (!Child->getPredicateCalls().empty()) ++Size; } @@ -1408,7 +1446,8 @@ SDTypeConstraint::SDTypeConstraint(Record *R, const CodeGenHwModes &CGH) { x.SDTCisSameSizeAs_Info.OtherOperandNum = R->getValueAsInt("OtherOperandNum"); } else { - PrintFatalError("Unrecognized SDTypeConstraint '" + R->getName() + "'!\n"); + PrintFatalError(R->getLoc(), + "Unrecognized SDTypeConstraint '" + R->getName() + "'!\n"); } } @@ -2120,7 +2159,8 @@ static TypeSetByHwMode getImplicitType(Record *R, unsigned ResNo, } if (R->getName() == "node" || R->getName() == "srcvalue" || - R->getName() == "zero_reg") { + R->getName() == "zero_reg" || R->getName() == "immAllOnesV" || + R->getName() == "immAllZerosV" || R->getName() == "undef_tied_input") { // Placeholder. return TypeSetByHwMode(); // Unknown. } @@ -2425,18 +2465,32 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { } } + // If one or more operands with a default value appear at the end of the + // formal operand list for an instruction, we allow them to be overridden + // by optional operands provided in the pattern. + // + // But if an operand B without a default appears at any point after an + // operand A with a default, then we don't allow A to be overridden, + // because there would be no way to specify whether the next operand in + // the pattern was intended to override A or skip it. + unsigned NonOverridableOperands = Inst.getNumOperands(); + while (NonOverridableOperands > 0 && + CDP.operandHasDefault(Inst.getOperand(NonOverridableOperands-1))) + --NonOverridableOperands; + unsigned ChildNo = 0; for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) { Record *OperandNode = Inst.getOperand(i); - // If the instruction expects a predicate or optional def operand, we - // codegen this by setting the operand to it's default value if it has a - // non-empty DefaultOps field. - if (OperandNode->isSubClassOf("OperandWithDefaultOps") && - !CDP.getDefaultOperand(OperandNode).DefaultOps.empty()) + // If the operand has a default value, do we use it? We must use the + // default if we've run out of children of the pattern DAG to consume, + // or if the operand is followed by a non-defaulted one. + if (CDP.operandHasDefault(OperandNode) && + (i < NonOverridableOperands || ChildNo >= getNumChildren())) continue; - // Verify that we didn't run out of provided operands. + // If we have run out of child nodes and there _isn't_ a default + // value we can use for the next operand, give an error. if (ChildNo >= getNumChildren()) { emitTooFewOperandsError(TP, getOperator()->getName(), getNumChildren()); return false; @@ -2753,7 +2807,7 @@ TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit, // chain. if (Int.IS.RetVTs.empty()) Operator = getDAGPatterns().get_intrinsic_void_sdnode(); - else if (Int.ModRef != CodeGenIntrinsic::NoMem) + else if (Int.ModRef != CodeGenIntrinsic::NoMem || Int.hasSideEffects) // Has side-effects, requires chain. Operator = getDAGPatterns().get_intrinsic_w_chain_sdnode(); else // Otherwise, no chain. |