diff options
Diffstat (limited to 'utils')
| -rw-r--r-- | utils/TableGen/CodeGenDAGPatterns.cpp | 3 | ||||
| -rw-r--r-- | utils/TableGen/CodeGenIntrinsics.h | 7 | ||||
| -rw-r--r-- | utils/TableGen/CodeGenTarget.cpp | 6 | ||||
| -rw-r--r-- | utils/TableGen/GlobalISelEmitter.cpp | 91 | ||||
| -rw-r--r-- | utils/TableGen/IntrinsicEmitter.cpp | 14 | ||||
| -rw-r--r-- | utils/TableGen/SubtargetFeatureInfo.cpp | 22 | ||||
| -rw-r--r-- | utils/TableGen/SubtargetFeatureInfo.h | 36 | ||||
| -rw-r--r-- | utils/TableGen/X86RecognizableInstr.cpp | 4 |
8 files changed, 128 insertions, 55 deletions
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 972eb9cd3403..ef2cb4208eae 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -2828,7 +2828,8 @@ public: if (IntInfo->ModRef & CodeGenIntrinsic::MR_Mod) mayStore = true;// Intrinsics that can write to memory are 'mayStore'. - if (IntInfo->ModRef >= CodeGenIntrinsic::ReadWriteMem) + if (IntInfo->ModRef >= CodeGenIntrinsic::ReadWriteMem || + IntInfo->hasSideEffects) // ReadWriteMem intrinsics can have other strange effects. hasSideEffects = true; } diff --git a/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h index 6df0e6a62caf..24374127f536 100644 --- a/utils/TableGen/CodeGenIntrinsics.h +++ b/utils/TableGen/CodeGenIntrinsics.h @@ -123,6 +123,13 @@ struct CodeGenIntrinsic { /// True if the intrinsic is marked as convergent. bool isConvergent; + /// True if the intrinsic has side effects that aren't captured by any + /// of the other flags. + bool hasSideEffects; + + // True if the intrinsic is marked as speculatable. + bool isSpeculatable; + enum ArgAttribute { NoCapture, Returned, ReadOnly, WriteOnly, ReadNone }; std::vector<std::pair<unsigned, ArgAttribute>> ArgumentAttributes; diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index 03c58ac09c2d..d1014a5668a5 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -515,6 +515,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { isNoReturn = false; isNoDuplicate = false; isConvergent = false; + isSpeculatable = false; + hasSideEffects = false; if (DefName.size() <= 4 || std::string(DefName.begin(), DefName.begin() + 4) != "int_") @@ -653,6 +655,10 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { isConvergent = true; else if (Property->getName() == "IntrNoReturn") isNoReturn = true; + else if (Property->getName() == "IntrSpeculatable") + isSpeculatable = true; + else if (Property->getName() == "IntrHasSideEffects") + hasSideEffects = true; else if (Property->isSubClassOf("NoCapture")) { unsigned ArgNo = Property->getValueAsInt("ArgNo"); ArgumentAttributes.push_back(std::make_pair(ArgNo, NoCapture)); diff --git a/utils/TableGen/GlobalISelEmitter.cpp b/utils/TableGen/GlobalISelEmitter.cpp index dcf10ab511da..65a1ea2f0f21 100644 --- a/utils/TableGen/GlobalISelEmitter.cpp +++ b/utils/TableGen/GlobalISelEmitter.cpp @@ -199,21 +199,19 @@ public: void emitCxxCapturedInsnList(raw_ostream &OS); void emitCxxCaptureStmts(raw_ostream &OS, StringRef Expr); - void emit(raw_ostream &OS, - std::map<Record *, SubtargetFeatureInfo, LessRecordByID> - SubtargetFeatures); +void emit(raw_ostream &OS, SubtargetFeatureInfoMap SubtargetFeatures); - /// Compare the priority of this object and B. - /// - /// Returns true if this object is more important than B. - bool isHigherPriorityThan(const RuleMatcher &B) const; +/// Compare the priority of this object and B. +/// +/// Returns true if this object is more important than B. +bool isHigherPriorityThan(const RuleMatcher &B) const; - /// Report the maximum number of temporary operands needed by the rule - /// matcher. - unsigned countRendererFns() const; +/// Report the maximum number of temporary operands needed by the rule +/// matcher. +unsigned countRendererFns() const; - // FIXME: Remove this as soon as possible - InstructionMatcher &insnmatcher_front() const { return *Matchers.front(); } +// FIXME: Remove this as soon as possible +InstructionMatcher &insnmatcher_front() const { return *Matchers.front(); } }; template <class PredicateTy> class PredicateListMatcher { @@ -856,7 +854,9 @@ public: } void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override { - OS << " MIB.addReg(" << RegisterDef->getValueAsString("Namespace") + OS << " MIB.addReg(" << (RegisterDef->getValue("Namespace") + ? RegisterDef->getValueAsString("Namespace") + : "") << "::" << RegisterDef->getName() << ");\n"; } }; @@ -951,6 +951,9 @@ private: /// True if the instruction can be built solely by mutating the opcode. bool canMutate() const { + if (OperandRenderers.size() != Matched.getNumOperands()) + return false; + for (const auto &Renderer : enumerate(OperandRenderers)) { if (const auto *Copy = dyn_cast<CopyRenderer>(&*Renderer.value())) { const OperandMatcher &OM = Matched.getOperand(Copy->getSymbolicName()); @@ -986,12 +989,16 @@ public: << ");\n"; for (auto Def : I->ImplicitDefs) { - auto Namespace = Def->getValueAsString("Namespace"); + auto Namespace = Def->getValue("Namespace") + ? Def->getValueAsString("Namespace") + : ""; OS << " MIB.addDef(" << Namespace << "::" << Def->getName() << ", RegState::Implicit);\n"; } for (auto Use : I->ImplicitUses) { - auto Namespace = Use->getValueAsString("Namespace"); + auto Namespace = Use->getValue("Namespace") + ? Use->getValueAsString("Namespace") + : ""; OS << " MIB.addUse(" << Namespace << "::" << Use->getName() << ", RegState::Implicit);\n"; } @@ -1072,8 +1079,7 @@ void RuleMatcher::emitCxxCaptureStmts(raw_ostream &OS, StringRef Expr) { } void RuleMatcher::emit(raw_ostream &OS, - std::map<Record *, SubtargetFeatureInfo, LessRecordByID> - SubtargetFeatures) { + SubtargetFeatureInfoMap SubtargetFeatures) { if (Matchers.empty()) llvm_unreachable("Unexpected empty matcher!"); @@ -1218,7 +1224,7 @@ private: DenseMap<const Record *, const Record *> ComplexPatternEquivs; // Map of predicates to their subtarget features. - std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures; + SubtargetFeatureInfoMap SubtargetFeatures; void gatherNodeEquivs(); const CodeGenInstruction *findNodeEquiv(Record *N) const; @@ -1712,15 +1718,36 @@ void GlobalISelEmitter::run(raw_ostream &OS) { OS << "#ifdef GET_GLOBALISEL_IMPL\n"; SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures, OS); - SubtargetFeatureInfo::emitNameTable(SubtargetFeatures, OS); + + // Separate subtarget features by how often they must be recomputed. + SubtargetFeatureInfoMap ModuleFeatures; + std::copy_if(SubtargetFeatures.begin(), SubtargetFeatures.end(), + std::inserter(ModuleFeatures, ModuleFeatures.end()), + [](const SubtargetFeatureInfoMap::value_type &X) { + return !X.second.mustRecomputePerFunction(); + }); + SubtargetFeatureInfoMap FunctionFeatures; + std::copy_if(SubtargetFeatures.begin(), SubtargetFeatures.end(), + std::inserter(FunctionFeatures, FunctionFeatures.end()), + [](const SubtargetFeatureInfoMap::value_type &X) { + return X.second.mustRecomputePerFunction(); + }); + SubtargetFeatureInfo::emitComputeAvailableFeatures( - Target.getName(), "InstructionSelector", "computeAvailableFeatures", - SubtargetFeatures, OS); + Target.getName(), "InstructionSelector", "computeAvailableModuleFeatures", + ModuleFeatures, OS); + SubtargetFeatureInfo::emitComputeAvailableFeatures( + Target.getName(), "InstructionSelector", + "computeAvailableFunctionFeatures", FunctionFeatures, OS, + "const MachineFunction *MF"); OS << "bool " << Target.getName() << "InstructionSelector::selectImpl(MachineInstr &I) const {\n" << " MachineFunction &MF = *I.getParent()->getParent();\n" - << " const MachineRegisterInfo &MRI = MF.getRegInfo();\n"; + << " const MachineRegisterInfo &MRI = MF.getRegInfo();\n" + << " // FIXME: This should be computed on a per-function basis rather than per-insn.\n" + << " AvailableFunctionFeatures = computeAvailableFunctionFeatures(&STI, &MF);\n" + << " const PredicateBitset AvailableFeatures = getAvailableFeatures();\n"; for (auto &Rule : Rules) { Rule.emit(OS, SubtargetFeatures); @@ -1730,6 +1757,26 @@ void GlobalISelEmitter::run(raw_ostream &OS) { OS << " return false;\n" << "}\n" << "#endif // ifdef GET_GLOBALISEL_IMPL\n"; + + OS << "#ifdef GET_GLOBALISEL_PREDICATES_DECL\n" + << "PredicateBitset AvailableModuleFeatures;\n" + << "mutable PredicateBitset AvailableFunctionFeatures;\n" + << "PredicateBitset getAvailableFeatures() const {\n" + << " return AvailableModuleFeatures | AvailableFunctionFeatures;\n" + << "}\n" + << "PredicateBitset\n" + << "computeAvailableModuleFeatures(const " << Target.getName() + << "Subtarget *Subtarget) const;\n" + << "PredicateBitset\n" + << "computeAvailableFunctionFeatures(const " << Target.getName() + << "Subtarget *Subtarget,\n" + << " const MachineFunction *MF) const;\n" + << "#endif // ifdef GET_GLOBALISEL_PREDICATES_DECL\n"; + + OS << "#ifdef GET_GLOBALISEL_PREDICATES_INIT\n" + << "AvailableModuleFeatures(computeAvailableModuleFeatures(&STI)),\n" + << "AvailableFunctionFeatures()\n" + << "#endif // ifdef GET_GLOBALISEL_PREDICATES_INIT\n"; } void GlobalISelEmitter::declareSubtargetFeature(Record *Predicate) { diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index e979b94e46d6..1fc18a5dd1d8 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -476,6 +476,12 @@ struct AttributeComparator { if (L->isConvergent != R->isConvergent) return R->isConvergent; + if (L->isSpeculatable != R->isSpeculatable) + return R->isSpeculatable; + + if (L->hasSideEffects != R->hasSideEffects) + return R->hasSideEffects; + // Try to order by readonly/readnone attribute. CodeGenIntrinsic::ModRefBehavior LK = L->ModRef; CodeGenIntrinsic::ModRefBehavior RK = R->ModRef; @@ -600,7 +606,7 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints, if (!intrinsic.canThrow || intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem || intrinsic.isNoReturn || intrinsic.isNoDuplicate || - intrinsic.isConvergent) { + intrinsic.isConvergent || intrinsic.isSpeculatable) { OS << " const Attribute::AttrKind Atts[] = {"; bool addComma = false; if (!intrinsic.canThrow) { @@ -625,6 +631,12 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints, OS << "Attribute::Convergent"; addComma = true; } + if (intrinsic.isSpeculatable) { + if (addComma) + OS << ","; + OS << "Attribute::Speculatable"; + addComma = true; + } switch (intrinsic.ModRef) { case CodeGenIntrinsic::NoMem: diff --git a/utils/TableGen/SubtargetFeatureInfo.cpp b/utils/TableGen/SubtargetFeatureInfo.cpp index 96418dc77d55..5153c35b1261 100644 --- a/utils/TableGen/SubtargetFeatureInfo.cpp +++ b/utils/TableGen/SubtargetFeatureInfo.cpp @@ -45,8 +45,7 @@ SubtargetFeatureInfo::getAll(const RecordKeeper &Records) { } void SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration( - std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures, - raw_ostream &OS) { + SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) { OS << "// Flags for subtarget features that participate in " << "instruction matching.\n"; OS << "enum SubtargetFeatureFlag : " @@ -60,8 +59,7 @@ void SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration( } void SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration( - std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures, - raw_ostream &OS) { + SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) { OS << "// Bits for subtarget features that participate in " << "instruction matching.\n"; OS << "enum SubtargetFeatureBits : " @@ -74,8 +72,7 @@ void SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration( } void SubtargetFeatureInfo::emitNameTable( - std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures, - raw_ostream &OS) { + SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) { // Need to sort the name table so that lookup by the log of the enum value // gives the proper name. More specifically, for a feature of value 1<<n, // SubtargetFeatureNames[n] should be the name of the feature. @@ -102,11 +99,13 @@ void SubtargetFeatureInfo::emitNameTable( void SubtargetFeatureInfo::emitComputeAvailableFeatures( StringRef TargetName, StringRef ClassName, StringRef FuncName, - std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures, - raw_ostream &OS) { + SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS, + StringRef ExtraParams) { OS << "PredicateBitset " << TargetName << ClassName << "::\n" - << FuncName << "(const MachineFunction *MF, const " << TargetName - << "Subtarget *Subtarget) const {\n"; + << FuncName << "(const " << TargetName << "Subtarget *Subtarget"; + if (!ExtraParams.empty()) + OS << ", " << ExtraParams; + OS << ") const {\n"; OS << " PredicateBitset Features;\n"; for (const auto &SF : SubtargetFeatures) { const SubtargetFeatureInfo &SFI = SF.second; @@ -120,8 +119,7 @@ void SubtargetFeatureInfo::emitComputeAvailableFeatures( void SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures( StringRef TargetName, StringRef ClassName, StringRef FuncName, - std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures, - raw_ostream &OS) { + SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) { OS << "uint64_t " << TargetName << ClassName << "::\n" << FuncName << "(const FeatureBitset& FB) const {\n"; OS << " uint64_t Features = 0;\n"; diff --git a/utils/TableGen/SubtargetFeatureInfo.h b/utils/TableGen/SubtargetFeatureInfo.h index bbaf45259606..c55c16a4031e 100644 --- a/utils/TableGen/SubtargetFeatureInfo.h +++ b/utils/TableGen/SubtargetFeatureInfo.h @@ -21,6 +21,9 @@ namespace llvm { class Record; class RecordKeeper; +struct SubtargetFeatureInfo; +using SubtargetFeatureInfoMap = std::map<Record *, SubtargetFeatureInfo, LessRecordByID>; + /// Helper class for storing information on a subtarget feature which /// participates in instruction matching. struct SubtargetFeatureInfo { @@ -43,6 +46,10 @@ struct SubtargetFeatureInfo { return "Feature_" + TheDef->getName().str() + "Bit"; } + bool mustRecomputePerFunction() const { + return TheDef->getValueAsBit("RecomputePerFunction"); + } + void dump() const; static std::vector<std::pair<Record *, SubtargetFeatureInfo>> getAll(const RecordKeeper &Records); @@ -52,21 +59,17 @@ struct SubtargetFeatureInfo { /// This version emits the bit value for the feature and is therefore limited /// to 64 feature bits. static void emitSubtargetFeatureFlagEnumeration( - std::map<Record *, SubtargetFeatureInfo, LessRecordByID> - &SubtargetFeatures, - raw_ostream &OS); + SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS); /// Emit the subtarget feature flag definitions. /// /// This version emits the bit index for the feature and can therefore support /// more than 64 feature bits. - static void emitSubtargetFeatureBitEnumeration( - std::map<Record *, SubtargetFeatureInfo, LessRecordByID> - &SubtargetFeatures, - raw_ostream &OS); + static void + emitSubtargetFeatureBitEnumeration(SubtargetFeatureInfoMap &SubtargetFeatures, + raw_ostream &OS); - static void emitNameTable(std::map<Record *, SubtargetFeatureInfo, - LessRecordByID> &SubtargetFeatures, + static void emitNameTable(SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS); /// Emit the function to compute the list of available features given a @@ -82,11 +85,12 @@ struct SubtargetFeatureInfo { /// \param FuncName The name of the function to emit. /// \param SubtargetFeatures A map of TableGen records to the /// SubtargetFeatureInfo equivalent. - static void emitComputeAvailableFeatures( - StringRef TargetName, StringRef ClassName, StringRef FuncName, - std::map<Record *, SubtargetFeatureInfo, LessRecordByID> - &SubtargetFeatures, - raw_ostream &OS); + /// \param ExtraParams Additional arguments to the generated function. + static void + emitComputeAvailableFeatures(StringRef TargetName, StringRef ClassName, + StringRef FuncName, + SubtargetFeatureInfoMap &SubtargetFeatures, + raw_ostream &OS, StringRef ExtraParams = ""); /// Emit the function to compute the list of available features given a /// subtarget. @@ -103,9 +107,7 @@ struct SubtargetFeatureInfo { /// SubtargetFeatureInfo equivalent. static void emitComputeAssemblerAvailableFeatures( StringRef TargetName, StringRef ClassName, StringRef FuncName, - std::map<Record *, SubtargetFeatureInfo, LessRecordByID> - &SubtargetFeatures, - raw_ostream &OS); + SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS); }; } // end namespace llvm diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index e703bbfc4496..4298bc5763b6 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -668,7 +668,7 @@ void RecognizableInstr::emitInstructionSpecifier() { break; case X86Local::MRMSrcReg4VOp3: assert(numPhysicalOperands == 3 && - "Unexpected number of operands for MRMSrcRegFrm"); + "Unexpected number of operands for MRMSrcReg4VOp3Frm"); HANDLE_OPERAND(roRegister) HANDLE_OPERAND(rmRegister) HANDLE_OPERAND(vvvvRegister) @@ -708,7 +708,7 @@ void RecognizableInstr::emitInstructionSpecifier() { break; case X86Local::MRMSrcMem4VOp3: assert(numPhysicalOperands == 3 && - "Unexpected number of operands for MRMSrcMemFrm"); + "Unexpected number of operands for MRMSrcMem4VOp3Frm"); HANDLE_OPERAND(roRegister) HANDLE_OPERAND(memory) HANDLE_OPERAND(vvvvRegister) |
