[llvm] Perf/goldsteinn/nocapture wip (PR #113116)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Oct 20 18:01:35 PDT 2024
https://github.com/goldsteinn created https://github.com/llvm/llvm-project/pull/113116
None
>From c54fae4334e9ecdc8f729f0f08554f20adf70d89 Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Sun, 20 Oct 2024 13:38:28 -0500
Subject: [PATCH 1/2] Foobar
---
llvm/lib/Transforms/Utils/InlineFunction.cpp | 118 +++++++++++++++++-
.../Transforms/Inline/noalias-calls-always.ll | 4 +-
llvm/test/Transforms/Inline/noalias-calls.ll | 4 +-
llvm/test/Transforms/PhaseOrdering/pr95152.ll | 4 +-
4 files changed, 123 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index 4ad426285ce2f0..77bf8097c45fe8 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -1351,6 +1351,109 @@ static bool MayContainThrowingOrExitingCallAfterCB(CallBase *Begin,
++BeginIt, End->getIterator(), InlinerAttributeWindow + 1);
}
+template <typename RangeT> static bool ContainsSideEffects(RangeT Range) {
+ // Any instruction that may clear local scratch space CB stored
+ // into.
+
+ return any_of(Range, [](Instruction &I) { return I.mayHaveSideEffects(); });
+}
+
+template <typename RangeT> static bool ContainsScratchSpace(RangeT Range) {
+ return any_of(Range, [](Instruction &I) {
+ // Any instruction that may create local scratch space CB can store
+ // into.
+ return I.mayHaveSideEffects() || isa<AllocaInst>(&I);
+ });
+}
+
+static bool CheckPathFromBB(DenseMap<BasicBlock *, bool> &CachedRes,
+ BasicBlock *BB, bool From) {
+ // Initialize to true (okay to propagate) `nocapture`. This means that loops
+ // will be okay.
+ auto [Iter, Inserted] = CachedRes.try_emplace(BB, true);
+ // If we already have a result, return it.
+ if (!Inserted)
+ return Iter->second;
+
+ bool Res = true;
+ auto BBRange = BB->instructionsWithoutDebug();
+ if (From) {
+ // Continue checking successors
+ Res = ContainsSideEffects(BBRange);
+ for (BasicBlock *Succ : successors(BB)) {
+ if (!Res)
+ break;
+ Res = CheckPathFromBB(CachedRes, Succ, From);
+ }
+ } else {
+ // Continue checking preds
+ Res = ContainsScratchSpace(BBRange);
+ for (BasicBlock *Pred : predecessors(BB)) {
+ if (!Res)
+ break;
+ Res = CheckPathFromBB(CachedRes, Pred, From);
+ }
+ }
+ if (!Res)
+ CachedRes[BB] = false;
+ return Res;
+}
+
+// Assuming we have:
+// define @foo(ptr nocapture %p) {
+// entry:
+// ...
+// bar (ptr %p)
+// ...
+// }
+//
+// Determine if we can propagate `nocapture` to the `%p` at the
+// `bar`.
+// First if `bar` is non-void, we only propagate if the only users of
+// `bar` are return instructions from `foo` (meaning if `bar` captured
+// via return, `foo` would too).
+// Next We do an extremely conservatively check and only propagate
+// the `nocapture` if the `bar` has no side-effects or if `bar` is the only
+// instruction with side-effects on all paths from `entry` that go through the
+// `bar` and there are no `alloca` instructions. This accomplishes two things.
+// 1) It ensures that after ``bar``, there is no way a store/other could "clean
+// up" an captures from `bar`. 2) There is no local state (i.e `alloca` or a
+// local `malloc`) that could `bar` could have stored `p` in.
+static bool
+CanPropagateNoCaptureAtCB(DenseMap<BasicBlock *, bool> &PureFromBB,
+ DenseMap<BasicBlock *, bool> &NoLocalStateToBB,
+ BasicBlock *BB, CallBase *CB) {
+ // Check that we can't capture via return.
+ if (!CB->getType()->isVoidTy())
+ for (auto Use : CB->users())
+ if (!isa<ReturnInst>(Use))
+ return false;
+
+ // Can't capture via return, so if no side-effects we are set.
+ if (!CB->mayHaveSideEffects())
+ return true;
+
+ auto It = CB->getIterator();
+ ++It;
+ if (ContainsSideEffects(make_range(It, BB->end())) ||
+ ContainsScratchSpace(make_range(BB->begin(), CB->getIterator())))
+ return false;
+
+ for (BasicBlock *Succ : successors(BB)) {
+ if (!CheckPathFromBB(PureFromBB, Succ, /*From=*/true)) {
+ PureFromBB[Succ] = false;
+ return false;
+ }
+ }
+ for (BasicBlock *Pred : predecessors(BB)) {
+ if (!CheckPathFromBB(NoLocalStateToBB, Pred, /*From=*/false)) {
+ PureFromBB[Pred] = false;
+ return false;
+ }
+ }
+ return true;
+}
+
// Add attributes from CB params and Fn attributes that can always be propagated
// to the corresponding argument / inner callbases.
static void AddParamAndFnBasicAttributes(const CallBase &CB,
@@ -1363,6 +1466,9 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
SmallVector<AttrBuilder> ValidObjParamAttrs, ValidExactParamAttrs;
bool HasAttrToPropagate = false;
+ DenseMap<BasicBlock *, bool> PureFromBB{};
+ DenseMap<BasicBlock *, bool> NoLocalStateToBB{};
+
// Attributes we can only propagate if the exact parameter is forwarded.
// We can propagate both poison generating and UB generating attributes
// without any extra checks. The only attribute that is tricky to propagate
@@ -1381,6 +1487,8 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
ValidObjParamAttrs.back().addAttribute(Attribute::ReadNone);
if (CB.paramHasAttr(I, Attribute::ReadOnly))
ValidObjParamAttrs.back().addAttribute(Attribute::ReadOnly);
+ if (CB.paramHasAttr(I, Attribute::NoCapture))
+ ValidObjParamAttrs.back().addAttribute(Attribute::NoCapture);
for (Attribute::AttrKind AK : ExactAttrsToPropagate) {
Attribute Attr = CB.getParamAttr(I, AK);
@@ -1463,8 +1571,16 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
ArgNo = Arg->getArgNo();
}
+ AttributeSet AS = AttributeSet::get(Context, ValidObjParamAttrs[ArgNo]);
+ // Check if we can propagate `nocapture`.
+ if (AS.hasAttribute(Attribute::NoCapture) &&
+ !NewInnerCB->paramHasAttr(I, Attribute::NoCapture))
+ if (!CanPropagateNoCaptureAtCB(PureFromBB, NoLocalStateToBB, &BB,
+ cast<CallBase>(&Ins)))
+ AS = AS.removeAttribute(Context, Attribute::NoCapture);
+
// If so, propagate its access attributes.
- AL = AL.addParamAttributes(Context, I, ValidObjParamAttrs[ArgNo]);
+ AL = AL.addParamAttributes(Context, I, AttrBuilder{Context, AS});
// We can have conflicting attributes from the inner callsite and
// to-be-inlined callsite. In that case, choose the most
// restrictive.
diff --git a/llvm/test/Transforms/Inline/noalias-calls-always.ll b/llvm/test/Transforms/Inline/noalias-calls-always.ll
index a80cd12b26b655..2d77d77938f1ea 100644
--- a/llvm/test/Transforms/Inline/noalias-calls-always.ll
+++ b/llvm/test/Transforms/Inline/noalias-calls-always.ll
@@ -38,7 +38,7 @@ define void @foo(ptr nocapture %a, ptr nocapture readonly %c, ptr nocapture %b)
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr readonly align 16 [[C:%.*]], i64 16, i1 false), !noalias [[META0]]
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr readonly align 16 [[C]], i64 16, i1 false), !alias.scope [[META5:![0-9]+]]
; CHECK-NEXT: call void @hey(), !noalias [[META5]]
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META0]]
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr nocapture readonly align 16 [[C]], i64 16, i1 false), !noalias [[META0]]
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 512, ptr [[L_I]])
; CHECK-NEXT: ret void
;
@@ -79,7 +79,7 @@ define void @foo_cs(ptr nocapture %a, ptr nocapture readonly %c, ptr nocapture %
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr readonly align 16 [[C:%.*]], i64 16, i1 false), !noalias [[META6]]
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr readonly align 16 [[C]], i64 16, i1 false), !alias.scope [[META11:![0-9]+]]
; CHECK-NEXT: call void @hey(), !noalias [[META11]]
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META6]]
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr nocapture readonly align 16 [[C]], i64 16, i1 false), !noalias [[META6]]
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 512, ptr [[L_I]])
; CHECK-NEXT: ret void
;
diff --git a/llvm/test/Transforms/Inline/noalias-calls.ll b/llvm/test/Transforms/Inline/noalias-calls.ll
index 0dd9ec3498a93a..dcafdcb01d13c8 100644
--- a/llvm/test/Transforms/Inline/noalias-calls.ll
+++ b/llvm/test/Transforms/Inline/noalias-calls.ll
@@ -41,7 +41,7 @@ define void @foo(ptr nocapture %a, ptr nocapture readonly %c, ptr nocapture %b)
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META0]]
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr readonly align 16 [[C]], i64 16, i1 false), !alias.scope [[META5:![0-9]+]]
; CHECK-NEXT: call void @hey(), !noalias [[META5]]
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META0]]
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr nocapture readonly align 16 [[C]], i64 16, i1 false), !noalias [[META0]]
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 512, ptr [[L_I]])
; CHECK-NEXT: ret void
;
@@ -84,7 +84,7 @@ define void @foo_cs(ptr nocapture %a, ptr nocapture readonly %c, ptr nocapture %
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META6]]
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr readonly align 16 [[C]], i64 16, i1 false), !alias.scope [[META11:![0-9]+]]
; CHECK-NEXT: call void @hey(), !noalias [[META11]]
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META6]]
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr nocapture readonly align 16 [[C]], i64 16, i1 false), !noalias [[META6]]
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 512, ptr [[L_I]])
; CHECK-NEXT: ret void
;
diff --git a/llvm/test/Transforms/PhaseOrdering/pr95152.ll b/llvm/test/Transforms/PhaseOrdering/pr95152.ll
index fff94673a1a519..9c814ab10c7977 100644
--- a/llvm/test/Transforms/PhaseOrdering/pr95152.ll
+++ b/llvm/test/Transforms/PhaseOrdering/pr95152.ll
@@ -45,9 +45,9 @@ define void @g(ptr dead_on_unwind noalias writable dereferenceable(8) align 8 %p
define void @f(ptr dead_on_unwind noalias %p) {
; CHECK-LABEL: define void @f(
-; CHECK-SAME: ptr dead_on_unwind noalias [[P:%.*]]) local_unnamed_addr {
+; CHECK-SAME: ptr dead_on_unwind noalias nocapture [[P:%.*]]) local_unnamed_addr {
; CHECK-NEXT: store i64 3, ptr [[P]], align 4
-; CHECK-NEXT: tail call void @j(ptr nonnull align 8 dereferenceable(8) [[P]])
+; CHECK-NEXT: tail call void @j(ptr nocapture nonnull align 8 dereferenceable(8) [[P]])
; CHECK-NEXT: store i64 43, ptr [[P]], align 4
; CHECK-NEXT: ret void
;
>From 00661f3e213e21283011c6dedc5857803aeaef6e Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Sun, 20 Oct 2024 20:00:51 -0500
Subject: [PATCH 2/2] NoCapture Prop During Inling
---
llvm/lib/Transforms/Utils/InlineFunction.cpp | 47 +++++++++++--------
.../Transforms/Inline/noalias-calls-always.ll | 4 +-
llvm/test/Transforms/Inline/noalias-calls.ll | 4 +-
llvm/test/Transforms/PhaseOrdering/pr95152.ll | 4 +-
4 files changed, 33 insertions(+), 26 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index 77bf8097c45fe8..a3c7337262313a 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -1375,28 +1375,32 @@ static bool CheckPathFromBB(DenseMap<BasicBlock *, bool> &CachedRes,
if (!Inserted)
return Iter->second;
- bool Res = true;
- auto BBRange = BB->instructionsWithoutDebug();
if (From) {
// Continue checking successors
- Res = ContainsSideEffects(BBRange);
+ if (ContainsSideEffects(BB->instructionsWithoutDebug())) {
+ CachedRes[BB] = false;
+ return false;
+ }
for (BasicBlock *Succ : successors(BB)) {
- if (!Res)
- break;
- Res = CheckPathFromBB(CachedRes, Succ, From);
+ if (!CheckPathFromBB(CachedRes, Succ, From)) {
+ CachedRes[BB] = false;
+ return false;
+ }
}
} else {
// Continue checking preds
- Res = ContainsScratchSpace(BBRange);
+ if (ContainsScratchSpace(BB->instructionsWithoutDebug())) {
+ CachedRes[BB] = false;
+ return false;
+ }
for (BasicBlock *Pred : predecessors(BB)) {
- if (!Res)
- break;
- Res = CheckPathFromBB(CachedRes, Pred, From);
+ if (!CheckPathFromBB(CachedRes, Pred, From)) {
+ CachedRes[BB] = false;
+ return false;
+ }
}
}
- if (!Res)
- CachedRes[BB] = false;
- return Res;
+ return true;
}
// Assuming we have:
@@ -1430,11 +1434,12 @@ CanPropagateNoCaptureAtCB(DenseMap<BasicBlock *, bool> &PureFromBB,
return false;
// Can't capture via return, so if no side-effects we are set.
- if (!CB->mayHaveSideEffects())
- return true;
+ // if (!CB->mayHaveSideEffects())
+ // return true;
auto It = CB->getIterator();
++It;
+
if (ContainsSideEffects(make_range(It, BB->end())) ||
ContainsScratchSpace(make_range(BB->begin(), CB->getIterator())))
return false;
@@ -1447,7 +1452,7 @@ CanPropagateNoCaptureAtCB(DenseMap<BasicBlock *, bool> &PureFromBB,
}
for (BasicBlock *Pred : predecessors(BB)) {
if (!CheckPathFromBB(NoLocalStateToBB, Pred, /*From=*/false)) {
- PureFromBB[Pred] = false;
+ NoLocalStateToBB[Pred] = false;
return false;
}
}
@@ -1573,11 +1578,13 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
AttributeSet AS = AttributeSet::get(Context, ValidObjParamAttrs[ArgNo]);
// Check if we can propagate `nocapture`.
- if (AS.hasAttribute(Attribute::NoCapture) &&
- !NewInnerCB->paramHasAttr(I, Attribute::NoCapture))
- if (!CanPropagateNoCaptureAtCB(PureFromBB, NoLocalStateToBB, &BB,
- cast<CallBase>(&Ins)))
+ if (AS.hasAttribute(Attribute::NoCapture)) {
+ if (NewInnerCB->paramHasAttr(I, Attribute::NoCapture))
+ AS = AS.removeAttribute(Context, Attribute::NoCapture);
+ else if (!CanPropagateNoCaptureAtCB(PureFromBB, NoLocalStateToBB, &BB,
+ cast<CallBase>(&Ins)))
AS = AS.removeAttribute(Context, Attribute::NoCapture);
+ }
// If so, propagate its access attributes.
AL = AL.addParamAttributes(Context, I, AttrBuilder{Context, AS});
diff --git a/llvm/test/Transforms/Inline/noalias-calls-always.ll b/llvm/test/Transforms/Inline/noalias-calls-always.ll
index 2d77d77938f1ea..a80cd12b26b655 100644
--- a/llvm/test/Transforms/Inline/noalias-calls-always.ll
+++ b/llvm/test/Transforms/Inline/noalias-calls-always.ll
@@ -38,7 +38,7 @@ define void @foo(ptr nocapture %a, ptr nocapture readonly %c, ptr nocapture %b)
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr readonly align 16 [[C:%.*]], i64 16, i1 false), !noalias [[META0]]
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr readonly align 16 [[C]], i64 16, i1 false), !alias.scope [[META5:![0-9]+]]
; CHECK-NEXT: call void @hey(), !noalias [[META5]]
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr nocapture readonly align 16 [[C]], i64 16, i1 false), !noalias [[META0]]
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META0]]
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 512, ptr [[L_I]])
; CHECK-NEXT: ret void
;
@@ -79,7 +79,7 @@ define void @foo_cs(ptr nocapture %a, ptr nocapture readonly %c, ptr nocapture %
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr readonly align 16 [[C:%.*]], i64 16, i1 false), !noalias [[META6]]
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr readonly align 16 [[C]], i64 16, i1 false), !alias.scope [[META11:![0-9]+]]
; CHECK-NEXT: call void @hey(), !noalias [[META11]]
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr nocapture readonly align 16 [[C]], i64 16, i1 false), !noalias [[META6]]
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META6]]
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 512, ptr [[L_I]])
; CHECK-NEXT: ret void
;
diff --git a/llvm/test/Transforms/Inline/noalias-calls.ll b/llvm/test/Transforms/Inline/noalias-calls.ll
index dcafdcb01d13c8..0dd9ec3498a93a 100644
--- a/llvm/test/Transforms/Inline/noalias-calls.ll
+++ b/llvm/test/Transforms/Inline/noalias-calls.ll
@@ -41,7 +41,7 @@ define void @foo(ptr nocapture %a, ptr nocapture readonly %c, ptr nocapture %b)
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META0]]
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr readonly align 16 [[C]], i64 16, i1 false), !alias.scope [[META5:![0-9]+]]
; CHECK-NEXT: call void @hey(), !noalias [[META5]]
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr nocapture readonly align 16 [[C]], i64 16, i1 false), !noalias [[META0]]
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META0]]
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 512, ptr [[L_I]])
; CHECK-NEXT: ret void
;
@@ -84,7 +84,7 @@ define void @foo_cs(ptr nocapture %a, ptr nocapture readonly %c, ptr nocapture %
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[B]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META6]]
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[A]], ptr readonly align 16 [[C]], i64 16, i1 false), !alias.scope [[META11:![0-9]+]]
; CHECK-NEXT: call void @hey(), !noalias [[META11]]
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr nocapture readonly align 16 [[C]], i64 16, i1 false), !noalias [[META6]]
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[L_I]], ptr readonly align 16 [[C]], i64 16, i1 false), !noalias [[META6]]
; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 512, ptr [[L_I]])
; CHECK-NEXT: ret void
;
diff --git a/llvm/test/Transforms/PhaseOrdering/pr95152.ll b/llvm/test/Transforms/PhaseOrdering/pr95152.ll
index 9c814ab10c7977..fff94673a1a519 100644
--- a/llvm/test/Transforms/PhaseOrdering/pr95152.ll
+++ b/llvm/test/Transforms/PhaseOrdering/pr95152.ll
@@ -45,9 +45,9 @@ define void @g(ptr dead_on_unwind noalias writable dereferenceable(8) align 8 %p
define void @f(ptr dead_on_unwind noalias %p) {
; CHECK-LABEL: define void @f(
-; CHECK-SAME: ptr dead_on_unwind noalias nocapture [[P:%.*]]) local_unnamed_addr {
+; CHECK-SAME: ptr dead_on_unwind noalias [[P:%.*]]) local_unnamed_addr {
; CHECK-NEXT: store i64 3, ptr [[P]], align 4
-; CHECK-NEXT: tail call void @j(ptr nocapture nonnull align 8 dereferenceable(8) [[P]])
+; CHECK-NEXT: tail call void @j(ptr nonnull align 8 dereferenceable(8) [[P]])
; CHECK-NEXT: store i64 43, ptr [[P]], align 4
; CHECK-NEXT: ret void
;
More information about the llvm-commits
mailing list