This patch is part of a set of patches that add an `-fextend-lifetimes` flag to clang, which extends the lifetimes of local variables and parameters for improved debuggability. In addition to that flag, the patch series adds a pragma to selectively disable `-fextend-lifetimes`, and an `-fextend-this-ptr` flag which functions as `-fextend-lifetimes` for this pointers only. All changes and tests in these patches were written by Wolfgang Pieb (@wolfy1961), while Stephen Tozer (@SLTozer) has handled review and merging. The extend lifetimes flag is intended to eventually be set on by `-Og`, as discussed in the RFC here: https://discourse.llvm.org/t/rfc-redefine-og-o1-and-add-a-new-level-of-og/72850 This patch implements a new intrinsic instruction in LLVM, `llvm.fake.use` in IR and `FAKE_USE` in MIR, that takes a single operand and has no effect other than "using" its operand, to ensure that its operand remains live until after the fake use. This patch does not emit fake uses anywhere; the next patch in this sequence causes them to be emitted from the clang frontend, such that for each variable (or this) a fake.use operand is inserted at the end of that variable's scope, using that variable's value. This patch covers everything post-frontend, which is largely just the basic plumbing for a new intrinsic/instruction, along with a few steps to preserve the fake uses through optimizations (such as moving them ahead of a tail call or translating them through SROA). Co-authored-by: Stephen Tozer <stephen.tozer@sony.com>
51 lines
2.0 KiB
LLVM
51 lines
2.0 KiB
LLVM
; RUN: opt < %s -passes='require<profile-summary>,function(codegenprepare)' -S -mtriple=x86_64 | FileCheck %s --implicit-check-not="llvm.fake.use"
|
|
;
|
|
; When performing return duplication to enable
|
|
; tail call optimization we clone fake uses that exist in the to-be-eliminated
|
|
; return block into the predecessor blocks. When doing this with fake uses
|
|
; of PHI-nodes, they cannot be easily copied, but require the correct operand.
|
|
; We are currently not able to do this correctly, so we suppress the cloning
|
|
; of such fake uses at the moment.
|
|
;
|
|
; There should be no fake use of a call result in any of the resulting return
|
|
; blocks.
|
|
|
|
; Fake uses of `this` should be duplicated into both return blocks.
|
|
; CHECK: if.then:
|
|
; CHECK: @llvm.fake.use({{.*}}this
|
|
; CHECK: if.else:
|
|
; CHECK: @llvm.fake.use({{.*}}this
|
|
|
|
; CHECK: declare void @llvm.fake.use
|
|
|
|
source_filename = "test.ll"
|
|
|
|
%class.a = type { i8 }
|
|
|
|
declare i32 @foo(ptr nonnull dereferenceable(1)) local_unnamed_addr
|
|
declare i32 @bar(ptr nonnull dereferenceable(1)) local_unnamed_addr
|
|
|
|
define hidden void @func(ptr nonnull dereferenceable(1) %this) local_unnamed_addr align 2 optdebug {
|
|
entry:
|
|
%b = getelementptr inbounds %class.a, ptr %this, i64 0, i32 0
|
|
%0 = load i8, i8* %b, align 1
|
|
%tobool.not = icmp eq i8 %0, 0
|
|
br i1 %tobool.not, label %if.else, label %if.then
|
|
|
|
if.then: ; preds = %entry
|
|
%call = tail call i32 @foo(ptr nonnull dereferenceable(1) %this)
|
|
%call2 = tail call i32 @bar(ptr nonnull dereferenceable(1) %this)
|
|
br label %if.end
|
|
|
|
if.else: ; preds = %entry
|
|
%call4 = tail call i32 @bar(ptr nonnull dereferenceable(1) %this)
|
|
%call5 = tail call i32 @foo(ptr nonnull dereferenceable(1) %this)
|
|
br label %if.end
|
|
|
|
if.end: ; preds = %if.else, %if.then
|
|
%call4.sink = phi i32 [ %call4, %if.else ], [ %call, %if.then ]
|
|
notail call void (...) @llvm.fake.use(i32 %call4.sink)
|
|
notail call void (...) @llvm.fake.use(ptr nonnull %this)
|
|
ret void
|
|
}
|