diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td index 7d6d38ecad897..ade2b64c108ff 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td @@ -1378,6 +1378,54 @@ def ModuleFlagCGProfileEntryAttr let assemblyFormat = "`<` struct(params) `>`"; } +def ModuleFlagProfileSummaryDetailedAttr + : LLVM_Attr<"ModuleFlagProfileSummaryDetailed", "profile_summary_detailed"> { + let summary = "ProfileSummary detailed information"; + let description = [{ + Contains detailed information pertinent to "ProfileSummary" attribute. + A `#llvm.profile_summary` may contain several of it. + ```mlir + llvm.module_flags [ ... + detailed_summary = + , + + ``` + }]; + let parameters = (ins "uint32_t":$cut_off, + "uint64_t":$min_count, + "uint32_t":$num_counts); + let assemblyFormat = "`<` struct(params) `>`"; +} + +def ModuleFlagProfileSummaryAttr + : LLVM_Attr<"ModuleFlagProfileSummary", "profile_summary"> { + let summary = "ProfileSummary module flag"; + let description = [{ + Describes ProfileSummary gathered data in a module. Example: + ```mlir + llvm.module_flags [#llvm.mlir.module_flag, + + >>] + ``` + }]; + let parameters = (ins "ProfileSummaryFormatKind":$format, + "uint64_t":$total_count, "uint64_t":$max_count, + "uint64_t":$max_internal_count, "uint64_t":$max_function_count, + "uint64_t":$num_counts, "uint64_t":$num_functions, + OptionalParameter<"std::optional">:$is_partial_profile, + OptionalParameter<"FloatAttr">:$partial_profile_ratio, + ArrayRefParameter<"ModuleFlagProfileSummaryDetailedAttr">:$detailed_summary); + + let assemblyFormat = "`<` struct(params) `>`"; +} + //===----------------------------------------------------------------------===// // LLVM_DependentLibrariesAttr //===----------------------------------------------------------------------===// diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td index 9f9d075a3eebf..b5ea8fc5da500 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td @@ -92,6 +92,9 @@ def LLVM_Dialect : Dialect { static StringRef getModuleFlagKeyCGProfileName() { return "CG Profile"; } + static StringRef getModuleFlagKeyProfileSummaryName() { + return "ProfileSummary"; + } /// Returns `true` if the given type is compatible with the LLVM dialect. static bool isCompatibleType(Type); diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td index 6c0fe363d5551..7f5052948ab6c 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td @@ -823,7 +823,7 @@ def FPExceptionBehaviorAttr : LLVM_EnumAttr< } //===----------------------------------------------------------------------===// -// Module Flag Behavior +// Module Flags //===----------------------------------------------------------------------===// // These values must match llvm::Module::ModFlagBehavior ones. @@ -855,6 +855,21 @@ def ModFlagBehaviorAttr : LLVM_EnumAttr< let cppNamespace = "::mlir::LLVM"; } +def LLVM_ProfileSummaryFormatSampleProfile : I64EnumAttrCase<"SampleProfile", + 0>; +def LLVM_ProfileSummaryFormatInstrProf : I64EnumAttrCase<"InstrProf", 1>; +def LLVM_ProfileSummaryFormatCSInstrProf : I64EnumAttrCase<"CSInstrProf", 2>; + +def LLVM_ProfileSummaryFormatKind : I64EnumAttr< + "ProfileSummaryFormatKind", + "LLVM ProfileSummary format kinds", [ + LLVM_ProfileSummaryFormatSampleProfile, + LLVM_ProfileSummaryFormatInstrProf, + LLVM_ProfileSummaryFormatCSInstrProf, + ]> { + let cppNamespace = "::mlir::LLVM"; +} + //===----------------------------------------------------------------------===// // UWTableKind //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp index ffde597ac83c1..d5815d39b364b 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp @@ -390,6 +390,13 @@ ModuleFlagAttr::verify(function_ref emitError, return success(); } + if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName()) { + if (!isa(value)) + return emitError() << "'ProfileSummary' key expects a " + "'#llvm.profile_summary' attribute"; + return success(); + } + if (isa(value)) return success(); diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp index 35dcde2a33d41..4ea313019f34d 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp @@ -303,6 +303,69 @@ convertModuleFlagValue(StringRef key, ArrayAttr arrayAttr, return nullptr; } +static llvm::Metadata *convertModuleFlagProfileSummaryAttr( + StringRef key, ModuleFlagProfileSummaryAttr summaryAttr, + llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) { + llvm::LLVMContext &context = builder.getContext(); + llvm::MDBuilder mdb(context); + SmallVector summaryNodes; + + auto getIntTuple = [&](StringRef key, uint64_t val) -> llvm::MDTuple * { + SmallVector tupleNodes{ + mdb.createString(key), mdb.createConstant(llvm::ConstantInt::get( + llvm::Type::getInt64Ty(context), val))}; + return llvm::MDTuple::get(context, tupleNodes); + }; + + SmallVector fmtNode{ + mdb.createString("ProfileFormat"), + mdb.createString( + stringifyProfileSummaryFormatKind(summaryAttr.getFormat()))}; + + SmallVector vals = { + llvm::MDTuple::get(context, fmtNode), + getIntTuple("TotalCount", summaryAttr.getTotalCount()), + getIntTuple("MaxCount", summaryAttr.getMaxCount()), + getIntTuple("MaxInternalCount", summaryAttr.getMaxInternalCount()), + getIntTuple("MaxFunctionCount", summaryAttr.getMaxFunctionCount()), + getIntTuple("NumCounts", summaryAttr.getNumCounts()), + getIntTuple("NumFunctions", summaryAttr.getNumFunctions()), + }; + + if (summaryAttr.getIsPartialProfile()) + vals.push_back( + getIntTuple("IsPartialProfile", *summaryAttr.getIsPartialProfile())); + + if (summaryAttr.getPartialProfileRatio()) { + SmallVector tupleNodes{ + mdb.createString("PartialProfileRatio"), + mdb.createConstant(llvm::ConstantFP::get( + llvm::Type::getDoubleTy(context), + summaryAttr.getPartialProfileRatio().getValue()))}; + vals.push_back(llvm::MDTuple::get(context, tupleNodes)); + } + + SmallVector detailedEntries; + llvm::Type *llvmInt64Type = llvm::Type::getInt64Ty(context); + for (ModuleFlagProfileSummaryDetailedAttr detailedEntry : + summaryAttr.getDetailedSummary()) { + SmallVector tupleNodes{ + mdb.createConstant( + llvm::ConstantInt::get(llvmInt64Type, detailedEntry.getCutOff())), + mdb.createConstant( + llvm::ConstantInt::get(llvmInt64Type, detailedEntry.getMinCount())), + mdb.createConstant(llvm::ConstantInt::get( + llvmInt64Type, detailedEntry.getNumCounts()))}; + detailedEntries.push_back(llvm::MDTuple::get(context, tupleNodes)); + } + SmallVector detailedSummary{ + mdb.createString("DetailedSummary"), + llvm::MDTuple::get(context, detailedEntries)}; + vals.push_back(llvm::MDTuple::get(context, detailedSummary)); + + return llvm::MDNode::get(context, vals); +} + static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) { llvm::Module *llvmModule = moduleTranslation.getLLVMModule(); @@ -323,6 +386,11 @@ static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder, arrayAttr, builder, moduleTranslation); }) + .Case([&](ModuleFlagProfileSummaryAttr summaryAttr) { + return convertModuleFlagProfileSummaryAttr( + flagAttr.getKey().getValue(), summaryAttr, builder, + moduleTranslation); + }) .Default([](auto) { return nullptr; }); assert(valueMetadata && "expected valid metadata"); diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp index 0b77a3d23d392..6f56a17ecd4e3 100644 --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -41,6 +41,7 @@ #include "llvm/IR/Metadata.h" #include "llvm/IR/Operator.h" #include "llvm/Support/ModRef.h" +#include using namespace mlir; using namespace mlir::LLVM; @@ -554,13 +555,284 @@ static Attribute convertCGProfileModuleFlagValue(ModuleOp mlirModule, return ArrayAttr::get(mlirModule->getContext(), cgProfile); } +/// Extract a two element `MDTuple` from a `MDOperand`. Emit a warning in case +/// something else is found. +static llvm::MDTuple *getTwoElementMDTuple(ModuleOp mlirModule, + const llvm::Module *llvmModule, + const llvm::MDOperand &md) { + auto *tupleEntry = dyn_cast_or_null(md); + if (!tupleEntry || tupleEntry->getNumOperands() != 2) + emitWarning(mlirModule.getLoc()) + << "expected 2-element tuple metadata: " << diagMD(md, llvmModule); + return tupleEntry; +} + +/// Extract a constant metadata value from a two element tuple (). +/// Return nullptr if requirements are not met. A warning is emitted if the +/// `matchKey` is different from the tuple's key. +static llvm::ConstantAsMetadata *getConstantMDFromKeyValueTuple( + ModuleOp mlirModule, const llvm::Module *llvmModule, + const llvm::MDOperand &md, StringRef matchKey, bool optional = false) { + llvm::MDTuple *tupleEntry = getTwoElementMDTuple(mlirModule, llvmModule, md); + if (!tupleEntry) + return nullptr; + auto *keyMD = dyn_cast(tupleEntry->getOperand(0)); + if (!keyMD || keyMD->getString() != matchKey) { + if (!optional) + emitWarning(mlirModule.getLoc()) + << "expected '" << matchKey << "' key, but found: " + << diagMD(tupleEntry->getOperand(0), llvmModule); + return nullptr; + } + + return dyn_cast(tupleEntry->getOperand(1)); +} + +/// Extract an integer value from a two element tuple (). +/// Fail if requirements are not met. A warning is emitted if the +/// found value isn't a LLVM constant integer. +static FailureOr +convertInt64FromKeyValueTuple(ModuleOp mlirModule, + const llvm::Module *llvmModule, + const llvm::MDOperand &md, StringRef matchKey) { + llvm::ConstantAsMetadata *valMD = + getConstantMDFromKeyValueTuple(mlirModule, llvmModule, md, matchKey); + if (!valMD) + return failure(); + + if (auto *cstInt = dyn_cast(valMD->getValue())) + return cstInt->getZExtValue(); + + emitWarning(mlirModule.getLoc()) + << "expected integer metadata value for key '" << matchKey + << "': " << diagMD(md, llvmModule); + return failure(); +} + +static std::optional +convertProfileSummaryFormat(ModuleOp mlirModule, const llvm::Module *llvmModule, + const llvm::MDOperand &formatMD) { + auto *tupleEntry = getTwoElementMDTuple(mlirModule, llvmModule, formatMD); + if (!tupleEntry) + return std::nullopt; + + llvm::MDString *keyMD = dyn_cast(tupleEntry->getOperand(0)); + if (!keyMD || keyMD->getString() != "ProfileFormat") { + emitWarning(mlirModule.getLoc()) + << "expected 'ProfileFormat' key: " + << diagMD(tupleEntry->getOperand(0), llvmModule); + return std::nullopt; + } + + llvm::MDString *valMD = dyn_cast(tupleEntry->getOperand(1)); + std::optional fmtKind = + symbolizeProfileSummaryFormatKind(valMD->getString()); + if (!fmtKind) { + emitWarning(mlirModule.getLoc()) + << "expected 'SampleProfile', 'InstrProf' or 'CSInstrProf' values, " + "but found: " + << diagMD(valMD, llvmModule); + return std::nullopt; + } + + return fmtKind; +} + +static FailureOr> +convertProfileSummaryDetailed(ModuleOp mlirModule, + const llvm::Module *llvmModule, + const llvm::MDOperand &summaryMD) { + auto *tupleEntry = getTwoElementMDTuple(mlirModule, llvmModule, summaryMD); + if (!tupleEntry) + return failure(); + + llvm::MDString *keyMD = dyn_cast(tupleEntry->getOperand(0)); + if (!keyMD || keyMD->getString() != "DetailedSummary") { + emitWarning(mlirModule.getLoc()) + << "expected 'DetailedSummary' key: " + << diagMD(tupleEntry->getOperand(0), llvmModule); + return failure(); + } + + llvm::MDTuple *entriesMD = dyn_cast(tupleEntry->getOperand(1)); + if (!entriesMD) { + emitWarning(mlirModule.getLoc()) + << "expected tuple value for 'DetailedSummary' key: " + << diagMD(tupleEntry->getOperand(1), llvmModule); + return failure(); + } + + SmallVector detailedSummary; + for (auto &&entry : entriesMD->operands()) { + llvm::MDTuple *entryMD = dyn_cast(entry); + if (!entryMD || entryMD->getNumOperands() != 3) { + emitWarning(mlirModule.getLoc()) + << "'DetailedSummary' entry expects 3 operands: " + << diagMD(entry, llvmModule); + return failure(); + } + + auto *op0 = dyn_cast(entryMD->getOperand(0)); + auto *op1 = dyn_cast(entryMD->getOperand(1)); + auto *op2 = dyn_cast(entryMD->getOperand(2)); + if (!op0 || !op1 || !op2) { + emitWarning(mlirModule.getLoc()) + << "expected only integer entries in 'DetailedSummary': " + << diagMD(entry, llvmModule); + return failure(); + } + + auto detaildSummaryEntry = ModuleFlagProfileSummaryDetailedAttr::get( + mlirModule->getContext(), + cast(op0->getValue())->getZExtValue(), + cast(op1->getValue())->getZExtValue(), + cast(op2->getValue())->getZExtValue()); + detailedSummary.push_back(detaildSummaryEntry); + } + return detailedSummary; +} + +static Attribute +convertProfileSummaryModuleFlagValue(ModuleOp mlirModule, + const llvm::Module *llvmModule, + llvm::MDTuple *mdTuple) { + unsigned profileNumEntries = mdTuple->getNumOperands(); + if (profileNumEntries < 8) { + emitWarning(mlirModule.getLoc()) + << "expected at 8 entries in 'ProfileSummary': " + << diagMD(mdTuple, llvmModule); + return nullptr; + } + + unsigned summayIdx = 0; + auto checkOptionalPosition = [&](const llvm::MDOperand &md, + StringRef matchKey) -> LogicalResult { + // Make sure we won't step over the bound of the array of summary entries. + // Since (non-optional) DetailedSummary always comes last, the next entry in + // the tuple operand array must exist. + if (summayIdx + 1 >= profileNumEntries) { + emitWarning(mlirModule.getLoc()) + << "the last summary entry is '" << matchKey + << "', expected 'DetailedSummary': " << diagMD(md, llvmModule); + return failure(); + } + + return success(); + }; + + auto getOptIntValue = + [&](const llvm::MDOperand &md, + StringRef matchKey) -> FailureOr> { + if (!getConstantMDFromKeyValueTuple(mlirModule, llvmModule, md, matchKey, + /*optional=*/true)) + return FailureOr>(std::nullopt); + if (checkOptionalPosition(md, matchKey).failed()) + return failure(); + FailureOr val = + convertInt64FromKeyValueTuple(mlirModule, llvmModule, md, matchKey); + if (failed(val)) + return failure(); + return val; + }; + + auto getOptDoubleValue = [&](const llvm::MDOperand &md, + StringRef matchKey) -> FailureOr { + auto *valMD = getConstantMDFromKeyValueTuple(mlirModule, llvmModule, md, + matchKey, /*optional=*/true); + if (!valMD) + return FloatAttr{}; + if (auto *cstFP = dyn_cast(valMD->getValue())) { + if (checkOptionalPosition(md, matchKey).failed()) + return failure(); + return FloatAttr::get(Float64Type::get(mlirModule.getContext()), + cstFP->getValueAPF()); + } + emitWarning(mlirModule.getLoc()) + << "expected double metadata value for key '" << matchKey + << "': " << diagMD(md, llvmModule); + return failure(); + }; + + // Build ModuleFlagProfileSummaryAttr by sequentially fetching elements in + // a fixed order: format, total count, etc. + SmallVector profileSummary; + std::optional format = convertProfileSummaryFormat( + mlirModule, llvmModule, mdTuple->getOperand(summayIdx++)); + if (!format.has_value()) + return nullptr; + + FailureOr totalCount = convertInt64FromKeyValueTuple( + mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "TotalCount"); + if (failed(totalCount)) + return nullptr; + + FailureOr maxCount = convertInt64FromKeyValueTuple( + mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "MaxCount"); + if (failed(maxCount)) + return nullptr; + + FailureOr maxInternalCount = convertInt64FromKeyValueTuple( + mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), + "MaxInternalCount"); + if (failed(maxInternalCount)) + return nullptr; + + FailureOr maxFunctionCount = convertInt64FromKeyValueTuple( + mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), + "MaxFunctionCount"); + if (failed(maxFunctionCount)) + return nullptr; + + FailureOr numCounts = convertInt64FromKeyValueTuple( + mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "NumCounts"); + if (failed(numCounts)) + return nullptr; + + FailureOr numFunctions = convertInt64FromKeyValueTuple( + mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "NumFunctions"); + if (failed(numFunctions)) + return nullptr; + + // Handle optional keys. + FailureOr> isPartialProfile = + getOptIntValue(mdTuple->getOperand(summayIdx), "IsPartialProfile"); + if (failed(isPartialProfile)) + return nullptr; + if (isPartialProfile->has_value()) + summayIdx++; + + FailureOr partialProfileRatio = + getOptDoubleValue(mdTuple->getOperand(summayIdx), "PartialProfileRatio"); + if (failed(partialProfileRatio)) + return nullptr; + if (*partialProfileRatio) + summayIdx++; + + // Handle detailed summary. + FailureOr> detailed = + convertProfileSummaryDetailed(mlirModule, llvmModule, + mdTuple->getOperand(summayIdx)); + if (failed(detailed)) + return nullptr; + + // Build the final profile summary attribute. + return ModuleFlagProfileSummaryAttr::get( + mlirModule->getContext(), *format, *totalCount, *maxCount, + *maxInternalCount, *maxFunctionCount, *numCounts, *numFunctions, + *isPartialProfile, *partialProfileRatio, *detailed); +} + /// Invoke specific handlers for each known module flag value, returns nullptr /// if the key is unknown or unimplemented. -static Attribute convertModuleFlagValueFromMDTuple(ModuleOp mlirModule, - StringRef key, - llvm::MDTuple *mdTuple) { +static Attribute +convertModuleFlagValueFromMDTuple(ModuleOp mlirModule, + const llvm::Module *llvmModule, StringRef key, + llvm::MDTuple *mdTuple) { if (key == LLVMDialect::getModuleFlagKeyCGProfileName()) return convertCGProfileModuleFlagValue(mlirModule, mdTuple); + if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName()) + return convertProfileSummaryModuleFlagValue(mlirModule, llvmModule, + mdTuple); return nullptr; } @@ -576,8 +848,8 @@ LogicalResult ModuleImport::convertModuleFlagsMetadata() { } else if (auto *mdString = dyn_cast(val)) { valAttr = builder.getStringAttr(mdString->getString()); } else if (auto *mdTuple = dyn_cast(val)) { - valAttr = convertModuleFlagValueFromMDTuple(mlirModule, key->getString(), - mdTuple); + valAttr = convertModuleFlagValueFromMDTuple(mlirModule, llvmModule.get(), + key->getString(), mdTuple); } if (!valAttr) { diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir index 5dea94026b248..f9ea066a63624 100644 --- a/mlir/test/Dialect/LLVMIR/invalid.mlir +++ b/mlir/test/Dialect/LLVMIR/invalid.mlir @@ -1800,6 +1800,29 @@ module { // ----- +module { + // expected-error@below {{'ProfileSummary' key expects a '#llvm.profile_summary' attribute}} + llvm.module_flags [#llvm.mlir.module_flag] +} + +// ----- + +llvm.module_flags [#llvm.mlir.module_flag, + + // expected-error@below {{failed to parse ModuleFlagAttr parameter}} +>>] + +// ----- + llvm.func @t0() -> !llvm.ptr { %0 = llvm.blockaddress > : !llvm.ptr llvm.blocktag diff --git a/mlir/test/Dialect/LLVMIR/module-roundtrip.mlir b/mlir/test/Dialect/LLVMIR/module-roundtrip.mlir index 025d9b2287c42..85abd57df53c8 100644 --- a/mlir/test/Dialect/LLVMIR/module-roundtrip.mlir +++ b/mlir/test/Dialect/LLVMIR/module-roundtrip.mlir @@ -11,7 +11,17 @@ module { #llvm.cgprofile_entry, #llvm.cgprofile_entry, #llvm.cgprofile_entry - ]>] + ]>, + #llvm.mlir.module_flag, + + >>] } // CHECK: llvm.module_flags [ @@ -25,4 +35,14 @@ module { // CHECK-SAME: #llvm.cgprofile_entry, // CHECK-SAME: #llvm.cgprofile_entry, // CHECK-SAME: #llvm.cgprofile_entry -// CHECK-SAME: ]>] +// CHECK-SAME: ]>, +// CHECK-SAME: #llvm.mlir.module_flag, +// CHECK-SAME: +// CHECK-SAME: >>] diff --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll index 782925a0a938e..7571158a57d14 100644 --- a/mlir/test/Target/LLVMIR/Import/import-failure.ll +++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll @@ -348,3 +348,127 @@ define void @fn() { bb1: ret void } + +; // ----- + +!10 = !{ i32 1, !"foo", i32 1 } +!11 = !{ i32 4, !"bar", i32 37 } +!12 = !{ i32 2, !"qux", i32 42 } +; CHECK: unsupported module flag value for key 'qux' : !4 = !{!"foo", i32 1} +!13 = !{ i32 3, !"qux", !{ !"foo", i32 1 }} +!llvm.module.flags = !{ !10, !11, !12, !13 } + +; // ----- + +!llvm.module.flags = !{!41873} + +!41873 = !{i32 1, !"ProfileSummary", !41874} +!41874 = !{!41875, !41876, !41877, !41878, !41880, !41881, !41882, !41883, !41884} +!41875 = !{!"ProfileFormat", !"InstrProf"} +!41876 = !{!"TotalCount", i64 263646} +!41877 = !{!"MaxCount", i64 86427} +!41878 = !{!"MaxInternalCount", i64 86427} +; CHECK: expected 'MaxFunctionCount' key, but found: !"NumCounts" +!41880 = !{!"NumCounts", i64 3712} +!41881 = !{!"NumFunctions", i64 796} +!41882 = !{!"IsPartialProfile", i64 0} +!41883 = !{!"PartialProfileRatio", double 0.000000e+00} +!41884 = !{!"DetailedSummary", !41885} +!41885 = !{!41886, !41887} +!41886 = !{i32 10000, i64 86427, i32 1} +!41887 = !{i32 100000, i64 86427, i32 1} + +; // ----- + +!llvm.module.flags = !{!51873} + +!51873 = !{i32 1, !"ProfileSummary", !51874} +!51874 = !{!51875, !51876, !51877, !51878, !51879, !51880, !51881, !51882, !51883, !51884} +!51875 = !{!"ProfileFormat", !"InstrProf"} +!51876 = !{!"TotalCount", i64 263646} +!51877 = !{!"MaxCount", i64 86427} +!51878 = !{!"MaxInternalCount", i64 86427} +!51879 = !{!"MaxFunctionCount", i64 4691} +!51880 = !{!"NumCounts", i64 3712} +; CHECK: expected integer metadata value for key 'NumFunctions' +!51881 = !{!"NumFunctions", double 0.000000e+00} +!51882 = !{!"IsPartialProfile", i64 0} +!51883 = !{!"PartialProfileRatio", double 0.000000e+00} +!51884 = !{!"DetailedSummary", !51885} +!51885 = !{!51886, !51887} +!51886 = !{i32 10000, i64 86427, i32 1} +!51887 = !{i32 100000, i64 86427, i32 1} + +; // ----- + +!llvm.module.flags = !{!61873} + +!61873 = !{i32 1, !"ProfileSummary", !61874} +!61874 = !{!61875, !61876, !61877, !61878, !61879, !61880, !61881, !61882, !61883, !61884} +; CHECK: expected 'SampleProfile', 'InstrProf' or 'CSInstrProf' values, but found: !"MyThingyFmt" +!61875 = !{!"ProfileFormat", !"MyThingyFmt"} +!61876 = !{!"TotalCount", i64 263646} +!61877 = !{!"MaxCount", i64 86427} +!61878 = !{!"MaxInternalCount", i64 86427} +!61879 = !{!"MaxFunctionCount", i64 4691} +!61880 = !{!"NumCounts", i64 3712} +!61881 = !{!"NumFunctions", i64 796} +!61882 = !{!"IsPartialProfile", i64 0} +!61883 = !{!"PartialProfileRatio", double 0.000000e+00} +!61884 = !{!"DetailedSummary", !61885} +!61885 = !{!61886, !61887} +!61886 = !{i32 10000, i64 86427, i32 1} +!61887 = !{i32 100000, i64 86427, i32 1} + +; // ----- + +!llvm.module.flags = !{!71873} + +!71873 = !{i32 1, !"ProfileSummary", !71874} +!71874 = !{!71875, !71876, !71877, !71878, !71879, !71880, !71881, !71882, !71883} +!71875 = !{!"ProfileFormat", !"InstrProf"} +!71876 = !{!"TotalCount", i64 263646} +!71877 = !{!"MaxCount", i64 86427} +!71878 = !{!"MaxInternalCount", i64 86427} +!71879 = !{!"MaxFunctionCount", i64 4691} +!71880 = !{!"NumCounts", i64 3712} +!71881 = !{!"NumFunctions", i64 796} +!71882 = !{!"IsPartialProfile", i64 0} +; CHECK: the last summary entry is 'PartialProfileRatio', expected 'DetailedSummary' +!71883 = !{!"PartialProfileRatio", double 0.000000e+00} + +; // ----- + +!llvm.module.flags = !{!81873} + +!81873 = !{i32 1, !"ProfileSummary", !81874} +; CHECK: expected at 8 entries in 'ProfileSummary' +!81874 = !{!81875, !81876, !81877, !81878, !81879, !81880, !81881} +!81875 = !{!"ProfileFormat", !"InstrProf"} +!81876 = !{!"TotalCount", i64 263646} +!81877 = !{!"MaxCount", i64 86427} +!81878 = !{!"MaxInternalCount", i64 86427} +!81879 = !{!"MaxFunctionCount", i64 4691} +!81880 = !{!"NumCounts", i64 3812} +!81881 = !{!"NumFunctions", i64 796} + +; // ----- + +!llvm.module.flags = !{!91873} + +!91873 = !{i32 1, !"ProfileSummary", !91874} +!91874 = !{!91875, !91876, !91877, !91878, !91879, !91880, !91881, !91882, !91883, !91884} +!91875 = !{!"ProfileFormat", !"InstrProf"} +; CHECK: expected 2-element tuple metadata +!91876 = !{!"TotalCount", i64 263646, i64 263646} +!91877 = !{!"MaxCount", i64 86427} +!91878 = !{!"MaxInternalCount", i64 86427} +!91879 = !{!"MaxFunctionCount", i64 4691} +!91880 = !{!"NumCounts", i64 3712} +!91881 = !{!"NumFunctions", i64 796} +!91882 = !{!"IsPartialProfile", i64 0} +!91883 = !{!"PartialProfileRatio", double 0.000000e+00} +!91884 = !{!"DetailedSummary", !91885} +!91885 = !{!91886, !91887} +!91886 = !{i32 10000, i64 86427, i32 1} +!91887 = !{i32 100000, i64 86427, i32 1} diff --git a/mlir/test/Target/LLVMIR/Import/module-flags.ll b/mlir/test/Target/LLVMIR/Import/module-flags.ll index 09e708de0cc93..725bd14deb651 100644 --- a/mlir/test/Target/LLVMIR/Import/module-flags.ll +++ b/mlir/test/Target/LLVMIR/Import/module-flags.ll @@ -18,14 +18,6 @@ ; CHECK-SAME: #llvm.mlir.module_flag, ; CHECK-SAME: #llvm.mlir.module_flag] -; // ----- -; expected-warning@-2 {{unsupported module flag value for key 'qux' : !4 = !{!"foo", i32 1}}} -!10 = !{ i32 1, !"foo", i32 1 } -!11 = !{ i32 4, !"bar", i32 37 } -!12 = !{ i32 2, !"qux", i32 42 } -!13 = !{ i32 3, !"qux", !{ !"foo", i32 1 }} -!llvm.module.flags = !{ !10, !11, !12, !13 } - ; // ----- declare void @from(i32) @@ -44,3 +36,62 @@ declare void @to() ; CHECK-SAME: #llvm.cgprofile_entry, ; CHECK-SAME: #llvm.cgprofile_entry ; CHECK-SAME: ]>] + +; // ----- + +!llvm.module.flags = !{!31873} + +!31873 = !{i32 1, !"ProfileSummary", !31874} +!31874 = !{!31875, !31876, !31877, !31878, !31879, !31880, !31881, !31882, !31883, !31884} +!31875 = !{!"ProfileFormat", !"InstrProf"} +!31876 = !{!"TotalCount", i64 263646} +!31877 = !{!"MaxCount", i64 86427} +!31878 = !{!"MaxInternalCount", i64 86427} +!31879 = !{!"MaxFunctionCount", i64 4691} +!31880 = !{!"NumCounts", i64 3712} +!31881 = !{!"NumFunctions", i64 796} +!31882 = !{!"IsPartialProfile", i64 0} +!31883 = !{!"PartialProfileRatio", double 0.000000e+00} +!31884 = !{!"DetailedSummary", !31885} +!31885 = !{!31886, !31887} +!31886 = !{i32 10000, i64 86427, i32 1} +!31887 = !{i32 100000, i64 86427, i32 1} + +; CHECK: llvm.module_flags [#llvm.mlir.module_flag, +; CHECK-SAME: +; CHECK-SAME: >>] + +; // ----- + +; Test optional fields + +!llvm.module.flags = !{!41873} + +!41873 = !{i32 1, !"ProfileSummary", !41874} +!41874 = !{!41875, !41876, !41877, !41878, !41879, !41880, !41881, !41884} +!41875 = !{!"ProfileFormat", !"InstrProf"} +!41876 = !{!"TotalCount", i64 263646} +!41877 = !{!"MaxCount", i64 86427} +!41878 = !{!"MaxInternalCount", i64 86427} +!41879 = !{!"MaxFunctionCount", i64 4691} +!41880 = !{!"NumCounts", i64 3712} +!41881 = !{!"NumFunctions", i64 796} +!41884 = !{!"DetailedSummary", !41885} +!41885 = !{!41886, !41887} +!41886 = !{i32 10000, i64 86427, i32 1} +!41887 = !{i32 100000, i64 86427, i32 1} + +; CHECK: llvm.module_flags [#llvm.mlir.module_flag, +; CHECK-SAME: +; CHECK-SAME: >>] diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir index 9852c4051f0d0..854034f3ec243 100644 --- a/mlir/test/Target/LLVMIR/llvmir.mlir +++ b/mlir/test/Target/LLVMIR/llvmir.mlir @@ -2883,6 +2883,37 @@ llvm.func @to() // ----- +llvm.module_flags [#llvm.mlir.module_flag, + + >>] + +// CHECK: !llvm.module.flags = !{![[#PSUM:]], {{.*}}} + +// CHECK: ![[#PSUM]] = !{i32 1, !"ProfileSummary", ![[#SUMLIST:]]} +// CHECK: ![[#SUMLIST]] = !{![[#FMT:]], ![[#TC:]], ![[#MC:]], ![[#MIC:]], ![[#MFC:]], ![[#NC:]], ![[#NF:]], ![[#IPP:]], ![[#PPR:]], ![[#DS:]]} +// CHECK: ![[#FMT]] = !{!"ProfileFormat", !"InstrProf"} +// CHECK: ![[#TC]] = !{!"TotalCount", i64 263646} +// CHECK: ![[#MC]] = !{!"MaxCount", i64 86427} +// CHECK: ![[#MIC]] = !{!"MaxInternalCount", i64 86427} +// CHECK: ![[#MFC]] = !{!"MaxFunctionCount", i64 4691} +// CHECK: ![[#NC]] = !{!"NumCounts", i64 3712} +// CHECK: ![[#NF]] = !{!"NumFunctions", i64 796} +// CHECK: ![[#IPP]] = !{!"IsPartialProfile", i64 0} +// CHECK: ![[#PPR]] = !{!"PartialProfileRatio", double 0.000000e+00} +// CHECK: ![[#DS]] = !{!"DetailedSummary", ![[#DETAILED:]]} +// CHECK: ![[#DETAILED]] = !{![[#DS0:]], ![[#DS1:]]} +// CHECK: ![[#DS0:]] = !{i64 10000, i64 86427, i64 1} +// CHECK: ![[#DS1:]] = !{i64 100000, i64 86427, i64 1} + +// ----- + module attributes {llvm.dependent_libraries = ["foo", "bar"]} {} // CHECK: !llvm.dependent-libraries = !{![[#LIBFOO:]], ![[#LIBBAR:]]}