diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -1079,7 +1079,8 @@ // Figure out if we're derived from anything that is not a noalias // argument. - bool CanDeriveViaCapture = false, UsesAliasingPtr = false; + bool CanDeriveViaCapture = false, UsesAliasingPtr = false, + MayAliasForUnidentify = false; for (const Value *V : ObjSet) { // Is this value a constant that cannot be derived from any pointer // value (we need to exclude constant expressions, for example, that @@ -1105,8 +1106,15 @@ // by definition, also cannot alias a noalias argument), then we could // alias a noalias argument that has been captured). if (!isa(V) && - !isIdentifiedFunctionLocal(const_cast(V))) + !isIdentifiedFunctionLocal(const_cast(V))) { CanDeriveViaCapture = true; + // If the underlying object is not a must-not-alias object and it is + // not an identified object, it still may be pointers derived from + // noalias argument as `getUnderlyingObjects()` may not check deep + // enough to get the real underlying object. + if (!isIdentifiedObject(V)) + MayAliasForUnidentify = true; + } } // A function call can always get captured noalias pointers (via other @@ -1119,20 +1127,22 @@ // 1. The noalias argument is not in the set of objects from which we // definitely derive. // 2. The noalias argument has not yet been captured. + // 3. The underlying object is identified. // An arbitrary function that might load pointers could see captured // noalias arguments via other noalias arguments or globals, and so we // must always check for prior capture. for (const Argument *A : NoAliasArgs) { - if (!ObjSet.count(A) && (!CanDeriveViaCapture || - // It might be tempting to skip the - // PointerMayBeCapturedBefore check if - // A->hasNoCaptureAttr() is true, but this is - // incorrect because nocapture only guarantees - // that no copies outlive the function, not - // that the value cannot be locally captured. - !PointerMayBeCapturedBefore(A, - /* ReturnCaptures */ false, - /* StoreCaptures */ false, I, &DT))) + if (!ObjSet.count(A) && !MayAliasForUnidentify && + (!CanDeriveViaCapture || + // It might be tempting to skip the + // PointerMayBeCapturedBefore check if + // A->hasNoCaptureAttr() is true, but this is + // incorrect because nocapture only guarantees + // that no copies outlive the function, not + // that the value cannot be locally captured. + !PointerMayBeCapturedBefore(A, + /* ReturnCaptures */ false, + /* StoreCaptures */ false, I, &DT))) NoAliases.push_back(NewScopes[A]); } diff --git a/llvm/test/Transforms/Coroutines/coro-retcon-opaque-ptr.ll b/llvm/test/Transforms/Coroutines/coro-retcon-opaque-ptr.ll --- a/llvm/test/Transforms/Coroutines/coro-retcon-opaque-ptr.ll +++ b/llvm/test/Transforms/Coroutines/coro-retcon-opaque-ptr.ll @@ -34,8 +34,8 @@ ; CHECK-LABEL: @main( ; CHECK-NEXT: entry: ; CHECK-NEXT: call void @print(i32 4) -; CHECK-NEXT: call void @print(i32 5), !noalias !0 -; CHECK-NEXT: call void @print(i32 6), !noalias !3 +; CHECK-NEXT: call void @print(i32 5) +; CHECK-NEXT: call void @print(i32 6) ; CHECK-NEXT: ret i32 0 ; entry: diff --git a/llvm/test/Transforms/Coroutines/coro-retcon-resume-values.ll b/llvm/test/Transforms/Coroutines/coro-retcon-resume-values.ll --- a/llvm/test/Transforms/Coroutines/coro-retcon-resume-values.ll +++ b/llvm/test/Transforms/Coroutines/coro-retcon-resume-values.ll @@ -46,29 +46,27 @@ ; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8** [[TMP0]] to %f.Frame** ; CHECK-NEXT: [[N_VAL3_SPILL_ADDR_I:%.*]] = getelementptr inbounds i8, i8* [[TMP1]], i64 4 ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i8* [[N_VAL3_SPILL_ADDR_I]] to i32* -; CHECK-NEXT: store i32 1, i32* [[TMP3]], align 4, !noalias !0 +; CHECK-NEXT: store i32 1, i32* [[TMP3]], align 4 ; CHECK-NEXT: [[INPUT_SPILL_ADDR_I:%.*]] = getelementptr inbounds i8, i8* [[TMP1]], i64 8 ; CHECK-NEXT: [[TMP4:%.*]] = bitcast i8* [[INPUT_SPILL_ADDR_I]] to i32* -; CHECK-NEXT: store i32 2, i32* [[TMP4]], align 4, !noalias !0 -; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META3:![0-9]+]]) -; CHECK-NEXT: [[FRAMEPTR_I1:%.*]] = load %f.Frame*, %f.Frame** [[TMP2]], align 8, !alias.scope !3 +; CHECK-NEXT: store i32 2, i32* [[TMP4]], align 4 +; CHECK-NEXT: [[FRAMEPTR_I1:%.*]] = load %f.Frame*, %f.Frame** [[TMP2]], align 8, !alias.scope !0 ; CHECK-NEXT: [[INPUT_RELOAD_ADDR13_I:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], %f.Frame* [[FRAMEPTR_I1]], i64 0, i32 2 -; CHECK-NEXT: [[INPUT_RELOAD14_I:%.*]] = load i32, i32* [[INPUT_RELOAD_ADDR13_I]], align 4, !noalias !3 +; CHECK-NEXT: [[INPUT_RELOAD14_I:%.*]] = load i32, i32* [[INPUT_RELOAD_ADDR13_I]], align 4 ; CHECK-NEXT: [[N_VAL3_RELOAD_ADDR11_I:%.*]] = getelementptr inbounds [[F_FRAME]], %f.Frame* [[FRAMEPTR_I1]], i64 0, i32 1 -; CHECK-NEXT: [[N_VAL3_RELOAD12_I:%.*]] = load i32, i32* [[N_VAL3_RELOAD_ADDR11_I]], align 4, !noalias !3 +; CHECK-NEXT: [[N_VAL3_RELOAD12_I:%.*]] = load i32, i32* [[N_VAL3_RELOAD_ADDR11_I]], align 4 ; CHECK-NEXT: [[SUM7_I:%.*]] = add i32 [[N_VAL3_RELOAD12_I]], [[INPUT_RELOAD14_I]] -; CHECK-NEXT: store i32 [[SUM7_I]], i32* [[N_VAL3_RELOAD_ADDR11_I]], align 4, !noalias !3 -; CHECK-NEXT: store i32 4, i32* [[INPUT_RELOAD_ADDR13_I]], align 4, !noalias !3 -; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]]) -; CHECK-NEXT: [[FRAMEPTR_I2:%.*]] = load %f.Frame*, %f.Frame** [[TMP2]], align 8, !alias.scope !6 +; CHECK-NEXT: store i32 [[SUM7_I]], i32* [[N_VAL3_RELOAD_ADDR11_I]], align 4 +; CHECK-NEXT: store i32 4, i32* [[INPUT_RELOAD_ADDR13_I]], align 4 +; CHECK-NEXT: [[FRAMEPTR_I2:%.*]] = load %f.Frame*, %f.Frame** [[TMP2]], align 8, !alias.scope !3 ; CHECK-NEXT: [[INPUT_RELOAD_ADDR13_I3:%.*]] = getelementptr inbounds [[F_FRAME]], %f.Frame* [[FRAMEPTR_I2]], i64 0, i32 2 -; CHECK-NEXT: [[INPUT_RELOAD14_I4:%.*]] = load i32, i32* [[INPUT_RELOAD_ADDR13_I3]], align 4, !noalias !6 +; CHECK-NEXT: [[INPUT_RELOAD14_I4:%.*]] = load i32, i32* [[INPUT_RELOAD_ADDR13_I3]], align 4 ; CHECK-NEXT: [[N_VAL3_RELOAD_ADDR11_I5:%.*]] = getelementptr inbounds [[F_FRAME]], %f.Frame* [[FRAMEPTR_I2]], i64 0, i32 1 -; CHECK-NEXT: [[N_VAL3_RELOAD12_I6:%.*]] = load i32, i32* [[N_VAL3_RELOAD_ADDR11_I5]], align 4, !noalias !6 +; CHECK-NEXT: [[N_VAL3_RELOAD12_I6:%.*]] = load i32, i32* [[N_VAL3_RELOAD_ADDR11_I5]], align 4 ; CHECK-NEXT: [[SUM7_I7:%.*]] = add i32 [[N_VAL3_RELOAD12_I6]], [[INPUT_RELOAD14_I4]] -; CHECK-NEXT: call void @print(i32 [[SUM7_I7]]), !noalias !6 +; CHECK-NEXT: call void @print(i32 [[SUM7_I7]]) ; CHECK-NEXT: [[TMP5:%.*]] = bitcast %f.Frame* [[FRAMEPTR_I2]] to i8* -; CHECK-NEXT: call void @deallocate(i8* [[TMP5]]), !noalias !6 +; CHECK-NEXT: call void @deallocate(i8* [[TMP5]]) ; CHECK-NEXT: ret i32 0 ; entry: diff --git a/llvm/test/Transforms/Coroutines/coro-retcon.ll b/llvm/test/Transforms/Coroutines/coro-retcon.ll --- a/llvm/test/Transforms/Coroutines/coro-retcon.ll +++ b/llvm/test/Transforms/Coroutines/coro-retcon.ll @@ -36,8 +36,8 @@ ; CHECK-LABEL: @main( ; CHECK-NEXT: entry: ; CHECK-NEXT: call void @print(i32 4) -; CHECK-NEXT: call void @print(i32 5), !noalias !0 -; CHECK-NEXT: call void @print(i32 6), !noalias !3 +; CHECK-NEXT: call void @print(i32 5) +; CHECK-NEXT: call void @print(i32 6) ; CHECK-NEXT: ret i32 0 ; entry: diff --git a/llvm/test/Transforms/Inline/inline-noalias-unidentify-object.ll b/llvm/test/Transforms/Inline/inline-noalias-unidentify-object.ll --- a/llvm/test/Transforms/Inline/inline-noalias-unidentify-object.ll +++ b/llvm/test/Transforms/Inline/inline-noalias-unidentify-object.ll @@ -14,7 +14,7 @@ ; CHECK-NEXT: [[P_6_I:%.*]] = getelementptr i8, ptr [[P_5_I]], i64 1 ; CHECK-NEXT: [[P_7_I:%.*]] = getelementptr i8, ptr [[P_6_I]], i64 1 ; CHECK-NEXT: [[P_8_ALIAS_I:%.*]] = getelementptr i8, ptr [[P_7_I]], i64 1 -; CHECK-NEXT: store i32 42, ptr [[P_8_ALIAS_I]], align 4, !noalias !0 +; CHECK-NEXT: store i32 42, ptr [[P_8_ALIAS_I]], align 4 ; CHECK-NEXT: ret i32 [[V_I]] ; %v = call i32 @callee(ptr %p)