From: Adam Nemet Date: Mon, 7 Nov 2016 22:41:13 +0000 (+0000) Subject: [OptDiag, opt-viewer] Save callee's location and display as link X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=330e12bad4975aa3c9335ddb7223f462977484d4;p=llvm [OptDiag, opt-viewer] Save callee's location and display as link With this we get a new field in the YAML record if the value being streamed out has a debug location. For examples, please see the changes to the tests. This is then used in opt-viewer to display a link for the callee function in the inlining remarks. Differential Revision: https://reviews.llvm.org/D26366 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286169 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h index 589a0c013ae..4951e94419a 100644 --- a/include/llvm/IR/DiagnosticInfo.h +++ b/include/llvm/IR/DiagnosticInfo.h @@ -385,6 +385,8 @@ public: struct Argument { StringRef Key; std::string Val; + // If set, the debug location corresponding to the value. + DebugLoc DLoc; explicit Argument(StringRef Str = "") : Key("String"), Val(Str) {} Argument(StringRef Key, Value *V); diff --git a/lib/Analysis/OptimizationDiagnosticInfo.cpp b/lib/Analysis/OptimizationDiagnosticInfo.cpp index 6584876f20a..0a5ef1b9b23 100644 --- a/lib/Analysis/OptimizationDiagnosticInfo.cpp +++ b/lib/Analysis/OptimizationDiagnosticInfo.cpp @@ -115,6 +115,8 @@ template <> struct MappingTraits { static void mapping(IO &io, DiagnosticInfoOptimizationBase::Argument &A) { assert(io.outputting() && "input not yet implemented"); io.mapRequired(A.Key.data(), A.Val); + if (A.DLoc) + io.mapOptional("DebugLoc", A.DLoc); } }; diff --git a/lib/IR/DiagnosticInfo.cpp b/lib/IR/DiagnosticInfo.cpp index ae10a6dcae6..5618de8f602 100644 --- a/lib/IR/DiagnosticInfo.cpp +++ b/lib/IR/DiagnosticInfo.cpp @@ -171,7 +171,14 @@ const std::string DiagnosticInfoWithDebugLocBase::getLocationStr() const { return (Filename + ":" + Twine(Line) + ":" + Twine(Column)).str(); } DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, Value *V) - : Key(Key), Val(GlobalValue::getRealLinkageName(V->getName())) {} + : Key(Key), Val(GlobalValue::getRealLinkageName(V->getName())) { + if (auto *F = dyn_cast(V)) { + if (DISubprogram *SP = F->getSubprogram()) + DLoc = DebugLoc::get(SP->getScopeLine(), 0, SP); + } + else if (auto *I = dyn_cast(V)) + DLoc = I->getDebugLoc(); +} DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, int N) : Key(Key), Val(itostr(N)) {} diff --git a/test/Transforms/Inline/optimization-remarks-passed-yaml.ll b/test/Transforms/Inline/optimization-remarks-passed-yaml.ll index 60d07587fdf..1e173342d8b 100644 --- a/test/Transforms/Inline/optimization-remarks-passed-yaml.ll +++ b/test/Transforms/Inline/optimization-remarks-passed-yaml.ll @@ -23,8 +23,10 @@ ; YAML-NEXT: Hotness: 30 ; YAML-NEXT: Args: ; YAML-NEXT: - Callee: foo +; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 1, Column: 0 } ; YAML-NEXT: - String: ' can be inlined into ' ; YAML-NEXT: - Caller: bar +; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 3, Column: 0 } ; YAML-NEXT: - String: ' with cost=' ; YAML-NEXT: - Cost: '{{[0-9]+}}' ; YAML-NEXT: - String: ' (threshold=' @@ -39,8 +41,10 @@ ; YAML-NEXT: Hotness: 30 ; YAML-NEXT: Args: ; YAML-NEXT: - Callee: foo +; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 1, Column: 0 } ; YAML-NEXT: - String: ' inlined into ' ; YAML-NEXT: - Caller: bar +; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 3, Column: 0 } ; YAML-NEXT: ... ; ModuleID = '/tmp/s.c' diff --git a/test/Transforms/Inline/optimization-remarks-yaml.ll b/test/Transforms/Inline/optimization-remarks-yaml.ll index 8c690d9ed4a..cfdd3e657a9 100644 --- a/test/Transforms/Inline/optimization-remarks-yaml.ll +++ b/test/Transforms/Inline/optimization-remarks-yaml.ll @@ -26,6 +26,7 @@ ; YAML-NEXT: - Callee: foo ; YAML-NEXT: - String: ' will not be inlined into ' ; YAML-NEXT: - Caller: baz +; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 4, Column: 0 } ; YAML-NEXT: - String: ' because its definition is unavailable' ; YAML-NEXT: ... ; YAML-NEXT: --- !Missed @@ -38,6 +39,7 @@ ; YAML-NEXT: - Callee: bar ; YAML-NEXT: - String: ' will not be inlined into ' ; YAML-NEXT: - Caller: baz +; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 4, Column: 0 } ; YAML-NEXT: - String: ' because its definition is unavailable' ; YAML-NEXT: ... diff --git a/utils/opt-viewer/opt-viewer.py b/utils/opt-viewer/opt-viewer.py index 1cafe0fe036..9d699f5d032 100755 --- a/utils/opt-viewer/opt-viewer.py +++ b/utils/opt-viewer/opt-viewer.py @@ -46,20 +46,36 @@ class Remark(yaml.YAMLObject): def DemangledFunctionName(self): return demangle(self.Function) + @classmethod + def make_link(cls, File, Line): + return "{}#L{}".format(SourceFileRenderer.html_file_name(File), Line) + @property def Link(self): - return "{}#L{}".format(SourceFileRenderer.html_file_name(self.File), self.Line) + return Remark.make_link(self.File, self.Line) + + def getArgString(self, mapping): + mapping = mapping.copy() + dl = mapping.get('DebugLoc') + if dl: + del mapping['DebugLoc'] + + assert(len(mapping) == 1) + (key, value) = mapping.items()[0] + + if key == 'Caller' or key == 'Callee': + value = demangle(value) - def getArgString(self, pair): - if pair[0] == 'Callee' or pair[0] == 'Caller': - return demangle(pair[1]) - return pair[1] + if dl and key != 'Caller': + return "{}".format( + Remark.make_link(dl['File'], dl['Line']), value) + else: + return value @property def message(self): - # Args is a list of mappings (dictionaries) with each dictionary with - # exactly one key-value pair. - values = [self.getArgString(mapping.items()[0]) for mapping in self.Args] + # Args is a list of mappings (dictionaries) + values = [self.getArgString(mapping) for mapping in self.Args] return "".join(values) @property