-
Notifications
You must be signed in to change notification settings - Fork 14.7k
[clang] report inlining decisions with -Wattribute-{warning|error} #73552
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
cea1772
c03a2cd
239ab3e
6c55bf2
4ea1488
c4bc1cb
3dab971
ba7c507
a1496de
0669084
d3a221a
e7ed56d
d0f28c2
9066947
17ced9d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ | |
//===----------------------------------------------------------------------===// | ||
|
||
#include "llvm/IR/DiagnosticInfo.h" | ||
#include "llvm/ADT/SmallVector.h" | ||
#include "llvm/ADT/StringExtras.h" | ||
#include "llvm/ADT/Twine.h" | ||
#include "llvm/ADT/iterator_range.h" | ||
|
@@ -433,8 +434,9 @@ void llvm::diagnoseDontCall(const CallInst &CI) { | |
if (MDNode *MD = CI.getMetadata("srcloc")) | ||
LocCookie = | ||
mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue(); | ||
DiagnosticInfoDontCall D(F->getName(), A.getValueAsString(), Sev, | ||
LocCookie); | ||
DiagnosticInfoDontCall D(CI.getParent()->getParent()->getName(), | ||
F->getName(), A.getValueAsString(), Sev, | ||
LocCookie, CI.getMetadata("inlined.from")); | ||
F->getContext().diagnose(D); | ||
} | ||
} | ||
|
@@ -449,3 +451,22 @@ void DiagnosticInfoDontCall::print(DiagnosticPrinter &DP) const { | |
if (!getNote().empty()) | ||
DP << ": " << getNote(); | ||
} | ||
|
||
SmallVector<StringRef> DiagnosticInfoDontCall::getInliningDecisions() const { | ||
SmallVector<StringRef> InliningDecisions; | ||
|
||
if (MDN) { | ||
const MDOperand &MO = MDN->getOperand(0); | ||
if (auto *MDT = dyn_cast<MDTuple>(MO)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Copying @aeubanks 's comment from the phab review:
For the life of me I cannot figure out why when an MDTuple is created via: Metadata *MD = MDString::get(CI->getContext(), CalledFunc->getName());
MDTuple *MDT = MDNode::get(CI->getContext(), {MD});
CI->setMetadata("inlined.from", MDT); you get !10 = !{!"my_memcpy"} but when you copy a Metadata *MD = MDString::get(CI->getContext(), CalledFunc->getName());
if (MDNode *N = CI->getMetadata("inlined.from")) {
TempMDTuple Temp = cast<MDTuple>(N)->clone();
Temp->push_back(MD);
MD = MDNode::replaceWithUniqued(std::move(Temp));
}
MDTuple *MDT = MDNode::get(CI->getContext(), {MD});
CI->setMetadata("inlined.from", MDT); !10 = !{!11}
!11 = !{!"my_memcpy", !"my_driver"} when I would have expected: !10 = !{!"my_memcpy", !"my_driver"} am I holding the API wrong?? |
||
for (const MDOperand &MO : MDT->operands()) { | ||
if (auto *S = dyn_cast<MDString>(MO)) { | ||
InliningDecisions.push_back(S->getString()); | ||
} | ||
} | ||
} else if (auto *S = dyn_cast<MDString>(MO)) { | ||
InliningDecisions.push_back(S->getString()); | ||
} | ||
} | ||
|
||
return InliningDecisions; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
; RUN: opt -S -passes=inline < %s | FileCheck %s --check-prefixes=CHECK-BOTH,CHECK | ||
; RUN: opt -S -passes=always-inline < %s | FileCheck %s --check-prefixes=CHECK-BOTH,CHECK-ALWAYS | ||
|
||
declare void @foo() "dontcall-warn"="oh no" | ||
declare void @fof() "dontcall-error"="oh no" | ||
|
||
define void @bar(i32 %x) { | ||
%cmp = icmp eq i32 %x, 10 | ||
br i1 %cmp, label %if.then, label %if.end | ||
|
||
if.then: | ||
call void @foo() | ||
br label %if.end | ||
|
||
if.end: | ||
ret void | ||
} | ||
|
||
define void @quux() { | ||
call void @bar(i32 9) | ||
ret void | ||
} | ||
|
||
; Test that @baz's call to @foo has metadata with inlining info. | ||
define void @baz() { | ||
; CHECK-LABEL: define {{[^@]+}}@baz( | ||
; CHECK-NEXT: call void @foo(), !inlined.from !0 | ||
call void @bar(i32 10) | ||
ret void | ||
} | ||
|
||
; Test that @zing's call to @foo has unique metadata from @baz's call to @foo. | ||
define void @zing() { | ||
; CHECK-LABEL: define {{[^@]+}}@zing( | ||
; CHECK-NEXT: call void @foo(), !inlined.from !1 | ||
call void @baz() | ||
ret void | ||
} | ||
|
||
; Same test but @fof has fn attr "dontcall-error"="..." rather than | ||
; "dontcall-warn"="...". | ||
define void @_Z1av() { | ||
call void @fof() | ||
ret void | ||
} | ||
define void @_Z1bv() { | ||
; CHECK-LABEL: define {{[^@]+}}@_Z1bv( | ||
; CHECK-NEXT: call void @fof(), !inlined.from !3 | ||
call void @_Z1av() | ||
ret void | ||
} | ||
|
||
; Add some tests for alwaysinline. | ||
define void @always_callee() alwaysinline { | ||
call void @fof() | ||
ret void | ||
} | ||
define void @always_caller() alwaysinline { | ||
; CHECK-BOTH-LABEL: define {{[^@]+}}@always_caller( | ||
; CHECK-NEXT: call void @fof(), !inlined.from !4 | ||
; CHECK-ALWAYS-NEXT: call void @fof(), !inlined.from !0 | ||
call void @always_callee() | ||
ret void | ||
} | ||
define void @always_caller2() alwaysinline { | ||
; CHECK-BOTH-LABEL: define {{[^@]+}}@always_caller2( | ||
; CHECK-NEXT: call void @fof(), !inlined.from !5 | ||
; CHECK-ALWAYS-NEXT: call void @fof(), !inlined.from !1 | ||
call void @always_caller() | ||
ret void | ||
} | ||
|
||
; CHECK: !0 = !{!"bar"} | ||
; CHECK-NEXT: !1 = !{!2} | ||
; CHECK-NEXT: !2 = !{!"bar", !"baz"} | ||
; CHECK-NEXT: !3 = !{!"_Z1av"} | ||
; CHECK-NEXT: !4 = !{!"always_callee"} | ||
; CHECK-ALWAYS: !0 = !{!"always_callee"} | ||
; CHECK-ALWAYS-NEXT: !1 = !{!2} | ||
; CHECK-ALWAYS-NEXT: !2 = !{!"always_callee", !"always_caller"} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the right file for this? It seems weird to do codegen in a 'frontend kinds' diagnostics list, though I'm not convinced I know enough to ask this question well enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where should the diagnostic strings go if not here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IDK, that is why I asked. It SOUNDS wrong, so I'm hopeful someone else can come along and tell us.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of the diagnostics for backend warnings are defined in this file. (see existing lines 66-95).
As is, this note is emitted alongside the err/warn from existing lines 91-95, so it makes sense to put the new notes immediately after those existing definitions.
If my newly added backend warning notes belong in a new file, then all of the above belong in a new file. But that seems orthogonal to my patch.