diff options
Diffstat (limited to 'utils')
22 files changed, 657 insertions, 366 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index abcec8f..78eb641 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -416,7 +416,7 @@ struct MatchableInfo { SmallVector<SubtargetFeatureInfo*, 4> RequiredFeatures; /// ConversionFnKind - The enum value which is passed to the generated - /// ConvertToMCInst to convert parsed operands into an MCInst for this + /// convertToMCInst to convert parsed operands into an MCInst for this /// function. std::string ConversionFnKind; @@ -488,6 +488,15 @@ struct MatchableInfo { return false; } + // Give matches that require more features higher precedence. This is useful + // because we cannot define AssemblerPredicates with the negation of + // processor features. For example, ARM v6 "nop" may be either a HINT or + // MOV. With v6, we want to match HINT. The assembler has no way to + // predicate MOV under "NoV6", but HINT will always match first because it + // requires V6 while MOV does not. + if (RequiredFeatures.size() != RHS.RequiredFeatures.size()) + return RequiredFeatures.size() > RHS.RequiredFeatures.size(); + return false; } @@ -666,7 +675,7 @@ void MatchableInfo::dump() { } static std::pair<StringRef, StringRef> -parseTwoOperandConstraint(StringRef S, SMLoc Loc) { +parseTwoOperandConstraint(StringRef S, ArrayRef<SMLoc> Loc) { // Split via the '='. std::pair<StringRef, StringRef> Ops = S.split('='); if (Ops.second == "") @@ -1638,34 +1647,90 @@ void MatchableInfo::buildAliasResultOperands() { } } +static unsigned getConverterOperandID(const std::string &Name, + SetVector<std::string> &Table, + bool &IsNew) { + IsNew = Table.insert(Name); + + unsigned ID = IsNew ? Table.size() - 1 : + std::find(Table.begin(), Table.end(), Name) - Table.begin(); + + assert(ID < Table.size()); + + return ID; +} + + static void emitConvertToMCInst(CodeGenTarget &Target, StringRef ClassName, std::vector<MatchableInfo*> &Infos, raw_ostream &OS) { + SetVector<std::string> OperandConversionKinds; + SetVector<std::string> InstructionConversionKinds; + std::vector<std::vector<uint8_t> > ConversionTable; + size_t MaxRowLength = 2; // minimum is custom converter plus terminator. + + // TargetOperandClass - This is the target's operand class, like X86Operand. + std::string TargetOperandClass = Target.getName() + "Operand"; + // Write the convert function to a separate stream, so we can drop it after - // the enum. + // the enum. We'll build up the conversion handlers for the individual + // operand types opportunistically as we encounter them. std::string ConvertFnBody; raw_string_ostream CvtOS(ConvertFnBody); - - // Function we have already generated. - std::set<std::string> GeneratedFns; - // Start the unified conversion function. - CvtOS << "bool " << Target.getName() << ClassName << "::\n"; - CvtOS << "ConvertToMCInst(unsigned Kind, MCInst &Inst, " + CvtOS << "void " << Target.getName() << ClassName << "::\n" + << "convertToMCInst(unsigned Kind, MCInst &Inst, " << "unsigned Opcode,\n" - << " const SmallVectorImpl<MCParsedAsmOperand*" - << "> &Operands) {\n"; - CvtOS << " Inst.setOpcode(Opcode);\n"; - CvtOS << " switch (Kind) {\n"; - CvtOS << " default:\n"; - - // Start the enum, which we will generate inline. - - OS << "// Unified function for converting operands to MCInst instances.\n\n"; - OS << "enum ConversionKind {\n"; - - // TargetOperandClass - This is the target's operand class, like X86Operand. - std::string TargetOperandClass = Target.getName() + "Operand"; + << " const SmallVectorImpl<MCParsedAsmOperand*" + << "> &Operands) {\n" + << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n" + << " uint8_t *Converter = ConversionTable[Kind];\n" + << " Inst.setOpcode(Opcode);\n" + << " for (uint8_t *p = Converter; *p; p+= 2) {\n" + << " switch (*p) {\n" + << " default: llvm_unreachable(\"invalid conversion entry!\");\n" + << " case CVT_Reg:\n" + << " static_cast<" << TargetOperandClass + << "*>(Operands[*(p + 1)])->addRegOperands(Inst, 1);\n" + << " break;\n" + << " case CVT_Tied:\n" + << " Inst.addOperand(Inst.getOperand(*(p + 1)));\n" + << " break;\n"; + + std::string OperandFnBody; + raw_string_ostream OpOS(OperandFnBody); + // Start the operand number lookup function. + OpOS << "unsigned " << Target.getName() << ClassName << "::\n" + << "getMCInstOperandNumImpl(unsigned Kind, MCInst &Inst,\n" + << " const SmallVectorImpl<MCParsedAsmOperand*> " + << "&Operands,\n unsigned OperandNum, unsigned " + << "&NumMCOperands) {\n" + << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n" + << " NumMCOperands = 0;\n" + << " unsigned MCOperandNum = 0;\n" + << " uint8_t *Converter = ConversionTable[Kind];\n" + << " for (uint8_t *p = Converter; *p; p+= 2) {\n" + << " if (*(p + 1) > OperandNum) continue;\n" + << " switch (*p) {\n" + << " default: llvm_unreachable(\"invalid conversion entry!\");\n" + << " case CVT_Reg:\n" + << " if (*(p + 1) == OperandNum) {\n" + << " NumMCOperands = 1;\n" + << " break;\n" + << " }\n" + << " ++MCOperandNum;\n" + << " break;\n" + << " case CVT_Tied:\n" + << " // FIXME: Tied operand calculation not supported.\n" + << " assert (0 && \"getMCInstOperandNumImpl() doesn't support tied operands, yet!\");\n" + << " break;\n"; + + // Pre-populate the operand conversion kinds with the standard always + // available entries. + OperandConversionKinds.insert("CVT_Done"); + OperandConversionKinds.insert("CVT_Reg"); + OperandConversionKinds.insert("CVT_Tied"); + enum { CVT_Done, CVT_Reg, CVT_Tied }; for (std::vector<MatchableInfo*>::const_iterator it = Infos.begin(), ie = Infos.end(); it != ie; ++it) { @@ -1679,24 +1744,35 @@ static void emitConvertToMCInst(CodeGenTarget &Target, StringRef ClassName, II.ConversionFnKind = Signature; // Check if we have already generated this signature. - if (!GeneratedFns.insert(Signature).second) + if (!InstructionConversionKinds.insert(Signature)) continue; - // If not, emit it now. Add to the enum list. - OS << " " << Signature << ",\n"; + // Remember this converter for the kind enum. + unsigned KindID = OperandConversionKinds.size(); + OperandConversionKinds.insert("CVT_" + AsmMatchConverter); - CvtOS << " case " << Signature << ":\n"; - CvtOS << " return " << AsmMatchConverter - << "(Inst, Opcode, Operands);\n"; + // Add the converter row for this instruction. + ConversionTable.push_back(std::vector<uint8_t>()); + ConversionTable.back().push_back(KindID); + ConversionTable.back().push_back(CVT_Done); + + // Add the handler to the conversion driver function. + CvtOS << " case CVT_" << AsmMatchConverter << ":\n" + << " " << AsmMatchConverter << "(Inst, Operands);\n" + << " break;\n"; + + // FIXME: Handle the operand number lookup for custom match functions. continue; } // Build the conversion function signature. std::string Signature = "Convert"; - std::string CaseBody; - raw_string_ostream CaseOS(CaseBody); + + std::vector<uint8_t> ConversionRow; // Compute the convert enum and the case body. + MaxRowLength = std::max(MaxRowLength, II.ResOperands.size()*2 + 1 ); + for (unsigned i = 0, e = II.ResOperands.size(); i != e; ++i) { const MatchableInfo::ResOperand &OpInfo = II.ResOperands[i]; @@ -1709,74 +1785,186 @@ static void emitConvertToMCInst(CodeGenTarget &Target, StringRef ClassName, // Registers are always converted the same, don't duplicate the // conversion function based on them. Signature += "__"; - if (Op.Class->isRegisterClass()) - Signature += "Reg"; - else - Signature += Op.Class->ClassName; + std::string Class; + Class = Op.Class->isRegisterClass() ? "Reg" : Op.Class->ClassName; + Signature += Class; Signature += utostr(OpInfo.MINumOperands); Signature += "_" + itostr(OpInfo.AsmOperandNum); - CaseOS << " ((" << TargetOperandClass << "*)Operands[" - << (OpInfo.AsmOperandNum+1) << "])->" << Op.Class->RenderMethod - << "(Inst, " << OpInfo.MINumOperands << ");\n"; + // Add the conversion kind, if necessary, and get the associated ID + // the index of its entry in the vector). + std::string Name = "CVT_" + (Op.Class->isRegisterClass() ? "Reg" : + Op.Class->RenderMethod); + + bool IsNewConverter = false; + unsigned ID = getConverterOperandID(Name, OperandConversionKinds, + IsNewConverter); + + // Add the operand entry to the instruction kind conversion row. + ConversionRow.push_back(ID); + ConversionRow.push_back(OpInfo.AsmOperandNum + 1); + + if (!IsNewConverter) + break; + + // This is a new operand kind. Add a handler for it to the + // converter driver. + CvtOS << " case " << Name << ":\n" + << " static_cast<" << TargetOperandClass + << "*>(Operands[*(p + 1)])->" + << Op.Class->RenderMethod << "(Inst, " << OpInfo.MINumOperands + << ");\n" + << " break;\n"; + + // Add a handler for the operand number lookup. + OpOS << " case " << Name << ":\n" + << " if (*(p + 1) == OperandNum) {\n" + << " NumMCOperands = " << OpInfo.MINumOperands << ";\n" + << " break;\n" + << " }\n" + << " MCOperandNum += " << OpInfo.MINumOperands << ";\n" + << " break;\n"; break; } - case MatchableInfo::ResOperand::TiedOperand: { // If this operand is tied to a previous one, just copy the MCInst // operand from the earlier one.We can only tie single MCOperand values. //assert(OpInfo.MINumOperands == 1 && "Not a singular MCOperand"); unsigned TiedOp = OpInfo.TiedOperandNum; assert(i > TiedOp && "Tied operand precedes its target!"); - CaseOS << " Inst.addOperand(Inst.getOperand(" << TiedOp << "));\n"; Signature += "__Tie" + utostr(TiedOp); + ConversionRow.push_back(CVT_Tied); + ConversionRow.push_back(TiedOp); + // FIXME: Handle the operand number lookup for tied operands. break; } case MatchableInfo::ResOperand::ImmOperand: { int64_t Val = OpInfo.ImmVal; - CaseOS << " Inst.addOperand(MCOperand::CreateImm(" << Val << "));\n"; - Signature += "__imm" + itostr(Val); + std::string Ty = "imm_" + itostr(Val); + Signature += "__" + Ty; + + std::string Name = "CVT_" + Ty; + bool IsNewConverter = false; + unsigned ID = getConverterOperandID(Name, OperandConversionKinds, + IsNewConverter); + // Add the operand entry to the instruction kind conversion row. + ConversionRow.push_back(ID); + ConversionRow.push_back(0); + + if (!IsNewConverter) + break; + + CvtOS << " case " << Name << ":\n" + << " Inst.addOperand(MCOperand::CreateImm(" << Val << "));\n" + << " break;\n"; + + OpOS << " case " << Name << ":\n" + << " if (*(p + 1) == OperandNum) {\n" + << " NumMCOperands = 1;\n" + << " break;\n" + << " }\n" + << " ++MCOperandNum;\n" + << " break;\n"; break; } case MatchableInfo::ResOperand::RegOperand: { + std::string Reg, Name; if (OpInfo.Register == 0) { - CaseOS << " Inst.addOperand(MCOperand::CreateReg(0));\n"; - Signature += "__reg0"; + Name = "reg0"; + Reg = "0"; } else { - std::string N = getQualifiedName(OpInfo.Register); - CaseOS << " Inst.addOperand(MCOperand::CreateReg(" << N << "));\n"; - Signature += "__reg" + OpInfo.Register->getName(); + Reg = getQualifiedName(OpInfo.Register); + Name = "reg" + OpInfo.Register->getName(); } + Signature += "__" + Name; + Name = "CVT_" + Name; + bool IsNewConverter = false; + unsigned ID = getConverterOperandID(Name, OperandConversionKinds, + IsNewConverter); + // Add the operand entry to the instruction kind conversion row. + ConversionRow.push_back(ID); + ConversionRow.push_back(0); + + if (!IsNewConverter) + break; + CvtOS << " case " << Name << ":\n" + << " Inst.addOperand(MCOperand::CreateReg(" << Reg << "));\n" + << " break;\n"; + + OpOS << " case " << Name << ":\n" + << " if (*(p + 1) == OperandNum) {\n" + << " NumMCOperands = 1;\n" + << " break;\n" + << " }\n" + << " ++MCOperandNum;\n" + << " break;\n"; } } } + // If there were no operands, add to the signature to that effect + if (Signature == "Convert") + Signature += "_NoOperands"; + II.ConversionFnKind = Signature; - // Check if we have already generated this signature. - if (!GeneratedFns.insert(Signature).second) + // Save the signature. If we already have it, don't add a new row + // to the table. + if (!InstructionConversionKinds.insert(Signature)) continue; - // If not, emit it now. Add to the enum list. - OS << " " << Signature << ",\n"; - - CvtOS << " case " << Signature << ":\n"; - CvtOS << CaseOS.str(); - CvtOS << " return true;\n"; + // Add the row to the table. + ConversionTable.push_back(ConversionRow); } - // Finish the convert function. + // Finish up the converter driver function. + CvtOS << " }\n }\n}\n\n"; + + // Finish up the operand number lookup function. + OpOS << " }\n }\n return MCOperandNum;\n}\n\n"; + + OS << "namespace {\n"; + + // Output the operand conversion kind enum. + OS << "enum OperatorConversionKind {\n"; + for (unsigned i = 0, e = OperandConversionKinds.size(); i != e; ++i) + OS << " " << OperandConversionKinds[i] << ",\n"; + OS << " CVT_NUM_CONVERTERS\n"; + OS << "};\n\n"; + + // Output the instruction conversion kind enum. + OS << "enum InstructionConversionKind {\n"; + for (SetVector<std::string>::const_iterator + i = InstructionConversionKinds.begin(), + e = InstructionConversionKinds.end(); i != e; ++i) + OS << " " << *i << ",\n"; + OS << " CVT_NUM_SIGNATURES\n"; + OS << "};\n\n"; + - CvtOS << " }\n"; - CvtOS << " return false;\n"; - CvtOS << "}\n\n"; + OS << "} // end anonymous namespace\n\n"; - // Finish the enum, and drop the convert function after it. + // Output the conversion table. + OS << "static uint8_t ConversionTable[CVT_NUM_SIGNATURES][" + << MaxRowLength << "] = {\n"; + + for (unsigned Row = 0, ERow = ConversionTable.size(); Row != ERow; ++Row) { + assert(ConversionTable[Row].size() % 2 == 0 && "bad conversion row!"); + OS << " // " << InstructionConversionKinds[Row] << "\n"; + OS << " { "; + for (unsigned i = 0, e = ConversionTable[Row].size(); i != e; i += 2) + OS << OperandConversionKinds[ConversionTable[Row][i]] << ", " + << (unsigned)(ConversionTable[Row][i + 1]) << ", "; + OS << "CVT_Done },\n"; + } - OS << " NumConversionVariants\n"; OS << "};\n\n"; + // Spit out the conversion driver function. OS << CvtOS.str(); + + // Spit out the operand number lookup function. + OS << OpOS.str(); } /// emitMatchClassEnumeration - Emit the enumeration for match class kinds. @@ -2407,14 +2595,19 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " // This should be included into the middle of the declaration of\n"; OS << " // your subclasses implementation of MCTargetAsmParser.\n"; OS << " unsigned ComputeAvailableFeatures(uint64_t FeatureBits) const;\n"; - OS << " bool ConvertToMCInst(unsigned Kind, MCInst &Inst, " + OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, " << "unsigned Opcode,\n" - << " const SmallVectorImpl<MCParsedAsmOperand*> " + << " const SmallVectorImpl<MCParsedAsmOperand*> " << "&Operands);\n"; + OS << " unsigned getMCInstOperandNumImpl(unsigned Kind, MCInst &Inst,\n " + << " const " + << "SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n " + << " unsigned OperandNum, unsigned &NumMCOperands);\n"; OS << " bool MnemonicIsValid(StringRef Mnemonic);\n"; - OS << " unsigned MatchInstructionImpl(\n"; - OS << " const SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n"; - OS << " MCInst &Inst, unsigned &ErrorInfo, unsigned VariantID = 0);\n"; + OS << " unsigned MatchInstructionImpl(\n" + << " const SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n" + << " unsigned &Kind, MCInst &Inst, " + << "unsigned &ErrorInfo,\n unsigned VariantID = 0);\n"; if (Info.OperandMatchInfo.size()) { OS << "\n enum OperandMatchResultTy {\n"; @@ -2594,8 +2787,14 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << Target.getName() << ClassName << "::\n" << "MatchInstructionImpl(const SmallVectorImpl<MCParsedAsmOperand*>" << " &Operands,\n"; - OS << " MCInst &Inst, unsigned &ErrorInfo, "; - OS << "unsigned VariantID) {\n"; + OS << " unsigned &Kind, MCInst &Inst, unsigned "; + OS << "&ErrorInfo,\n unsigned VariantID) {\n"; + + OS << " // Eliminate obvious mismatches.\n"; + OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n"; + OS << " ErrorInfo = " << (MaxNumOperands+1) << ";\n"; + OS << " return Match_InvalidOperand;\n"; + OS << " }\n\n"; // Emit code to get the available features. OS << " // Get the current feature set.\n"; @@ -2613,12 +2812,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { } // Emit code to compute the class list for this operand vector. - OS << " // Eliminate obvious mismatches.\n"; - OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n"; - OS << " ErrorInfo = " << (MaxNumOperands+1) << ";\n"; - OS << " return Match_InvalidOperand;\n"; - OS << " }\n\n"; - OS << " // Some state to try to produce better error messages.\n"; OS << " bool HadMatchOtherThanFeatures = false;\n"; OS << " bool HadMatchOtherThanPredicate = false;\n"; @@ -2683,17 +2876,15 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " HadMatchOtherThanFeatures = true;\n"; OS << " unsigned NewMissingFeatures = it->RequiredFeatures & " "~AvailableFeatures;\n"; - OS << " if (CountPopulation_32(NewMissingFeatures) <= " - "CountPopulation_32(MissingFeatures))\n"; + OS << " if (CountPopulation_32(NewMissingFeatures) <=\n" + " CountPopulation_32(MissingFeatures))\n"; OS << " MissingFeatures = NewMissingFeatures;\n"; OS << " continue;\n"; OS << " }\n"; OS << "\n"; OS << " // We have selected a definite instruction, convert the parsed\n" << " // operands into the appropriate MCInst.\n"; - OS << " if (!ConvertToMCInst(it->ConvertFn, Inst,\n" - << " it->Opcode, Operands))\n"; - OS << " return Match_ConversionFail;\n"; + OS << " convertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands);\n"; OS << "\n"; // Verify the instruction with the target-specific match predicate function. @@ -2714,6 +2905,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { if (!InsnCleanupFn.empty()) OS << " " << InsnCleanupFn << "(Inst);\n"; + OS << " Kind = it->ConvertFn;\n"; OS << " return Match_Success;\n"; OS << " }\n\n"; diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index eaa6789..db16bda 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -92,7 +92,7 @@ void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) { int CodeEmitterGen::getVariableBit(const std::string &VarName, BitsInit *BI, int bit) { if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(BI->getBit(bit))) { - if (VarInit *VI = dynamic_cast<VarInit*>(VBI->getVariable())) + if (VarInit *VI = dynamic_cast<VarInit*>(VBI->getBitVar())) if (VI->getName() == VarName) return VBI->getBitNum(); } else if (VarInit *VI = dynamic_cast<VarInit*>(BI->getBit(bit))) { diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 34f8a34..8713a56 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -1410,19 +1410,13 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { // Make sure that the value is representable for this type. if (Size >= 32) return MadeChange; - int Val = (II->getValue() << (32-Size)) >> (32-Size); - if (Val == II->getValue()) return MadeChange; - - // If sign-extended doesn't fit, does it fit as unsigned? - unsigned ValueMask; - unsigned UnsignedVal; - ValueMask = unsigned(~uint32_t(0UL) >> (32-Size)); - UnsignedVal = unsigned(II->getValue()); - - if ((ValueMask & UnsignedVal) == UnsignedVal) + // Check that the value doesn't use more bits than we have. It must either + // be a sign- or zero-extended equivalent of the original. + int64_t SignBitAndAbove = II->getValue() >> (Size - 1); + if (SignBitAndAbove == -1 || SignBitAndAbove == 0 || SignBitAndAbove == 1) return MadeChange; - TP.error("Integer value '" + itostr(II->getValue())+ + TP.error("Integer value '" + itostr(II->getValue()) + "' is out of range for type '" + getEnumName(getType(0)) + "'!"); return MadeChange; } @@ -1581,8 +1575,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { // 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("PredicateOperand") || - OperandNode->isSubClassOf("OptionalDefOperand")) && + if (OperandNode->isSubClassOf("OperandWithDefaultOps") && !CDP.getDefaultOperand(OperandNode).DefaultOps.empty()) continue; @@ -2033,6 +2026,9 @@ CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : // stores, and side effects in many cases by examining an // instruction's pattern. InferInstructionFlags(); + + // Verify that instruction flags match the patterns. + VerifyInstructionFlags(); } CodeGenDAGPatterns::~CodeGenDAGPatterns() { @@ -2176,53 +2172,46 @@ void CodeGenDAGPatterns::ParsePatternFragments() { } void CodeGenDAGPatterns::ParseDefaultOperands() { - std::vector<Record*> DefaultOps[2]; - DefaultOps[0] = Records.getAllDerivedDefinitions("PredicateOperand"); - DefaultOps[1] = Records.getAllDerivedDefinitions("OptionalDefOperand"); + std::vector<Record*> DefaultOps; + DefaultOps = Records.getAllDerivedDefinitions("OperandWithDefaultOps"); // Find some SDNode. assert(!SDNodes.empty() && "No SDNodes parsed?"); Init *SomeSDNode = DefInit::get(SDNodes.begin()->first); - for (unsigned iter = 0; iter != 2; ++iter) { - for (unsigned i = 0, e = DefaultOps[iter].size(); i != e; ++i) { - DagInit *DefaultInfo = DefaultOps[iter][i]->getValueAsDag("DefaultOps"); - - // Clone the DefaultInfo dag node, changing the operator from 'ops' to - // SomeSDnode so that we can parse this. - std::vector<std::pair<Init*, std::string> > Ops; - for (unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op) - Ops.push_back(std::make_pair(DefaultInfo->getArg(op), - DefaultInfo->getArgName(op))); - DagInit *DI = DagInit::get(SomeSDNode, "", Ops); - - // Create a TreePattern to parse this. - TreePattern P(DefaultOps[iter][i], DI, false, *this); - assert(P.getNumTrees() == 1 && "This ctor can only produce one tree!"); - - // Copy the operands over into a DAGDefaultOperand. - DAGDefaultOperand DefaultOpInfo; - - TreePatternNode *T = P.getTree(0); - for (unsigned op = 0, e = T->getNumChildren(); op != e; ++op) { - TreePatternNode *TPN = T->getChild(op); - while (TPN->ApplyTypeConstraints(P, false)) - /* Resolve all types */; - - if (TPN->ContainsUnresolvedType()) { - if (iter == 0) - throw "Value #" + utostr(i) + " of PredicateOperand '" + - DefaultOps[iter][i]->getName() +"' doesn't have a concrete type!"; - else - throw "Value #" + utostr(i) + " of OptionalDefOperand '" + - DefaultOps[iter][i]->getName() +"' doesn't have a concrete type!"; - } - DefaultOpInfo.DefaultOps.push_back(TPN); + for (unsigned i = 0, e = DefaultOps.size(); i != e; ++i) { + DagInit *DefaultInfo = DefaultOps[i]->getValueAsDag("DefaultOps"); + + // Clone the DefaultInfo dag node, changing the operator from 'ops' to + // SomeSDnode so that we can parse this. + std::vector<std::pair<Init*, std::string> > Ops; + for (unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op) + Ops.push_back(std::make_pair(DefaultInfo->getArg(op), + DefaultInfo->getArgName(op))); + DagInit *DI = DagInit::get(SomeSDNode, "", Ops); + + // Create a TreePattern to parse this. + TreePattern P(DefaultOps[i], DI, false, *this); + assert(P.getNumTrees() == 1 && "This ctor can only produce one tree!"); + + // Copy the operands over into a DAGDefaultOperand. + DAGDefaultOperand DefaultOpInfo; + + TreePatternNode *T = P.getTree(0); + for (unsigned op = 0, e = T->getNumChildren(); op != e; ++op) { + TreePatternNode *TPN = T->getChild(op); + while (TPN->ApplyTypeConstraints(P, false)) + /* Resolve all types */; + + if (TPN->ContainsUnresolvedType()) { + throw "Value #" + utostr(i) + " of OperandWithDefaultOps '" + + DefaultOps[i]->getName() +"' doesn't have a concrete type!"; } - - // Insert it into the DefaultOperands map so we can find it later. - DefaultOperands[DefaultOps[iter][i]] = DefaultOpInfo; + DefaultOpInfo.DefaultOps.push_back(TPN); } + + // Insert it into the DefaultOperands map so we can find it later. + DefaultOperands[DefaultOps[i]] = DefaultOpInfo; } } @@ -2367,36 +2356,29 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, class InstAnalyzer { const CodeGenDAGPatterns &CDP; - bool &mayStore; - bool &mayLoad; - bool &IsBitcast; - bool &HasSideEffects; - bool &IsVariadic; public: - InstAnalyzer(const CodeGenDAGPatterns &cdp, - bool &maystore, bool &mayload, bool &isbc, bool &hse, bool &isv) - : CDP(cdp), mayStore(maystore), mayLoad(mayload), IsBitcast(isbc), - HasSideEffects(hse), IsVariadic(isv) { - } + bool hasSideEffects; + bool mayStore; + bool mayLoad; + bool isBitcast; + bool isVariadic; - /// Analyze - Analyze the specified instruction, returning true if the - /// instruction had a pattern. - bool Analyze(Record *InstRecord) { - const TreePattern *Pattern = CDP.getInstruction(InstRecord).getPattern(); - if (Pattern == 0) { - HasSideEffects = 1; - return false; // No pattern. - } + InstAnalyzer(const CodeGenDAGPatterns &cdp) + : CDP(cdp), hasSideEffects(false), mayStore(false), mayLoad(false), + isBitcast(false), isVariadic(false) {} - // FIXME: Assume only the first tree is the pattern. The others are clobber - // nodes. - AnalyzeNode(Pattern->getTree(0)); - return true; + void Analyze(const TreePattern *Pat) { + // Assume only the first tree is the pattern. The others are clobber nodes. + AnalyzeNode(Pat->getTree(0)); + } + + void Analyze(const PatternToMatch *Pat) { + AnalyzeNode(Pat->getSrcPattern()); } private: bool IsNodeBitcast(const TreePatternNode *N) const { - if (HasSideEffects || mayLoad || mayStore || IsVariadic) + if (hasSideEffects || mayLoad || mayStore || isVariadic) return false; if (N->getNumChildren() != 2) @@ -2418,6 +2400,7 @@ private: return OpInfo.getEnumName() == "ISD::BITCAST"; } +public: void AnalyzeNode(const TreePatternNode *N) { if (N->isLeaf()) { if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) { @@ -2427,7 +2410,7 @@ private: const ComplexPattern &CP = CDP.getComplexPattern(LeafRec); if (CP.hasProperty(SDNPMayStore)) mayStore = true; if (CP.hasProperty(SDNPMayLoad)) mayLoad = true; - if (CP.hasProperty(SDNPSideEffect)) HasSideEffects = true; + if (CP.hasProperty(SDNPSideEffect)) hasSideEffects = true; } } return; @@ -2439,7 +2422,7 @@ private: // Ignore set nodes, which are not SDNodes. if (N->getOperator()->getName() == "set") { - IsBitcast = IsNodeBitcast(N); + isBitcast = IsNodeBitcast(N); return; } @@ -2449,8 +2432,8 @@ private: // Notice properties of the node. if (OpInfo.hasProperty(SDNPMayStore)) mayStore = true; if (OpInfo.hasProperty(SDNPMayLoad)) mayLoad = true; - if (OpInfo.hasProperty(SDNPSideEffect)) HasSideEffects = true; - if (OpInfo.hasProperty(SDNPVariadic)) IsVariadic = true; + if (OpInfo.hasProperty(SDNPSideEffect)) hasSideEffects = true; + if (OpInfo.hasProperty(SDNPVariadic)) isVariadic = true; if (const CodeGenIntrinsic *IntInfo = N->getIntrinsicInfo(CDP)) { // If this is an intrinsic, analyze it. @@ -2462,62 +2445,64 @@ private: if (IntInfo->ModRef >= CodeGenIntrinsic::ReadWriteMem) // WriteMem intrinsics can have other strange effects. - HasSideEffects = true; + hasSideEffects = true; } } }; -static void InferFromPattern(const CodeGenInstruction &Inst, - bool &MayStore, bool &MayLoad, - bool &IsBitcast, - bool &HasSideEffects, bool &IsVariadic, - const CodeGenDAGPatterns &CDP) { - MayStore = MayLoad = IsBitcast = HasSideEffects = IsVariadic = false; - - bool HadPattern = - InstAnalyzer(CDP, MayStore, MayLoad, IsBitcast, HasSideEffects, IsVariadic) - .Analyze(Inst.TheDef); - - // InstAnalyzer only correctly analyzes mayStore/mayLoad so far. - if (Inst.mayStore) { // If the .td file explicitly sets mayStore, use it. - // If we decided that this is a store from the pattern, then the .td file - // entry is redundant. - if (MayStore) - PrintWarning(Inst.TheDef->getLoc(), - "mayStore flag explicitly set on " - "instruction, but flag already inferred from pattern."); - MayStore = true; +static bool InferFromPattern(CodeGenInstruction &InstInfo, + const InstAnalyzer &PatInfo, + Record *PatDef) { + bool Error = false; + + // Remember where InstInfo got its flags. + if (InstInfo.hasUndefFlags()) + InstInfo.InferredFrom = PatDef; + + // Check explicitly set flags for consistency. + if (InstInfo.hasSideEffects != PatInfo.hasSideEffects && + !InstInfo.hasSideEffects_Unset) { + // Allow explicitly setting hasSideEffects = 1 on instructions, even when + // the pattern has no side effects. That could be useful for div/rem + // instructions that may trap. + if (!InstInfo.hasSideEffects) { + Error = true; + PrintError(PatDef->getLoc(), "Pattern doesn't match hasSideEffects = " + + Twine(InstInfo.hasSideEffects)); + } } - if (Inst.mayLoad) { // If the .td file explicitly sets mayLoad, use it. - // If we decided that this is a load from the pattern, then the .td file - // entry is redundant. - if (MayLoad) - PrintWarning(Inst.TheDef->getLoc(), - "mayLoad flag explicitly set on " - "instruction, but flag already inferred from pattern."); - MayLoad = true; + if (InstInfo.mayStore != PatInfo.mayStore && !InstInfo.mayStore_Unset) { + Error = true; + PrintError(PatDef->getLoc(), "Pattern doesn't match mayStore = " + + Twine(InstInfo.mayStore)); } - if (Inst.neverHasSideEffects) { - if (HadPattern) - PrintWarning(Inst.TheDef->getLoc(), - "neverHasSideEffects flag explicitly set on " - "instruction, but flag already inferred from pattern."); - HasSideEffects = false; + if (InstInfo.mayLoad != PatInfo.mayLoad && !InstInfo.mayLoad_Unset) { + // Allow explicitly setting mayLoad = 1, even when the pattern has no loads. + // Some targets translate imediates to loads. + if (!InstInfo.mayLoad) { + Error = true; + PrintError(PatDef->getLoc(), "Pattern doesn't match mayLoad = " + + Twine(InstInfo.mayLoad)); + } } - if (Inst.hasSideEffects) { - if (HasSideEffects) - PrintWarning(Inst.TheDef->getLoc(), - "hasSideEffects flag explicitly set on " - "instruction, but flag already inferred from pattern."); - HasSideEffects = true; - } + // Transfer inferred flags. + InstInfo.hasSideEffects |= PatInfo.hasSideEffects; + InstInfo.mayStore |= PatInfo.mayStore; + InstInfo.mayLoad |= PatInfo.mayLoad; - if (Inst.Operands.isVariadic) - IsVariadic = true; // Can warn if we want. + // These flags are silently added without any verification. + InstInfo.isBitcast |= PatInfo.isBitcast; + + // Don't infer isVariadic. This flag means something different on SDNodes and + // instructions. For example, a CALL SDNode is variadic because it has the + // call arguments as operands, but a CALL instruction is not variadic - it + // has argument registers as implicit, not explicit uses. + + return Error; } /// hasNullFragReference - Return true if the DAG has any reference to the @@ -2551,6 +2536,17 @@ static bool hasNullFragReference(ListInit *LI) { return false; } +/// Get all the instructions in a tree. +static void +getInstructionsInTree(TreePatternNode *Tree, SmallVectorImpl<Record*> &Instrs) { + if (Tree->isLeaf()) + return; + if (Tree->getOperator()->isSubClassOf("Instruction")) + Instrs.push_back(Tree->getOperator()); + for (unsigned i = 0, e = Tree->getNumChildren(); i != e; ++i) + getInstructionsInTree(Tree->getChild(i), Instrs); +} + /// ParseInstructions - Parse all of the instructions, inlining and resolving /// any fragments involved. This populates the Instructions list with fully /// resolved instructions. @@ -2683,11 +2679,9 @@ void CodeGenDAGPatterns::ParseInstructions() { I->error("Operand #" + utostr(i) + " in operands list has no name!"); if (!InstInputsCheck.count(OpName)) { - // If this is an predicate operand or optional def operand with an - // DefaultOps set filled in, we can ignore this. When we codegen it, - // we will do so as always executed. - if (Op.Rec->isSubClassOf("PredicateOperand") || - Op.Rec->isSubClassOf("OptionalDefOperand")) { + // If this is an operand with a DefaultOps set filled in, we can ignore + // this. When we codegen it, we will do so as always executed. + if (Op.Rec->isSubClassOf("OperandWithDefaultOps")) { // Does it have a non-empty DefaultOps field? If so, ignore this // operand. if (!getDefaultOperand(Op.Rec).DefaultOps.empty()) @@ -2852,25 +2846,156 @@ void CodeGenDAGPatterns::AddPatternToMatch(const TreePattern *Pattern, void CodeGenDAGPatterns::InferInstructionFlags() { const std::vector<const CodeGenInstruction*> &Instructions = Target.getInstructionsByEnumValue(); + + // First try to infer flags from the primary instruction pattern, if any. + SmallVector<CodeGenInstruction*, 8> Revisit; + unsigned Errors = 0; for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { CodeGenInstruction &InstInfo = const_cast<CodeGenInstruction &>(*Instructions[i]); - // Determine properties of the instruction from its pattern. - bool MayStore, MayLoad, IsBitcast, HasSideEffects, IsVariadic; - InferFromPattern(InstInfo, MayStore, MayLoad, IsBitcast, - HasSideEffects, IsVariadic, *this); - InstInfo.mayStore = MayStore; - InstInfo.mayLoad = MayLoad; - InstInfo.isBitcast = IsBitcast; - InstInfo.hasSideEffects = HasSideEffects; - InstInfo.Operands.isVariadic = IsVariadic; - // Sanity checks. - if (InstInfo.isReMaterializable && InstInfo.hasSideEffects) - throw TGError(InstInfo.TheDef->getLoc(), "The instruction " + - InstInfo.TheDef->getName() + - " is rematerializable AND has unmodeled side effects?"); + // Treat neverHasSideEffects = 1 as the equivalent of hasSideEffects = 0. + // This flag is obsolete and will be removed. + if (InstInfo.neverHasSideEffects) { + assert(!InstInfo.hasSideEffects); + InstInfo.hasSideEffects_Unset = false; + } + + // Get the primary instruction pattern. + const TreePattern *Pattern = getInstruction(InstInfo.TheDef).getPattern(); + if (!Pattern) { + if (InstInfo.hasUndefFlags()) + Revisit.push_back(&InstInfo); + continue; + } + InstAnalyzer PatInfo(*this); + PatInfo.Analyze(Pattern); + Errors += InferFromPattern(InstInfo, PatInfo, InstInfo.TheDef); + } + + // Second, look for single-instruction patterns defined outside the + // instruction. + for (ptm_iterator I = ptm_begin(), E = ptm_end(); I != E; ++I) { + const PatternToMatch &PTM = *I; + + // We can only infer from single-instruction patterns, otherwise we won't + // know which instruction should get the flags. + SmallVector<Record*, 8> PatInstrs; + getInstructionsInTree(PTM.getDstPattern(), PatInstrs); + if (PatInstrs.size() != 1) + continue; + + // Get the single instruction. + CodeGenInstruction &InstInfo = Target.getInstruction(PatInstrs.front()); + + // Only infer properties from the first pattern. We'll verify the others. + if (InstInfo.InferredFrom) + continue; + + InstAnalyzer PatInfo(*this); + PatInfo.Analyze(&PTM); + Errors += InferFromPattern(InstInfo, PatInfo, PTM.getSrcRecord()); } + + if (Errors) + throw "pattern conflicts"; + + // Revisit instructions with undefined flags and no pattern. + if (Target.guessInstructionProperties()) { + for (unsigned i = 0, e = Revisit.size(); i != e; ++i) { + CodeGenInstruction &InstInfo = *Revisit[i]; + if (InstInfo.InferredFrom) + continue; + // The mayLoad and mayStore flags default to false. + // Conservatively assume hasSideEffects if it wasn't explicit. + if (InstInfo.hasSideEffects_Unset) + InstInfo.hasSideEffects = true; + } + return; + } + + // Complain about any flags that are still undefined. + for (unsigned i = 0, e = Revisit.size(); i != e; ++i) { + CodeGenInstruction &InstInfo = *Revisit[i]; + if (InstInfo.InferredFrom) + continue; + if (InstInfo.hasSideEffects_Unset) + PrintError(InstInfo.TheDef->getLoc(), + "Can't infer hasSideEffects from patterns"); + if (InstInfo.mayStore_Unset) + PrintError(InstInfo.TheDef->getLoc(), + "Can't infer mayStore from patterns"); + if (InstInfo.mayLoad_Unset) + PrintError(InstInfo.TheDef->getLoc(), + "Can't infer mayLoad from patterns"); + } +} + + +/// Verify instruction flags against pattern node properties. +void CodeGenDAGPatterns::VerifyInstructionFlags() { + unsigned Errors = 0; + for (ptm_iterator I = ptm_begin(), E = ptm_end(); I != E; ++I) { + const PatternToMatch &PTM = *I; + SmallVector<Record*, 8> Instrs; + getInstructionsInTree(PTM.getDstPattern(), Instrs); + if (Instrs.empty()) + continue; + + // Count the number of instructions with each flag set. + unsigned NumSideEffects = 0; + unsigned NumStores = 0; + unsigned NumLoads = 0; + for (unsigned i = 0, e = Instrs.size(); i != e; ++i) { + const CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]); + NumSideEffects += InstInfo.hasSideEffects; + NumStores += InstInfo.mayStore; + NumLoads += InstInfo.mayLoad; + } + + // Analyze the source pattern. + InstAnalyzer PatInfo(*this); + PatInfo.Analyze(&PTM); + + // Collect error messages. + SmallVector<std::string, 4> Msgs; + + // Check for missing flags in the output. + // Permit extra flags for now at least. + if (PatInfo.hasSideEffects && !NumSideEffects) + Msgs.push_back("pattern has side effects, but hasSideEffects isn't set"); + + // Don't verify store flags on instructions with side effects. At least for + // intrinsics, side effects implies mayStore. + if (!PatInfo.hasSideEffects && PatInfo.mayStore && !NumStores) + Msgs.push_back("pattern may store, but mayStore isn't set"); + + // Similarly, mayStore implies mayLoad on intrinsics. + if (!PatInfo.mayStore && PatInfo.mayLoad && !NumLoads) + Msgs.push_back("pattern may load, but mayLoad isn't set"); + + // Print error messages. + if (Msgs.empty()) + continue; + ++Errors; + + for (unsigned i = 0, e = Msgs.size(); i != e; ++i) + PrintError(PTM.getSrcRecord()->getLoc(), Twine(Msgs[i]) + " on the " + + (Instrs.size() == 1 ? + "instruction" : "output instructions")); + // Provide the location of the relevant instruction definitions. + for (unsigned i = 0, e = Instrs.size(); i != e; ++i) { + if (Instrs[i] != PTM.getSrcRecord()) + PrintError(Instrs[i]->getLoc(), "defined here"); + const CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]); + if (InstInfo.InferredFrom && + InstInfo.InferredFrom != InstInfo.TheDef && + InstInfo.InferredFrom != PTM.getSrcRecord()) + PrintError(InstInfo.InferredFrom->getLoc(), "inferred from patttern"); + } + } + if (Errors) + throw "Errors in DAG patterns"; } /// Given a pattern result with an unresolved type, see if we can find one @@ -3330,4 +3455,3 @@ void CodeGenDAGPatterns::GenerateVariants() { DEBUG(errs() << "\n"); } } - diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index 5a2d40a..25a0e4b 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -582,8 +582,8 @@ private: void ComputeNamedNodes(TreePatternNode *N); }; -/// DAGDefaultOperand - One of these is created for each PredicateOperand -/// or OptionalDefOperand that has a set ExecuteAlways / DefaultOps field. +/// DAGDefaultOperand - One of these is created for each OperandWithDefaultOps +/// that has a set ExecuteAlways / DefaultOps field. struct DAGDefaultOperand { std::vector<TreePatternNode*> DefaultOps; }; @@ -797,6 +797,7 @@ private: void ParsePatterns(); void InferInstructionFlags(); void GenerateVariants(); + void VerifyInstructionFlags(); void AddPatternToMatch(const TreePattern *Pattern, const PatternToMatch &PTM); void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 12e153a..38e2b83 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -287,7 +287,8 @@ void CGIOperandList::ProcessDisableEncoding(std::string DisableEncoding) { // CodeGenInstruction Implementation //===----------------------------------------------------------------------===// -CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R), Operands(R) { +CodeGenInstruction::CodeGenInstruction(Record *R) + : TheDef(R), Operands(R), InferredFrom(0) { Namespace = R->getValueAsString("Namespace"); AsmString = R->getValueAsString("AsmString"); @@ -301,8 +302,6 @@ CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R), Operands(R) { isBarrier = R->getValueAsBit("isBarrier"); isCall = R->getValueAsBit("isCall"); canFoldAsLoad = R->getValueAsBit("canFoldAsLoad"); - mayLoad = R->getValueAsBit("mayLoad"); - mayStore = R->getValueAsBit("mayStore"); isPredicable = Operands.isPredicable || R->getValueAsBit("isPredicable"); isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress"); isCommutable = R->getValueAsBit("isCommutable"); @@ -313,8 +312,13 @@ CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R), Operands(R) { hasPostISelHook = R->getValueAsBit("hasPostISelHook"); hasCtrlDep = R->getValueAsBit("hasCtrlDep"); isNotDuplicable = R->getValueAsBit("isNotDuplicable"); - hasSideEffects = R->getValueAsBit("hasSideEffects"); + + mayLoad = R->getValueAsBitOrUnset("mayLoad", mayLoad_Unset); + mayStore = R->getValueAsBitOrUnset("mayStore", mayStore_Unset); + hasSideEffects = R->getValueAsBitOrUnset("hasSideEffects", + hasSideEffects_Unset); neverHasSideEffects = R->getValueAsBit("neverHasSideEffects"); + isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove"); hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq"); hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq"); @@ -409,7 +413,7 @@ FlattenAsmStringVariants(StringRef Cur, unsigned Variant) { /// successful match, with ResOp set to the result operand to be used. bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, Record *InstOpRec, bool hasSubOps, - SMLoc Loc, CodeGenTarget &T, + ArrayRef<SMLoc> Loc, CodeGenTarget &T, ResultOperand &ResOp) { Init *Arg = Result->getArg(AliasOpNo); DefInit *ADI = dynamic_cast<DefInit*>(Arg); diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index 95b572d..f601a83 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -226,7 +226,10 @@ namespace llvm { bool isBarrier; bool isCall; bool canFoldAsLoad; - bool mayLoad, mayStore; + bool mayLoad; + bool mayLoad_Unset; + bool mayStore; + bool mayStore_Unset; bool isPredicable; bool isConvertibleToThreeAddress; bool isCommutable; @@ -238,6 +241,7 @@ namespace llvm { bool hasCtrlDep; bool isNotDuplicable; bool hasSideEffects; + bool hasSideEffects_Unset; bool neverHasSideEffects; bool isAsCheapAsAMove; bool hasExtraSrcRegAllocReq; @@ -245,6 +249,14 @@ namespace llvm { bool isCodeGenOnly; bool isPseudo; + /// Are there any undefined flags? + bool hasUndefFlags() const { + return mayLoad_Unset || mayStore_Unset || hasSideEffects_Unset; + } + + // The record used to infer instruction flags, or NULL if no flag values + // have been inferred. + Record *InferredFrom; CodeGenInstruction(Record *R); @@ -319,7 +331,7 @@ namespace llvm { CodeGenInstAlias(Record *R, CodeGenTarget &T); bool tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, - Record *InstOpRec, bool hasSubOps, SMLoc Loc, + Record *InstOpRec, bool hasSubOps, ArrayRef<SMLoc> Loc, CodeGenTarget &T, ResultOperand &ResOp); }; } diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp index 011f4b7..b2e9e38 100644 --- a/utils/TableGen/CodeGenRegisters.cpp +++ b/utils/TableGen/CodeGenRegisters.cpp @@ -298,7 +298,7 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) { for (SubRegMap::const_iterator SI = SubRegs.begin(), SE = SubRegs.end(); SI != SE; ++SI) { if (SI->second == this) { - SMLoc Loc; + ArrayRef<SMLoc> Loc; if (TheDef) Loc = TheDef->getLoc(); throw TGError(Loc, "Register " + getName() + @@ -310,7 +310,7 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) { if (Ins->second == SI->first) continue; // Trouble: Two different names for SI->second. - SMLoc Loc; + ArrayRef<SMLoc> Loc; if (TheDef) Loc = TheDef->getLoc(); throw TGError(Loc, "Sub-register can't have two names: " + diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index 1dd2efc..fa31c9f 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -300,6 +300,8 @@ void CodeGenTarget::ComputeInstrsByEnum() const { "REG_SEQUENCE", "COPY", "BUNDLE", + "LIFETIME_START", + "LIFETIME_END", 0 }; const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions(); @@ -334,6 +336,15 @@ bool CodeGenTarget::isLittleEndianEncoding() const { return getInstructionSet()->getValueAsBit("isLittleEndianEncoding"); } +/// guessInstructionProperties - Return true if it's OK to guess instruction +/// properties instead of raising an error. +/// +/// This is configurable as a temporary migration aid. It will eventually be +/// permanently false. +bool CodeGenTarget::guessInstructionProperties() const { + return getInstructionSet()->getValueAsBit("guessInstructionProperties"); +} + //===----------------------------------------------------------------------===// // ComplexPattern implementation // diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h index 2f8cee4..672b140 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -177,6 +177,10 @@ public: /// bool isLittleEndianEncoding() const; + /// guessInstructionProperties - should we just guess unset instruction + /// properties? + bool guessInstructionProperties() const; + private: void ComputeInstrsByEnum() const; }; diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index aed222c..b291269 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -727,8 +727,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // Determine what to emit for this operand. Record *OperandNode = II.Operands[InstOpNo].Rec; - if ((OperandNode->isSubClassOf("PredicateOperand") || - OperandNode->isSubClassOf("OptionalDefOperand")) && + if (OperandNode->isSubClassOf("OperandWithDefaultOps") && !CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) { // This is a predicate or optional def operand; emit the // 'default ops' operands. diff --git a/utils/TableGen/DFAPacketizerEmitter.cpp b/utils/TableGen/DFAPacketizerEmitter.cpp index 8bfecea..0ad25a5 100644 --- a/utils/TableGen/DFAPacketizerEmitter.cpp +++ b/utils/TableGen/DFAPacketizerEmitter.cpp @@ -17,6 +17,7 @@ #include "CodeGenTarget.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" #include <list> @@ -74,6 +75,8 @@ public: // Another way of thinking about this transition is we are mapping a NDFA with // two states [0x01] and [0x10] into a DFA with a single state [0x01, 0x10]. // +// A State instance also contains a collection of transitions from that state: +// a map from inputs to new states. // namespace { class State { @@ -82,10 +85,16 @@ class State { int stateNum; bool isInitial; std::set<unsigned> stateInfo; + typedef std::map<unsigned, State *> TransitionMap; + TransitionMap Transitions; State(); State(const State &S); + bool operator<(const State &s) const { + return stateNum < s.stateNum; + } + // // canAddInsnClass - Returns true if an instruction of type InsnClass is a // valid transition from this state, i.e., can an instruction of type InsnClass @@ -100,38 +109,18 @@ class State { // which are possible from this state (PossibleStates). // void AddInsnClass(unsigned InsnClass, std::set<unsigned> &PossibleStates); + // + // addTransition - Add a transition from this state given the input InsnClass + // + void addTransition(unsigned InsnClass, State *To); + // + // hasTransition - Returns true if there is a transition from this state + // given the input InsnClass + // + bool hasTransition(unsigned InsnClass); }; } // End anonymous namespace. - -namespace { -struct Transition { - public: - static int currentTransitionNum; - int transitionNum; - State *from; - unsigned input; - State *to; - - Transition(State *from_, unsigned input_, State *to_); -}; -} // End anonymous namespace. - - -// -// Comparators to keep set of states sorted. -// -namespace { -struct ltState { - bool operator()(const State *s1, const State *s2) const; -}; - -struct ltTransition { - bool operator()(const Transition *s1, const Transition *s2) const; -}; -} // End anonymous namespace. - - // // class DFA: deterministic finite automaton for processor resource tracking. // @@ -139,36 +128,19 @@ namespace { class DFA { public: DFA(); + ~DFA(); // Set of states. Need to keep this sorted to emit the transition table. - std::set<State*, ltState> states; + typedef std::set<State *, less_ptr<State> > StateSet; + StateSet states; - // Map from a state to the list of transitions with that state as source. - std::map<State*, std::set<Transition*, ltTransition>, ltState> - stateTransitions; State *currentState; - // Highest valued Input seen. - unsigned LargestInput; - // // Modify the DFA. // void initialize(); void addState(State *); - void addTransition(Transition *); - - // - // getTransition - Return the state when a transition is made from - // State From with Input I. If a transition is not found, return NULL. - // - State *getTransition(State *, unsigned); - - // - // isValidTransition: Predicate that checks if there is a valid transition - // from state From on input InsnClass. - // - bool isValidTransition(State *From, unsigned InsnClass); // // writeTable: Print out a table representing the DFA. @@ -179,7 +151,7 @@ public: // -// Constructors for State, Transition, and DFA +// Constructors and destructors for State and DFA // State::State() : stateNum(currentStateNum++), isInitial(false) {} @@ -189,22 +161,27 @@ State::State(const State &S) : stateNum(currentStateNum++), isInitial(S.isInitial), stateInfo(S.stateInfo) {} +DFA::DFA(): currentState(NULL) {} -Transition::Transition(State *from_, unsigned input_, State *to_) : - transitionNum(currentTransitionNum++), from(from_), input(input_), - to(to_) {} - - -DFA::DFA() : - LargestInput(0) {} - +DFA::~DFA() { + DeleteContainerPointers(states); +} -bool ltState::operator()(const State *s1, const State *s2) const { - return (s1->stateNum < s2->stateNum); +// +// addTransition - Add a transition from this state given the input InsnClass +// +void State::addTransition(unsigned InsnClass, State *To) { + assert(!Transitions.count(InsnClass) && + "Cannot have multiple transitions for the same input"); + Transitions[InsnClass] = To; } -bool ltTransition::operator()(const Transition *s1, const Transition *s2) const { - return (s1->input < s2->input); +// +// hasTransition - Returns true if there is a transition from this state +// given the input InsnClass +// +bool State::hasTransition(unsigned InsnClass) { + return Transitions.count(InsnClass) > 0; } // @@ -272,6 +249,7 @@ bool State::canAddInsnClass(unsigned InsnClass) const { void DFA::initialize() { + assert(currentState && "Missing current state"); currentState->isInitial = true; } @@ -282,47 +260,7 @@ void DFA::addState(State *S) { } -void DFA::addTransition(Transition *T) { - // Update LargestInput. - if (T->input > LargestInput) - LargestInput = T->input; - - // Add the new transition. - bool Added = stateTransitions[T->from].insert(T).second; - assert(Added && "Cannot have multiple states for the same input"); - (void)Added; -} - - -// -// getTransition - Return the state when a transition is made from -// State From with Input I. If a transition is not found, return NULL. -// -State *DFA::getTransition(State *From, unsigned I) { - // Do we have a transition from state From? - if (!stateTransitions.count(From)) - return NULL; - - // Do we have a transition from state From with Input I? - Transition TVal(NULL, I, NULL); - // Do not count this temporal instance - Transition::currentTransitionNum--; - std::set<Transition*, ltTransition>::iterator T = - stateTransitions[From].find(&TVal); - if (T != stateTransitions[From].end()) - return (*T)->to; - - return NULL; -} - - -bool DFA::isValidTransition(State *From, unsigned InsnClass) { - return (getTransition(From, InsnClass) != NULL); -} - - int State::currentStateNum = 0; -int Transition::currentTransitionNum = 0; DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R): TargetName(CodeGenTarget(R).getName()), @@ -341,7 +279,7 @@ DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R): // // void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) { - std::set<State*, ltState>::iterator SI = states.begin(); + DFA::StateSet::iterator SI = states.begin(); // This table provides a map to the beginning of the transitions for State s // in DFAStateInputTable. std::vector<int> StateEntry(states.size()); @@ -353,18 +291,16 @@ void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) { // to construct the StateEntry table. int ValidTransitions = 0; for (unsigned i = 0; i < states.size(); ++i, ++SI) { + assert (((*SI)->stateNum == (int) i) && "Mismatch in state numbers"); StateEntry[i] = ValidTransitions; - for (unsigned j = 0; j <= LargestInput; ++j) { - assert (((*SI)->stateNum == (int) i) && "Mismatch in state numbers"); - State *To = getTransition(*SI, j); - if (To == NULL) - continue; - - OS << "{" << j << ", " - << To->stateNum + for (State::TransitionMap::iterator + II = (*SI)->Transitions.begin(), IE = (*SI)->Transitions.end(); + II != IE; ++II) { + OS << "{" << II->first << ", " + << II->second->stateNum << "}, "; - ++ValidTransitions; } + ValidTransitions += (*SI)->Transitions.size(); // If there are no valid transitions from this stage, we need a sentinel // transition. @@ -539,7 +475,7 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { // If we haven't already created a transition for this input // and the state can accommodate this InsnClass, create a transition. // - if (!D.getTransition(current, InsnClass) && + if (!current->hasTransition(InsnClass) && current->canAddInsnClass(InsnClass)) { State *NewState = NULL; current->AddInsnClass(InsnClass, NewStateResources); @@ -559,10 +495,8 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { Visited[NewStateResources] = NewState; WorkList.push_back(NewState); } - - Transition *NewTransition = new Transition(current, InsnClass, - NewState); - D.addTransition(NewTransition); + + current->addTransition(InsnClass, NewState); } } } diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index e89c393..aa6d796 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -1783,7 +1783,7 @@ static bool populateInstruction(const CodeGenInstruction &CGI, unsigned Opc, VarInit *Var = 0; VarBitInit *BI = dynamic_cast<VarBitInit*>(Bits.getBit(bi)); if (BI) - Var = dynamic_cast<VarInit*>(BI->getVariable()); + Var = dynamic_cast<VarInit*>(BI->getBitVar()); else Var = dynamic_cast<VarInit*>(Bits.getBit(bi)); diff --git a/utils/TableGen/PseudoLoweringEmitter.cpp b/utils/TableGen/PseudoLoweringEmitter.cpp index 8d9d419..8e28180 100644 --- a/utils/TableGen/PseudoLoweringEmitter.cpp +++ b/utils/TableGen/PseudoLoweringEmitter.cpp @@ -156,7 +156,7 @@ void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) { // If there are more operands that weren't in the DAG, they have to // be operands that have default values, or we have an error. Currently, - // PredicateOperand and OptionalDefOperand both have default values. + // Operands that are a sublass of OperandWithDefaultOp have default values. // Validate that each result pattern argument has a matching (by name) diff --git a/utils/TableGen/SequenceToOffsetTable.h b/utils/TableGen/SequenceToOffsetTable.h index d8ab2ee..60202b5 100644 --- a/utils/TableGen/SequenceToOffsetTable.h +++ b/utils/TableGen/SequenceToOffsetTable.h @@ -29,8 +29,8 @@ namespace llvm { /// Compute the layout of a table that contains all the sequences, possibly by /// reusing entries. /// -/// @param SeqT The sequence container. (vector or string). -/// @param Less A stable comparator for SeqT elements. +/// @tparam SeqT The sequence container. (vector or string). +/// @tparam Less A stable comparator for SeqT elements. template<typename SeqT, typename Less = std::less<typename SeqT::value_type> > class SequenceToOffsetTable { typedef typename SeqT::value_type ElemT; diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index 3472343..5dfd716 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -626,7 +626,7 @@ void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) { // Emit as { "cpu", procinit }, OS << " { " << "\"" << Name << "\", " - << "(void *)&" << ProcModelName; + << "(const void *)&" << ProcModelName; OS << " }"; diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index 7ac2336..4b12279 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -1145,6 +1145,8 @@ OperandEncoding RecognizableInstr::immediateEncodingFromString // register IDs in 8-bit immediates nowadays. ENCODING("VR256", ENCODING_IB) ENCODING("VR128", ENCODING_IB) + ENCODING("FR32", ENCODING_IB) + ENCODING("FR64", ENCODING_IB) errs() << "Unhandled immediate encoding " << s << "\n"; llvm_unreachable("Unhandled immediate encoding"); } diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h index 542e510..e0bb2e2 100644 --- a/utils/TableGen/X86RecognizableInstr.h +++ b/utils/TableGen/X86RecognizableInstr.h @@ -143,7 +143,7 @@ private: /// @param hasREX_WPrefix - Indicates whether the instruction has a REX.W /// prefix. If it does, 32-bit register operands stay /// 32-bit regardless of the operand size. - /// @param hasOpSizePrefix- Indicates whether the instruction has an OpSize + /// @param hasOpSizePrefix Indicates whether the instruction has an OpSize /// prefix. If it does not, then 16-bit register /// operands stay 16-bit. /// @return - The operand's type. diff --git a/utils/lit/lit/Util.py b/utils/lit/lit/Util.py index 226e453..f294809 100644 --- a/utils/lit/lit/Util.py +++ b/utils/lit/lit/Util.py @@ -56,7 +56,7 @@ def which(command, paths = None): paths = os.environ.get('PATH','') # Check for absolute match first. - if os.path.exists(command): + if os.path.isfile(command): return command # Would be nice if Python had a lib function for this. diff --git a/utils/llvm-lit/llvm-lit.in b/utils/llvm-lit/llvm-lit.in index 879d18b..768dc51 100755 --- a/utils/llvm-lit/llvm-lit.in +++ b/utils/llvm-lit/llvm-lit.in @@ -18,10 +18,15 @@ builtin_parameters = { 'llvm_site_config' : os.path.join(llvm_obj_root, 'test', 'lit.site.cfg') } -clang_site_config = os.path.join(llvm_obj_root, 'tools', 'clang', 'test', - 'lit.site.cfg') -if os.path.exists(clang_site_config): - builtin_parameters['clang_site_config'] = clang_site_config +clang_obj_root = os.path.join(llvm_obj_root, 'tools', 'clang') + +if os.path.exists(clang_obj_root): + builtin_parameters['clang_site_config'] = \ + os.path.join(clang_obj_root, 'test', 'lit.site.cfg') + clang_tools_extra_obj_root = os.path.join(clang_obj_root, 'tools', 'extra') + if os.path.exists(clang_tools_extra_obj_root): + builtin_parameters['clang_tools_extra_site_config'] = \ + os.path.join(clang_tools_extra_obj_root, 'test', 'lit.site.cfg') if __name__=='__main__': import lit diff --git a/utils/llvm.grm b/utils/llvm.grm index ad2799f..322036b 100644 --- a/utils/llvm.grm +++ b/utils/llvm.grm @@ -175,7 +175,6 @@ FuncAttr ::= noreturn | returns_twice | nonlazybind | address_safety - | ia_nsdialect ; OptFuncAttrs ::= + _ | OptFuncAttrs FuncAttr ; diff --git a/utils/unittest/googletest/gtest-port.cc b/utils/unittest/googletest/gtest-port.cc index 07e5bb3..3c32ff1 100644 --- a/utils/unittest/googletest/gtest-port.cc +++ b/utils/unittest/googletest/gtest-port.cc @@ -505,6 +505,10 @@ class CapturedStream { GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file " << temp_file_path; filename_ = temp_file_path; +#elif GTEST_OS_LINUX_ANDROID + char name_template[] = "/sdcard/captured_stderr.XXXXXX"; + const int captured_fd = mkstemp(name_template); + filename_ = name_template; # else // There's no guarantee that a test has write access to the // current directory, so we create the temporary file in the /tmp diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-port.h b/utils/unittest/googletest/include/gtest/internal/gtest-port.h index 8ef5d7d..58f6caf 100644 --- a/utils/unittest/googletest/include/gtest/internal/gtest-port.h +++ b/utils/unittest/googletest/include/gtest/internal/gtest-port.h @@ -230,7 +230,7 @@ # define GTEST_OS_MAC 1 #elif defined __linux__ # define GTEST_OS_LINUX 1 -# ifdef ANDROID +# if defined(ANDROID) || defined(__ANDROID__) # define GTEST_OS_LINUX_ANDROID 1 # endif // ANDROID #elif defined __MVS__ |