[Attributor][FIX] NoCapture is not a subsuming property
authorJohannes Doerfert <johannes@jdoerfert.de>
Fri, 1 Nov 2019 01:03:13 +0000 (20:03 -0500)
committerJohannes Doerfert <johannes@jdoerfert.de>
Sat, 2 Nov 2019 05:26:15 +0000 (00:26 -0500)
We cannot look at the subsuming positions and take their nocapture bit
as shown with the two tests for which we derived nocapture on the call
site argument and readonly on the argument of the second before.

llvm/lib/Transforms/IPO/Attributor.cpp
llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll

index a0677c1..6f0a4a8 100644 (file)
@@ -3131,7 +3131,16 @@ struct AANoCaptureImpl : public AANoCapture {
 
   /// See AbstractAttribute::initialize(...).
   void initialize(Attributor &A) override {
-    AANoCapture::initialize(A);
+    if (hasAttr(getAttrKind(), /* IgnoreSubsumingPositions */ true)) {
+      indicateOptimisticFixpoint();
+      return;
+    }
+    Function *AnchorScope = getAnchorScope();
+    if (isFnInterfaceKind() &&
+        (!AnchorScope || !AnchorScope->hasExactDefinition())) {
+      indicatePessimisticFixpoint();
+      return;
+    }
 
     // You cannot "capture" null in the default address space.
     if (isa<ConstantPointerNull>(getAssociatedValue()) &&
@@ -3140,13 +3149,11 @@ struct AANoCaptureImpl : public AANoCapture {
       return;
     }
 
-    const IRPosition &IRP = getIRPosition();
-    const Function *F =
-        getArgNo() >= 0 ? IRP.getAssociatedFunction() : IRP.getAnchorScope();
+    const Function *F = getArgNo() >= 0 ? getAssociatedFunction() : AnchorScope;
 
     // Check what state the associated function can actually capture.
     if (F)
-      determineFunctionCaptureCapabilities(IRP, *F, *this);
+      determineFunctionCaptureCapabilities(getIRPosition(), *F, *this);
     else
       indicatePessimisticFixpoint();
   }
index 18a4f76..ec7db07 100644 (file)
@@ -437,4 +437,35 @@ entry:
   ret i32* %call
 }
 
+
+declare i32* @unknown_i32p(i32*)
+define void @nocapture_is_not_subsumed_1(i32* nocapture %b) {
+; CHECK-LABEL: define {{[^@]+}}@nocapture_is_not_subsumed_1
+; CHECK-SAME: (i32* nocapture [[B:%.*]])
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = call i32* @unknown_i32p(i32* [[B:%.*]])
+; CHECK-NEXT:    store i32 0, i32* [[CALL]]
+; CHECK-NEXT:    ret void
+;
+entry:
+  %call = call i32* @unknown_i32p(i32* %b)
+  store i32 0, i32* %call
+  ret void
+}
+
+declare i32* @readonly_i32p(i32*) readonly
+define void @nocapture_is_not_subsumed_2(i32* nocapture %b) {
+; CHECK-LABEL: define {{[^@]+}}@nocapture_is_not_subsumed_2
+; CHECK-SAME: (i32* nocapture [[B:%.*]])
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL:%.*]] = call i32* @readonly_i32p(i32* readonly [[B:%.*]])
+; CHECK-NEXT:    store i32 0, i32* [[CALL]]
+; CHECK-NEXT:    ret void
+;
+entry:
+  %call = call i32* @readonly_i32p(i32* %b)
+  store i32 0, i32* %call
+  ret void
+}
+
 attributes #0 = { noinline nounwind uwtable }