[PATCH] D151644: [InstCombine] Propegating `nocapture` flag to callsites

Noah Goldstein via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon May 29 00:14:18 PDT 2023


goldstein.w.n created this revision.
goldstein.w.n added reviewers: nikic, StephenFan.
Herald added a subscriber: hiraditya.
Herald added a project: All.
goldstein.w.n requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

If a function FA has an argument ARG with the `nocapture` attribute it
implies that any function callsites FB from within FA also don't cause
ARG argument to be captured. It's useful to set this explicitly, as if
function FA get inlined, we don't want to lose the information that
the specific callsites can't cause ARG to be captured.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D151644

Files:
  llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
  llvm/test/Analysis/BasicAA/nocapture.ll
  llvm/test/Transforms/InstCombine/nocapture-attribute.ll


Index: llvm/test/Transforms/InstCombine/nocapture-attribute.ll
===================================================================
--- llvm/test/Transforms/InstCombine/nocapture-attribute.ll
+++ llvm/test/Transforms/InstCombine/nocapture-attribute.ll
@@ -17,7 +17,7 @@
 define void @a0_nocapture_a1_a2_maybe_capture(ptr nocapture %a0, ptr %a1, ptr %a2) {
 ; CHECK-LABEL: define void @a0_nocapture_a1_a2_maybe_capture
 ; CHECK-SAME: (ptr nocapture [[A0:%.*]], ptr [[A1:%.*]], ptr [[A2:%.*]]) {
-; CHECK-NEXT:    tail call void @ptrs_maybe_capture(ptr [[A0]], ptr [[A1]], ptr [[A2]])
+; CHECK-NEXT:    tail call void @ptrs_maybe_capture(ptr nocapture [[A0]], ptr [[A1]], ptr [[A2]])
 ; CHECK-NEXT:    ret void
 ;
   tail call void @ptrs_maybe_capture(ptr %a0, ptr %a1, ptr %a2)
@@ -27,7 +27,7 @@
 define void @a2_nocapture2x_a1_maybe_capture(ptr %a0, ptr %a1, ptr nocapture %a2) {
 ; CHECK-LABEL: define void @a2_nocapture2x_a1_maybe_capture
 ; CHECK-SAME: (ptr [[A0:%.*]], ptr [[A1:%.*]], ptr nocapture [[A2:%.*]]) {
-; CHECK-NEXT:    tail call void @ptrs_maybe_capture(ptr [[A2]], ptr [[A1]], ptr [[A2]])
+; CHECK-NEXT:    tail call void @ptrs_maybe_capture(ptr nocapture [[A2]], ptr [[A1]], ptr nocapture [[A2]])
 ; CHECK-NEXT:    ret void
 ;
   tail call void @ptrs_maybe_capture(ptr %a2, ptr %a1, ptr %a2)
@@ -37,7 +37,7 @@
 define void @a0_a1_a2_nocapture(ptr nocapture %a0, ptr nocapture %a1, ptr nocapture %a2) {
 ; CHECK-LABEL: define void @a0_a1_a2_nocapture
 ; CHECK-SAME: (ptr nocapture [[A0:%.*]], ptr nocapture [[A1:%.*]], ptr nocapture [[A2:%.*]]) {
-; CHECK-NEXT:    tail call void @ptrs_maybe_capture(ptr [[A0]], ptr [[A1]], ptr [[A2]])
+; CHECK-NEXT:    tail call void @ptrs_maybe_capture(ptr nocapture [[A0]], ptr nocapture [[A1]], ptr nocapture [[A2]])
 ; CHECK-NEXT:    ret void
 ;
   tail call void @ptrs_maybe_capture(ptr %a0, ptr %a1, ptr %a2)
Index: llvm/test/Analysis/BasicAA/nocapture.ll
===================================================================
--- llvm/test/Analysis/BasicAA/nocapture.ll
+++ llvm/test/Analysis/BasicAA/nocapture.ll
@@ -18,9 +18,9 @@
 define i32 @test4(ptr noalias nocapture %p) nounwind {
 ; CHECK: call void @test3
 ; CHECK: store i32 0, ptr %p
+; CHECK: %x = load ptr, ptr %q
 ; CHECK: store i32 1, ptr %x
-; CHECK: %y = load i32, ptr %p
-; CHECK: ret i32 %y
+; CHECK: ret i32 0
 entry:
        %q = alloca ptr
        ; Here test3 might store %p to %q. This doesn't violate %p's nocapture
Index: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3385,24 +3385,40 @@
   // Mark any parameters that are known to be non-null with the nonnull
   // attribute.  This is helpful for inlining calls to functions with null
   // checks on their arguments.
-  SmallVector<unsigned, 4> ArgNos;
+  // Likewise mark parameters that are known not captured from parent attributes
+  // as nocapture.
+  SmallVector<unsigned, 4> ArgNosNonNull, ArgNosNoCapture;
+  SmallPtrSet<Value *, 4> NoCaptureParentArguments;
   unsigned ArgNo = 0;
+  if (auto *BB = Call.getParent())
+    if (auto *PF = BB->getParent())
+      for (unsigned I = 0; I < PF->arg_size(); ++I)
+        if (PF->getArg(I)->hasNoCaptureAttr())
+          NoCaptureParentArguments.insert(PF->getArg(I));
 
   for (Value *V : Call.args()) {
     if (V->getType()->isPointerTy() &&
         !Call.paramHasAttr(ArgNo, Attribute::NonNull) &&
         isKnownNonZero(V, DL, 0, &AC, &Call, &DT))
-      ArgNos.push_back(ArgNo);
+      ArgNosNonNull.push_back(ArgNo);
+    if (!Call.paramHasAttr(ArgNo, Attribute::NoCapture) &&
+        NoCaptureParentArguments.contains(V))
+      ArgNosNoCapture.push_back(ArgNo);
+
     ArgNo++;
   }
 
   assert(ArgNo == Call.arg_size() && "Call arguments not processed correctly.");
 
-  if (!ArgNos.empty()) {
+  if (!ArgNosNonNull.empty() || !ArgNosNoCapture.empty()) {
     AttributeList AS = Call.getAttributes();
     LLVMContext &Ctx = Call.getContext();
-    AS = AS.addParamAttribute(Ctx, ArgNos,
-                              Attribute::get(Ctx, Attribute::NonNull));
+    if (!ArgNosNonNull.empty())
+      AS = AS.addParamAttribute(Ctx, ArgNosNonNull,
+                                Attribute::get(Ctx, Attribute::NonNull));
+    if (!ArgNosNoCapture.empty())
+      AS = AS.addParamAttribute(Ctx, ArgNosNoCapture,
+                                Attribute::get(Ctx, Attribute::NoCapture));
     Call.setAttributes(AS);
     Changed = true;
   }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D151644.526400.patch
Type: text/x-patch
Size: 4589 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230529/b519ecc6/attachment.bin>


More information about the llvm-commits mailing list