PtrArgs.push_back(*AI);
}
+ bool IsFuncCall = isa<CallInst>(I) || isa<InvokeInst>(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<MemIntrinsic>(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<CallInst>(I) && !isa<InvokeInst>(I))
+ if (PtrArgs.empty() && !IsFuncCall)
continue;
// It is possible that there is only one underlying object, but you
bool IsNonPtrConst = isa<ConstantInt>(V) || isa<ConstantFP>(V) ||
isa<ConstantPointerNull>(V) ||
isa<ConstantDataVector>(V) || isa<UndefValue>(V);
- if (!IsNonPtrConst &&
- !isIdentifiedFunctionLocal(const_cast<Value*>(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<Argument>(V)) {
+ if (!A->hasNoAliasAttr())
+ UsesAliasingPtr = true;
+ } else {
UsesAliasingPtr = true;
- if (!isa<Argument>(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<Argument>(V) &&
+ !isIdentifiedFunctionLocal(const_cast<Value*>(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
// scopes to arbitrary functions unless we know they don't access any
// non-parameter pointer-values.
bool CanAddScopes = !UsesAliasingPtr;
- if (CanAddScopes && (isa<CallInst>(I) || isa<InvokeInst>(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<MemIntrinsic>(I);
- }
+ if (CanAddScopes && IsFuncCall)
+ CanAddScopes = IsArgMemOnlyCall;
if (CanAddScopes)
for (const Argument *A : NoAliasArgs) {
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
}
; 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: }