Index: llvm/trunk/include/llvm/IR/DiagnosticInfo.h =================================================================== --- llvm/trunk/include/llvm/IR/DiagnosticInfo.h +++ llvm/trunk/include/llvm/IR/DiagnosticInfo.h @@ -385,6 +385,8 @@ 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); Index: llvm/trunk/lib/Analysis/OptimizationDiagnosticInfo.cpp =================================================================== --- llvm/trunk/lib/Analysis/OptimizationDiagnosticInfo.cpp +++ llvm/trunk/lib/Analysis/OptimizationDiagnosticInfo.cpp @@ -115,6 +115,8 @@ 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); } }; Index: llvm/trunk/lib/IR/DiagnosticInfo.cpp =================================================================== --- llvm/trunk/lib/IR/DiagnosticInfo.cpp +++ llvm/trunk/lib/IR/DiagnosticInfo.cpp @@ -171,7 +171,14 @@ 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)) {} Index: llvm/trunk/test/Transforms/Inline/optimization-remarks-passed-yaml.ll =================================================================== --- llvm/trunk/test/Transforms/Inline/optimization-remarks-passed-yaml.ll +++ llvm/trunk/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' Index: llvm/trunk/test/Transforms/Inline/optimization-remarks-yaml.ll =================================================================== --- llvm/trunk/test/Transforms/Inline/optimization-remarks-yaml.ll +++ llvm/trunk/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: ... Index: llvm/trunk/utils/opt-viewer/opt-viewer.py =================================================================== --- llvm/trunk/utils/opt-viewer/opt-viewer.py +++ llvm/trunk/utils/opt-viewer/opt-viewer.py @@ -46,20 +46,36 @@ 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, pair): - if pair[0] == 'Callee' or pair[0] == 'Caller': - return demangle(pair[1]) - return pair[1] + 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) + + 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