Skip to content

Commit

Permalink
[Globals] Treat nobuiltin fns as maybe-derefined.
Browse files Browse the repository at this point in the history
Callsites could be marked as `builtin` while calling `nobuiltin`
functions. This can lead to problems, if local optimizations apply
transformations based on the semantics of the builtin, but then IPO
treats the function as `nobuiltin` and applies a transform that breaks
builtin semantics (assumed earlier).

To avoid this, mark such functions as maybey-derefined, to avoid IPO
transforms on them that may break assumptions of earlier calls.

Fixes #57075
Fixes #48366

Reviewed By: ychen

Differential Revision: https://reviews.llvm.org/D97735
  • Loading branch information
fhahn committed Aug 23, 2022
1 parent 1e5b3ce commit 5913d77
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 2 deletions.
10 changes: 9 additions & 1 deletion llvm/include/llvm/IR/GlobalValue.h
Expand Up @@ -145,12 +145,20 @@ class GlobalValue : public Constant {
case AppendingLinkage:
case InternalLinkage:
case PrivateLinkage:
return isInterposable();
// Optimizations may assume builtin semantics for functions defined as
// nobuiltin due to attributes at call-sites. To avoid applying IPO based
// on nobuiltin semantics, treat such function definitions as maybe
// derefined.
return isInterposable() || isNobuiltinFnDef();
}

llvm_unreachable("Fully covered switch above!");
}

/// Returns true if the global is a function definition with the nobuiltin
/// attribute.
bool isNobuiltinFnDef() const;

protected:
/// The intrinsic ID for this subclass (which must be a Function).
///
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/IR/Globals.cpp
Expand Up @@ -261,6 +261,13 @@ void GlobalObject::setSection(StringRef S) {
setGlobalObjectFlag(HasSectionHashEntryBit, !S.empty());
}

bool GlobalValue::isNobuiltinFnDef() const {
const Function *F = dyn_cast<Function>(this);
if (!F || F->empty())
return false;
return F->hasFnAttribute(Attribute::NoBuiltin);
}

bool GlobalValue::isDeclaration() const {
// Globals are definitions if they have an initializer.
if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(this))
Expand Down
Expand Up @@ -13,7 +13,7 @@ entry:
define dso_local i32 @test_fn(ptr %ptr) {
; CHECK-LABEL: @test_fn(
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @_ZdlPv(ptr poison) #[[ATTR1:[0-9]+]]
; CHECK-NEXT: call void @_ZdlPv(ptr [[PTR:%.*]]) #[[ATTR1:[0-9]+]]
; CHECK-NEXT: ret i32 1
;
entry:
Expand Down

0 comments on commit 5913d77

Please sign in to comment.