diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp index 833cc2d4d75..d88554189d1 100644 --- a/lib/Transforms/Utils/InlineFunction.cpp +++ b/lib/Transforms/Utils/InlineFunction.cpp @@ -487,11 +487,18 @@ static void AddAliasScopeMetadata(CallSite CS, ValueToValueMapTy &VMap, PtrArgs.push_back(*AI); } + bool IsFuncCall = isa(I) || isa(I); + // FIXME: We should have a way to access the + // IntrReadArgMem/IntrReadWriteArgMem properties of intrinsics, and we + // should have a way to determine that for regular functions too. For + // now, just do this for the memory intrinsics we understand. + bool IsArgMemOnlyCall = isa(I); + // If we found no pointers, then this instruction is not suitable for // pairing with an instruction to receive aliasing metadata. // However, if this is a call, this we might just alias with none of the // noalias arguments. - if (PtrArgs.empty() && !isa(I) && !isa(I)) + if (PtrArgs.empty() && !IsFuncCall) continue; // It is possible that there is only one underlying object, but you @@ -520,21 +527,41 @@ static void AddAliasScopeMetadata(CallSite CS, ValueToValueMapTy &VMap, bool IsNonPtrConst = isa(V) || isa(V) || isa(V) || isa(V) || isa(V); - if (!IsNonPtrConst && - !isIdentifiedFunctionLocal(const_cast(V))) { + if (IsNonPtrConst) + continue; + + // If this is anything other than a noalias argument, then we cannot + // completely describe the aliasing properties using alias.scope + // metadata (and, thus, won't add any). + if (const Argument *A = dyn_cast(V)) { + if (!A->hasNoAliasAttr()) + UsesAliasingPtr = true; + } else { UsesAliasingPtr = true; - if (!isa(V)) { - CanDeriveViaCapture = true; - break; - } } + + // If this is not some identified function-local object (which cannot + // directly alias a noalias argument), or some other argument (which, + // 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))) + CanDeriveViaCapture = true; } - + + // A function call can always get captured noalias pointers (via other + // parameters, globals, etc.). + if (IsFuncCall && !IsArgMemOnlyCall) + CanDeriveViaCapture = true; + // First, we want to figure out all of the sets with which we definitely // don't alias. Iterate over all noalias set, and add those for which: // 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. + // 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 @@ -565,13 +592,8 @@ static void AddAliasScopeMetadata(CallSite CS, ValueToValueMapTy &VMap, // scopes to arbitrary functions unless we know they don't access any // non-parameter pointer-values. bool CanAddScopes = !UsesAliasingPtr; - if (CanAddScopes && (isa(I) || isa(I))) { - // FIXME: We should have a way to access the - // IntrReadArgMem/IntrReadWriteArgMem properties of intrinsics, and we - // should have a way to determine that for regular functions too. For - // now, just do this for the memory intrinsics we understand. - CanAddScopes = isa(I); - } + if (CanAddScopes && IsFuncCall) + CanAddScopes = IsArgMemOnlyCall; if (CanAddScopes) for (const Argument *A : NoAliasArgs) { diff --git a/test/Transforms/Inline/noalias-calls.ll b/test/Transforms/Inline/noalias-calls.ll index d2404013d22..65b2f6e39cc 100644 --- a/test/Transforms/Inline/noalias-calls.ll +++ b/test/Transforms/Inline/noalias-calls.ll @@ -7,10 +7,12 @@ declare void @hey() #0 define void @hello(i8* noalias nocapture %a, i8* noalias nocapture readonly %c, i8* nocapture %b) #1 { entry: + %l = alloca i8, i32 512, align 1 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 16, i32 16, i1 0) call void @llvm.memcpy.p0i8.p0i8.i64(i8* %b, i8* %c, i64 16, i32 16, i1 0) call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %c, i64 16, i32 16, i1 0) call void @hey() + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %l, i8* %c, i64 16, i32 16, i1 0) ret void } @@ -26,6 +28,7 @@ entry: ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %b, i8* %c, i64 16, i32 16, i1 false) #0, !noalias !3 ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %c, i64 16, i32 16, i1 false) #0, !alias.scope !5 ; CHECK: call void @hey() #0, !noalias !5 +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.*}}, i8* %c, i64 16, i32 16, i1 false) #0, !noalias !3 ; CHECK: ret void ; CHECK: }