From: River Riddle Date: Tue, 29 Nov 2022 02:35:00 +0000 (-0800) Subject: [mlir] Cleanup lingering problems surrounding attribute/type aliases X-Git-Tag: upstream/17.0.6~25789 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=aef89c8b41847c7235e00fbf8b2a2f10cb1aad25;p=platform%2Fupstream%2Fllvm.git [mlir] Cleanup lingering problems surrounding attribute/type aliases This commit refactors attribute/type alias generation to be similar to how we do it for operations, i.e. we generate aliases determined on what is actually necessary when printing the IR (using a dummy printer for alias collection). This allows for generating aliases only when necessary, and also allows for proper propagation of when a nested alias can be deferred. This also necessitated a fix for location parsing to actually parse aliases instead of ignoring them. Fixes #59041 Differential Revision: https://reviews.llvm.org/D138886 --- diff --git a/mlir/include/mlir/IR/OpImplementation.h b/mlir/include/mlir/IR/OpImplementation.h index c6e5abd..e517794 100644 --- a/mlir/include/mlir/IR/OpImplementation.h +++ b/mlir/include/mlir/IR/OpImplementation.h @@ -181,7 +181,7 @@ public: virtual void printSymbolName(StringRef symbolRef); /// Print a handle to the given dialect resource. - void printResourceHandle(const AsmDialectResourceHandle &resource); + virtual void printResourceHandle(const AsmDialectResourceHandle &resource); /// Print an optional arrow followed by a type list. template diff --git a/mlir/lib/AsmParser/LocationParser.cpp b/mlir/lib/AsmParser/LocationParser.cpp index cf1e8af..02cb3ed 100644 --- a/mlir/lib/AsmParser/LocationParser.cpp +++ b/mlir/lib/AsmParser/LocationParser.cpp @@ -149,6 +149,16 @@ ParseResult Parser::parseNameOrFileLineColLocation(LocationAttr &loc) { } ParseResult Parser::parseLocationInstance(LocationAttr &loc) { + // Handle aliases. + if (getToken().is(Token::hash_identifier)) { + Attribute locAttr = parseExtendedAttr(Type()); + if (!locAttr) + return failure(); + if (!(loc = dyn_cast(locAttr))) + return emitError("expected location attribute, but got") << locAttr; + return success(); + } + // Handle either name or filelinecol locations. if (getToken().is(Token::string)) return parseNameOrFileLineColLocation(loc); diff --git a/mlir/lib/IR/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp index c06e96d..f1d5b7b 100644 --- a/mlir/lib/IR/AsmPrinter.cpp +++ b/mlir/lib/IR/AsmPrinter.cpp @@ -389,7 +389,8 @@ protected: bool withKeyword = false); void printNamedAttribute(NamedAttribute attr); void printTrailingLocation(Location loc, bool allowAlias = true); - void printLocationInternal(LocationAttr loc, bool pretty = false); + void printLocationInternal(LocationAttr loc, bool pretty = false, + bool isTopLevel = false); /// Print a dense elements attribute. If 'allowHex' is true, a hex string is /// used instead of individual elements when the elements attr is large. @@ -495,14 +496,21 @@ public: /// Visit the given attribute to see if it has an alias. `canBeDeferred` is /// set to true if the originator of this attribute can resolve the alias /// after parsing has completed (e.g. in the case of operation locations). - /// Returns the maximum alias depth of the attribute. - size_t visit(Attribute attr, bool canBeDeferred = false) { - return visitImpl(attr, aliases, canBeDeferred); + /// `elideType` indicates if the type of the attribute should be skipped when + /// looking for nested aliases. Returns the maximum alias depth of the + /// attribute, and the alias index of this attribute. + std::pair visit(Attribute attr, bool canBeDeferred = false, + bool elideType = false) { + return visitImpl(attr, aliases, canBeDeferred, elideType); } - /// Visit the given type to see if it has an alias. Returns the maximum alias - /// depth of the type. - size_t visit(Type type) { return visitImpl(type, aliases); } + /// Visit the given type to see if it has an alias. `canBeDeferred` is + /// set to true if the originator of this attribute can resolve the alias + /// after parsing has completed. Returns the maximum alias depth of the type, + /// and the alias index of this type. + std::pair visit(Type type, bool canBeDeferred = false) { + return visitImpl(type, aliases, canBeDeferred); + } private: struct InProgressAliasInfo { @@ -530,16 +538,23 @@ private: bool isType : 1; /// If this alias can be deferred or not. bool canBeDeferred : 1; + /// Indices for child aliases. + SmallVector childIndices; }; /// Visit the given attribute or type to see if it has an alias. /// `canBeDeferred` is set to true if the originator of this value can resolve /// the alias after parsing has completed (e.g. in the case of operation - /// locations). Returns the maximum alias depth of the value. - template - size_t visitImpl(T value, - llvm::MapVector &aliases, - bool canBeDeferred = false); + /// locations). Returns the maximum alias depth of the value, and its alias + /// index. + template + std::pair + visitImpl(T value, + llvm::MapVector &aliases, + bool canBeDeferred, PrintArgs &&...printArgs); + + /// Mark the given alias as non-deferrable. + void markAliasNonDeferrable(size_t aliasIndex); /// Try to generate an alias for the provided symbol. If an alias is /// generated, the provided alias mapping and reverse mapping are updated. @@ -722,7 +737,7 @@ private: /// The following are hooks of `OpAsmPrinter` that are not necessary for /// determining potential aliases. - void printFloat(const APFloat &value) override {} + void printFloat(const APFloat &) override {} void printAffineMapOfSSAIds(AffineMapAttr, ValueRange) override {} void printAffineExprOfSSAIds(AffineExpr, ValueRange, ValueRange) override {} void printNewline() override {} @@ -736,6 +751,7 @@ private: os << "%"; } void printKeywordOrString(StringRef) override {} + void printResourceHandle(const AsmDialectResourceHandle &) override {} void printSymbolName(StringRef) override {} void printSuccessor(Block *) override {} void printSuccessorAndUseList(Block *, ValueRange) override {} @@ -750,6 +766,149 @@ private: /// A dummy output stream. mutable llvm::raw_null_ostream os; }; + +class DummyAliasDialectAsmPrinter : public DialectAsmPrinter { +public: + explicit DummyAliasDialectAsmPrinter(AliasInitializer &initializer, + bool canBeDeferred, + SmallVectorImpl &childIndices) + : initializer(initializer), canBeDeferred(canBeDeferred), + childIndices(childIndices) {} + + /// Print the given attribute/type, visiting any nested aliases that would be + /// generated as part of printing. Returns the maximum alias depth found while + /// printing the given value. + template + size_t printAndVisitNestedAliases(T value, PrintArgs &&...printArgs) { + printAndVisitNestedAliasesImpl(value, printArgs...); + return maxAliasDepth; + } + +private: + /// Print the given attribute/type, visiting any nested aliases that would be + /// generated as part of printing. + void printAndVisitNestedAliasesImpl(Attribute attr, bool elideType) { + if (!isa(attr.getDialect())) + return attr.getDialect().printAttribute(attr, *this); + + // Process the builtin attributes. + if (attr.isa()) + return; + if (auto dictAttr = dyn_cast(attr)) { + for (const NamedAttribute &nestedAttr : dictAttr.getValue()) { + printAttribute(nestedAttr.getName()); + printAttribute(nestedAttr.getValue()); + } + } else if (auto arrayAttr = dyn_cast(attr)) { + for (Attribute nestedAttr : arrayAttr.getValue()) + printAttribute(nestedAttr); + } else if (auto typeAttr = dyn_cast(attr)) { + printType(typeAttr.getValue()); + } else if (auto locAttr = dyn_cast(attr)) { + printAttribute(locAttr.getFallbackLocation()); + } else if (auto locAttr = dyn_cast(attr)) { + if (!isa(locAttr.getChildLoc())) + printAttribute(locAttr.getChildLoc()); + } else if (auto locAttr = dyn_cast(attr)) { + printAttribute(locAttr.getCallee()); + printAttribute(locAttr.getCaller()); + } else if (auto locAttr = dyn_cast(attr)) { + if (Attribute metadata = locAttr.getMetadata()) + printAttribute(metadata); + for (Location nestedLoc : locAttr.getLocations()) + printAttribute(nestedLoc); + } + + // Don't print the type if we must elide it, or if it is a None type. + if (!elideType) { + if (auto typedAttr = attr.dyn_cast()) { + Type attrType = typedAttr.getType(); + if (!attrType.isa()) + printType(attrType); + } + } + } + void printAndVisitNestedAliasesImpl(Type type) { + if (!isa(type.getDialect())) + return type.getDialect().printType(type, *this); + + // Only visit the layout of memref if it isn't the identity. + if (auto memrefTy = type.dyn_cast()) { + printType(memrefTy.getElementType()); + MemRefLayoutAttrInterface layout = memrefTy.getLayout(); + if (!layout.isa() || !layout.isIdentity()) + printAttribute(memrefTy.getLayout()); + if (memrefTy.getMemorySpace()) + printAttribute(memrefTy.getMemorySpace()); + return; + } + + // For most builtin types, we can simply walk the sub elements. + if (auto subElementInterface = dyn_cast(type)) { + auto visitFn = [&](auto element) { + if (element) + (void)printAlias(element); + }; + subElementInterface.walkImmediateSubElements(visitFn, visitFn); + } + } + + /// Consider the given type to be printed for an alias. + void printType(Type type) override { + recordAliasResult(initializer.visit(type, canBeDeferred)); + } + + /// Consider the given attribute to be printed for an alias. + void printAttribute(Attribute attr) override { + recordAliasResult(initializer.visit(attr, canBeDeferred)); + } + void printAttributeWithoutType(Attribute attr) override { + recordAliasResult( + initializer.visit(attr, canBeDeferred, /*elideType=*/true)); + } + LogicalResult printAlias(Attribute attr) override { + printAttribute(attr); + return success(); + } + LogicalResult printAlias(Type type) override { + printType(type); + return success(); + } + + /// Record the alias result of a child element. + void recordAliasResult(std::pair aliasDepthAndIndex) { + childIndices.push_back(aliasDepthAndIndex.second); + if (aliasDepthAndIndex.first > maxAliasDepth) + maxAliasDepth = aliasDepthAndIndex.first; + } + + /// Return a null stream as the output stream, this will ignore any data fed + /// to it. + raw_ostream &getStream() const override { return os; } + + /// The following are hooks of `DialectAsmPrinter` that are not necessary for + /// determining potential aliases. + void printFloat(const APFloat &) override {} + void printKeywordOrString(StringRef) override {} + void printSymbolName(StringRef) override {} + void printResourceHandle(const AsmDialectResourceHandle &) override {} + + /// The initializer to use when identifying aliases. + AliasInitializer &initializer; + + /// If the aliases visited by this printer can be deferred. + bool canBeDeferred; + + /// The indices of child aliases. + SmallVectorImpl &childIndices; + + /// The maximum alias depth found by the printer. + size_t maxAliasDepth = 0; + + /// A dummy output stream. + mutable llvm::raw_null_ostream os; +}; } // namespace /// Sanitize the given name such that it can be used as a valid identifier. If @@ -836,48 +995,48 @@ void AliasInitializer::initialize( initializeAliases(aliases, attrTypeToAlias); } -template -size_t AliasInitializer::visitImpl( +template +std::pair AliasInitializer::visitImpl( T value, llvm::MapVector &aliases, - bool canBeDeferred) { + bool canBeDeferred, PrintArgs &&...printArgs) { auto [it, inserted] = aliases.insert({value.getAsOpaquePointer(), InProgressAliasInfo()}); + size_t aliasIndex = std::distance(aliases.begin(), it); if (!inserted) { // Make sure that the alias isn't deferred if we don't permit it. if (!canBeDeferred) - it->second.canBeDeferred = false; - return it->second.aliasDepth; + markAliasNonDeferrable(aliasIndex); + return {static_cast(it->second.aliasDepth), aliasIndex}; } - // Try to generate an alias for this attribute. + // Try to generate an alias for this value. generateAlias(value, it->second, canBeDeferred); - size_t aliasIndex = std::distance(aliases.begin(), it); - // Check for any sub elements. - using SubElementInterfaceT = - std::conditional_t, SubElementTypeInterface, - SubElementAttrInterface>; - if (auto subElementInterface = dyn_cast(value)) { - size_t maxAliasDepth = 0; - auto visitSubElement = [&](auto element) { - if (!element) - return; - if (size_t depth = visit(element)) - maxAliasDepth = std::max(maxAliasDepth, depth + 1); - }; - subElementInterface.walkImmediateSubElements(visitSubElement, - visitSubElement); + // Print the value, capturing any nested elements that require aliases. + SmallVector childAliases; + DummyAliasDialectAsmPrinter printer(*this, canBeDeferred, childAliases); + size_t maxAliasDepth = + printer.printAndVisitNestedAliases(value, printArgs...); - // Make sure to recompute `it` in case the map was reallocated. - it = std::next(aliases.begin(), aliasIndex); + // Make sure to recompute `it` in case the map was reallocated. + it = std::next(aliases.begin(), aliasIndex); - // If we had sub elements, update to account for the depth. - if (maxAliasDepth) - it->second.aliasDepth = maxAliasDepth; - } + // If we had sub elements, update to account for the depth. + it->second.childIndices = std::move(childAliases); + if (maxAliasDepth) + it->second.aliasDepth = maxAliasDepth + 1; // Propagate the alias depth of the value. - return it->second.aliasDepth; + return {(size_t)it->second.aliasDepth, aliasIndex}; +} + +void AliasInitializer::markAliasNonDeferrable(size_t aliasIndex) { + auto it = std::next(aliases.begin(), aliasIndex); + it->second.canBeDeferred = false; + + // Propagate the non-deferrable flag to any child aliases. + for (size_t childIndex : it->second.childIndices) + markAliasNonDeferrable(childIndex); } template @@ -1681,7 +1840,12 @@ void AsmPrinter::Impl::printTrailingLocation(Location loc, bool allowAlias) { printLocation(loc, /*allowAlias=*/allowAlias); } -void AsmPrinter::Impl::printLocationInternal(LocationAttr loc, bool pretty) { +void AsmPrinter::Impl::printLocationInternal(LocationAttr loc, bool pretty, + bool isTopLevel) { + // If this isn't a top-level location, check for an alias. + if (!isTopLevel && succeeded(state.getAliasState().getAlias(loc, os))) + return; + TypeSwitch(loc) .Case([&](OpaqueLoc loc) { printLocationInternal(loc.getFallbackLocation(), pretty); @@ -1802,11 +1966,11 @@ static void printFloatValue(const APFloat &apValue, raw_ostream &os) { void AsmPrinter::Impl::printLocation(LocationAttr loc, bool allowAlias) { if (printerFlags.shouldPrintDebugInfoPrettyForm()) - return printLocationInternal(loc, /*pretty=*/true); + return printLocationInternal(loc, /*pretty=*/true, /*isTopLevel=*/true); os << "loc("; if (!allowAlias || failed(printAlias(loc))) - printLocationInternal(loc); + printLocationInternal(loc, /*pretty=*/false, /*isTopLevel=*/true); os << ')'; } diff --git a/mlir/test/Dialect/DLTI/roundtrip.mlir b/mlir/test/Dialect/DLTI/roundtrip.mlir index ec66bae..613dc354 100644 --- a/mlir/test/Dialect/DLTI/roundtrip.mlir +++ b/mlir/test/Dialect/DLTI/roundtrip.mlir @@ -2,10 +2,12 @@ // Round-tripping the syntax. +// CHECK: #[[MAP:.*]] = affine_map<(d0) -> (d0)> + "test.unknown_op"() { // CHECK: #dlti.dl_entry<"test.identifier", 42 : i64> test.unknown_attr_1 = #dlti.dl_entry<"test.identifier", 42 : i64>, - // CHECK: #dlti.dl_entry<"test.identifier", affine_map<(d0) -> (d0)>> + // CHECK: #dlti.dl_entry<"test.identifier", #[[MAP]]> test.unknown_attr_2 = #dlti.dl_entry<"test.identifier", affine_map<(d0) -> (d0)>>, // CHECK: #dlti.dl_entry test.unknown_attr_3 = #dlti.dl_entry, diff --git a/mlir/test/Dialect/SparseTensor/sparse_vector_chain.mlir b/mlir/test/Dialect/SparseTensor/sparse_vector_chain.mlir index 612927c..824fd40 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_vector_chain.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_vector_chain.mlir @@ -84,7 +84,7 @@ // CHECK: } attributes {"Emitted from" = "linalg.generic"} // CHECK: %[[VAL_59:.*]] = vector.insertelement %[[VAL_60:.*]]#2, %[[VAL_4]]{{\[}}%[[VAL_6]] : index] : vector<8xf64> // CHECK: %[[VAL_61:.*]] = scf.for %[[VAL_62:.*]] = %[[VAL_60]]#0 to %[[VAL_21]] step %[[VAL_3]] iter_args(%[[VAL_63:.*]] = %[[VAL_59]]) -> (vector<8xf64>) { -// CHECK: %[[VAL_64:.*]] = affine.min #map2(%[[VAL_21]], %[[VAL_62]]){{\[}}%[[VAL_3]]] +// CHECK: %[[VAL_64:.*]] = affine.min #map(%[[VAL_21]], %[[VAL_62]]){{\[}}%[[VAL_3]]] // CHECK: %[[VAL_65:.*]] = vector.create_mask %[[VAL_64]] : vector<8xi1> // CHECK: %[[VAL_66:.*]] = vector.maskedload %[[VAL_10]]{{\[}}%[[VAL_62]]], %[[VAL_65]], %[[VAL_4]] : memref, vector<8xi1>, vector<8xf64> into vector<8xf64> // CHECK: %[[VAL_67:.*]] = arith.addf %[[VAL_63]], %[[VAL_66]] : vector<8xf64> @@ -92,7 +92,7 @@ // CHECK: scf.yield %[[VAL_68]] : vector<8xf64> // CHECK: } {"Emitted from" = "linalg.generic"} // CHECK: %[[VAL_69:.*]] = scf.for %[[VAL_70:.*]] = %[[VAL_60]]#1 to %[[VAL_23]] step %[[VAL_3]] iter_args(%[[VAL_71:.*]] = %[[VAL_61]]) -> (vector<8xf64>) { -// CHECK: %[[VAL_73:.*]] = affine.min #map2(%[[VAL_23]], %[[VAL_70]]){{\[}}%[[VAL_3]]] +// CHECK: %[[VAL_73:.*]] = affine.min #map(%[[VAL_23]], %[[VAL_70]]){{\[}}%[[VAL_3]]] // CHECK: %[[VAL_74:.*]] = vector.create_mask %[[VAL_73]] : vector<8xi1> // CHECK: %[[VAL_75:.*]] = vector.maskedload %[[VAL_13]]{{\[}}%[[VAL_70]]], %[[VAL_74]], %[[VAL_4]] : memref, vector<8xi1>, vector<8xf64> into vector<8xf64> // CHECK: %[[VAL_76:.*]] = arith.addf %[[VAL_71]], %[[VAL_75]] : vector<8xf64> diff --git a/mlir/test/Dialect/SparseTensor/sparse_vector_index.mlir b/mlir/test/Dialect/SparseTensor/sparse_vector_index.mlir index 37d5b80..7bb8254 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_vector_index.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_vector_index.mlir @@ -33,7 +33,7 @@ // CHECK: %[[VAL_12:.*]] = memref.load %[[VAL_8]]{{\[}}%[[VAL_5]]] : memref // CHECK: %[[VAL_13:.*]] = memref.load %[[VAL_8]]{{\[}}%[[VAL_6]]] : memref // CHECK: scf.for %[[VAL_14:.*]] = %[[VAL_12]] to %[[VAL_13]] step %[[VAL_1]] { -// CHECK: %[[VAL_15:.*]] = affine.min #map1(%[[VAL_13]], %[[VAL_14]]){{\[}}%[[VAL_1]]] +// CHECK: %[[VAL_15:.*]] = affine.min #map(%[[VAL_13]], %[[VAL_14]]){{\[}}%[[VAL_1]]] // CHECK: %[[VAL_16:.*]] = vector.create_mask %[[VAL_15]] : vector<8xi1> // CHECK: %[[VAL_17:.*]] = vector.maskedload %[[VAL_9]]{{\[}}%[[VAL_14]]], %[[VAL_16]], %[[VAL_3]] : memref, vector<8xi1>, vector<8xindex> into vector<8xindex> // CHECK: %[[VAL_18:.*]] = vector.maskedload %[[VAL_10]]{{\[}}%[[VAL_14]]], %[[VAL_16]], %[[VAL_2]] : memref, vector<8xi1>, vector<8xi64> into vector<8xi64> @@ -99,7 +99,7 @@ func.func @sparse_index_1d_conj(%arga: tensor<8xi64, #SparseVector>) -> tensor<8 // CHECK: scf.yield %[[VAL_27]], %[[VAL_28]] : index, index // CHECK: } attributes {"Emitted from" = "linalg.generic"} // CHECK: scf.for %[[VAL_29:.*]] = %[[VAL_30:.*]]#1 to %[[VAL_1]] step %[[VAL_1]] { -// CHECK: %[[VAL_31:.*]] = affine.min #map1(%[[VAL_1]], %[[VAL_29]]){{\[}}%[[VAL_1]]] +// CHECK: %[[VAL_31:.*]] = affine.min #map(%[[VAL_1]], %[[VAL_29]]){{\[}}%[[VAL_1]]] // CHECK: %[[VAL_32:.*]] = vector.create_mask %[[VAL_31]] : vector<8xi1> // CHECK: %[[VAL_33:.*]] = vector.broadcast %[[VAL_29]] : index to vector<8xindex> // CHECK: %[[VAL_34:.*]] = arith.addi %[[VAL_33]], %[[VAL_2]] : vector<8xindex> diff --git a/mlir/test/IR/pretty-locations.mlir b/mlir/test/IR/pretty-locations.mlir index f3feb60..e9337b5 100644 --- a/mlir/test/IR/pretty-locations.mlir +++ b/mlir/test/IR/pretty-locations.mlir @@ -1,4 +1,4 @@ -// RUN: mlir-opt -allow-unregistered-dialect %s -mlir-print-debuginfo -mlir-pretty-debuginfo | FileCheck %s +// RUN: mlir-opt -allow-unregistered-dialect %s -mlir-print-debuginfo -mlir-pretty-debuginfo -mlir-print-local-scope | FileCheck %s #set0 = affine_set<(d0) : (1 == 0)> diff --git a/mlir/test/IR/print-attr-type-aliases.mlir b/mlir/test/IR/print-attr-type-aliases.mlir index b9893f2..b1631b2 100644 --- a/mlir/test/IR/print-attr-type-aliases.mlir +++ b/mlir/test/IR/print-attr-type-aliases.mlir @@ -29,8 +29,9 @@ // CHECK-DAG: tensor<32x!test_ui8_> "test.op"() : () -> tensor<32x!test.int> -// CHECK-DAG: #loc2 = loc("nested") -// CHECK-DAG: #loc3 = loc(fused<#loc2>["test.mlir":10:8]) +// CHECK-DAG: #loc = loc("nested") +// CHECK-DAG: #loc1 = loc("test.mlir":10:8) +// CHECK-DAG: #loc2 = loc(fused<#loc>[#loc1]) "test.op"() {alias_test = loc(fused["test.mlir":10:8])} : () -> () // ----- @@ -39,3 +40,10 @@ // CHECK: !tuple = tuple< // CHECK: #loc1 = loc(fused>["test.mlir":10:8])} : () -> () + +// ----- + +// Check that we don't print aliases for things that aren't printed. +// CHECK: #loc1 = loc(fused +// CHECK-NOT: #map +"test.op"() {alias_test = loc(fused (d0)>>>["test.mlir":10:8])} : () -> () diff --git a/mlir/test/Target/LLVMIR/Import/debug-info.ll b/mlir/test/Target/LLVMIR/Import/debug-info.ll index 415b40c..f7513d5 100644 --- a/mlir/test/Target/LLVMIR/Import/debug-info.ll +++ b/mlir/test/Target/LLVMIR/Import/debug-info.ll @@ -1,6 +1,5 @@ ; RUN: mlir-translate -import-llvm -mlir-print-debuginfo -split-input-file %s | FileCheck %s -; CHECK: #[[$UNKNOWNLOC:.+]] = loc(unknown) ; CHECK-LABEL: @unknown( define i32 @unknown(i32 %0) { entry: @@ -10,28 +9,35 @@ end: %1 = phi i32 [ %2, %next ] ret i32 %1 next: - ; CHECK: = llvm.mul %{{.+}}, %{{.+}} : i32 loc(#[[$UNKNOWNLOC:.+]]) + ; CHECK: = llvm.mul %{{.+}}, %{{.+}} : i32 loc(#[[UNKNOWNLOC:.+]]) %2 = mul i32 %0, %0 br label %end } -; // ----- +; CHECK: #[[UNKNOWNLOC:.+]] = loc(unknown) -; CHECK: #[[$SP:.+]] = #llvm.di_subprogram["debug-info.ll":1:2]) -; CHECK #[[CALLSITE_LOC]] = loc(fused<#[[$CALLEE]]>[callsite("debug-info.ll":7:4 at fused<#[[$SP]]>["debug-info.ll":2:2])]) + +; CHECK-DAG: #[[RAW_FILE_LOC:.+]] = loc("debug-info.ll":1:2) +; CHECK-DAG: #[[SP:.+]] = #llvm.di_subprogram[#[[RAW_FILE_LOC]]]) +; CHECK-DAG: #[[CALLEE_LOC:.+]] = loc("debug-info.ll":7:4) +; CHECK-DAG: #[[RAW_CALLER_LOC:.+]] = loc("debug-info.ll":2:2) +; CHECK-DAG: #[[CALLER_LOC:.+]] = loc(fused<#[[SP]]>[#[[RAW_CALLER_LOC]]]) +; CHECK-DAG: #[[RAW_CALLSITE_LOC:.+]] = loc(callsite(#[[CALLEE_LOC]] at #[[CALLER_LOC]])) +; CHECK-DAG: #[[CALLSITE_LOC]] = loc(fused<#[[CALLEE]]>[#[[RAW_CALLSITE_LOC]]]) !llvm.dbg.cu = !{!1} !llvm.module.flags = !{!0} @@ -46,23 +52,22 @@ define i32 @instruction_loc(i32 %arg1) { ; // ----- -; CHECK: #[[FILE:.+]] = #llvm.di_file<"debug-info.ll" in "/"> -; CHECK: #[[SP:.+]] = #llvm.di_subprogram -; CHECK: #[[$LB1:.+]] = #llvm.di_lexical_block - ; CHECK-LABEL: @lexical_block define i32 @lexical_block(i32 %arg1) { - ; CHECK llvm.add {{.*}} loc(#[[LOC0:.*]]) + ; CHECK: llvm.add {{.*}} loc(#[[LOC0:.*]]) %1 = add i32 %arg1, %arg1, !dbg !6 - ; CHECK llvm.mul {{.*}} loc(#[[LOC1:.*]]) + ; CHECK: llvm.mul {{.*}} loc(#[[LOC1:.*]]) %2 = mul i32 %arg1, %arg1, !dbg !7 ret i32 %2 } -; CHECK #[[LOC0]] = loc(fused<#[[$LB0]]>["debug-info.ll":1:2]) -; CHECK #[[LOC1]] = loc(fused<#[[$LB1]]>["debug-info.ll":1:2]) +; CHECK: #[[FILE:.+]] = #llvm.di_file<"debug-info.ll" in "/"> +; CHECK: #[[SP:.+]] = #llvm.di_subprogram +; CHECK: #[[LB1:.+]] = #llvm.di_lexical_block +; CHECK: #[[LOC0]] = loc(fused<#[[LB0]]>[{{.*}}]) +; CHECK: #[[LOC1]] = loc(fused<#[[LB1]]>[{{.*}}]) !llvm.dbg.cu = !{!1} !llvm.module.flags = !{!0} @@ -77,23 +82,22 @@ define i32 @lexical_block(i32 %arg1) { ; // ----- -; CHECK: #[[FILE:.+]] = #llvm.di_file<"debug-info.ll" in "/"> -; CHECK: #[[SP:.+]] = #llvm.di_subprogram -; CHECK: #[[$LB1:.+]] = #llvm.di_lexical_block_file - ; CHECK-LABEL: @lexical_block_file define i32 @lexical_block_file(i32 %arg1) { - ; CHECK llvm.add {{.*}} loc(#[[LOC0:.*]]) + ; CHECK: llvm.add {{.*}} loc(#[[LOC0:.*]]) %1 = add i32 %arg1, %arg1, !dbg !6 - ; CHECK llvm.mul {{.*}} loc(#[[LOC1:.*]]) + ; CHECK: llvm.mul {{.*}} loc(#[[LOC1:.*]]) %2 = mul i32 %arg1, %arg1, !dbg !7 ret i32 %2 } -; CHECK #[[LOC0]] = loc(fused<#[[$LB0]]>["debug-info.ll":1:2])) -; CHECK #[[LOC1]] = loc(fused<#[[$LB1]]>["debug-info.ll":2:2])) +; CHECK: #[[FILE:.+]] = #llvm.di_file<"debug-info.ll" in "/"> +; CHECK: #[[SP:.+]] = #llvm.di_subprogram +; CHECK: #[[LB1:.+]] = #llvm.di_lexical_block_file +; CHECK: #[[LOC0]] = loc(fused<#[[LB0]]>[ +; CHECK: #[[LOC1]] = loc(fused<#[[LB1]]>[ !llvm.dbg.cu = !{!1} !llvm.module.flags = !{!0} @@ -206,13 +210,12 @@ define void @subprogram() !dbg !3 { ; // ----- -; CHECK: #[[$SP:.+]] = #llvm.di_subprogram - ; CHECK-LABEL: @func_loc define void @func_loc() !dbg !3 { ret void } -; CHECK: loc(fused<#[[$SP]]>["func_loc"]) +; CHECK: #[[SP:.+]] = #llvm.di_subprogram +; CHECK: loc(fused<#[[SP]]>[ !llvm.dbg.cu = !{!1} !llvm.module.flags = !{!0} @@ -246,9 +249,9 @@ define void @intrinsic(i64 %0, ptr %1) { ret void } -; CHECK: #[[LOC0]] = loc(fused<#[[$SP]]>["debug-info.ll":1:2]) -; CHECK: #[[LOC1]] = loc(fused<#[[$SP]]>["debug-info.ll":2:2]) -; CHECK: #[[LOC2]] = loc(fused<#[[$SP]]>["debug-info.ll":3:2]) +; CHECK: #[[LOC0]] = loc(fused<#[[$SP]]>[{{.*}}]) +; CHECK: #[[LOC1]] = loc(fused<#[[$SP]]>[{{.*}}]) +; CHECK: #[[LOC2]] = loc(fused<#[[$SP]]>[{{.*}}]) declare void @llvm.dbg.value(metadata, metadata, metadata) declare void @llvm.dbg.addr(metadata, metadata, metadata)