diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp index 4d1a95a0c4b43..66b2c1050d59c 100644 --- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -1533,6 +1533,23 @@ AliasResult BasicAAResult::aliasPHI(const PHINode *PN, LocationSize PNSize, return Alias; } +// Return true for an Argument, IntToPtr(Argument) or +// IntToPtr(ExtractValue(Argument)). These are all known +// to not alias with FunctionLocal objects and can come up +// from coerced function arguments. +static bool isArgumentOrArgumentLike(const Value *V) { + if (isa(V)) + return true; + if (auto *P = dyn_cast(V)) { + const Value *POp = P->getOperand(0); + if (isa(POp)) + return true; + if (auto *E = dyn_cast(POp)) + return isa(E->getOperand(0)); + } + return false; +} + /// Provides a bunch of ad-hoc rules to disambiguate in common cases, such as /// array references. AliasResult BasicAAResult::aliasCheck(const Value *V1, LocationSize V1Size, @@ -1585,8 +1602,8 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, LocationSize V1Size, // Function arguments can't alias with things that are known to be // unambigously identified at the function level. - if ((isa(O1) && isIdentifiedFunctionLocal(O2)) || - (isa(O2) && isIdentifiedFunctionLocal(O1))) + if ((isArgumentOrArgumentLike(O1) && isIdentifiedFunctionLocal(O2)) || + (isArgumentOrArgumentLike(O2) && isIdentifiedFunctionLocal(O1))) return AliasResult::NoAlias; // If one pointer is the result of a call/invoke or load and the other is a diff --git a/llvm/test/Analysis/BasicAA/noalias-inttoptr.ll b/llvm/test/Analysis/BasicAA/noalias-inttoptr.ll index 24bbcc55b3202..4e48dd048cf6b 100644 --- a/llvm/test/Analysis/BasicAA/noalias-inttoptr.ll +++ b/llvm/test/Analysis/BasicAA/noalias-inttoptr.ll @@ -24,10 +24,10 @@ define void @test2(i64 %Q_as_int) { ret void } -; Verify that escaped noalias parameter may alias inttoptr +; Verify that escaped noalias parameter are no alias inttoptr define void @test3(ptr noalias %P, i64 %Q_as_int) { ; CHECK-LABEL: Function: test3: - ; CHECK: MayAlias: i8* %P, i8* %Q + ; CHECK: NoAlias: i8* %P, i8* %Q call void @escape(ptr %P) %Q = inttoptr i64 %Q_as_int to ptr store i8 0, ptr %P @@ -35,10 +35,10 @@ define void @test3(ptr noalias %P, i64 %Q_as_int) { ret void } -; Verify that escaped alloca may alias inttoptr +; Verify that escaped alloca are noalias inttoptr define void @test4(i64 %Q_as_int) { ; CHECK-LABEL: Function: test4: - ; CHECK: MayAlias: i8* %P, i8* %Q + ; CHECK: NoAlias: i8* %P, i8* %Q %P = alloca i8 call void @escape(ptr %P) %Q = inttoptr i64 %Q_as_int to ptr @@ -58,3 +58,15 @@ define void @test5(i64 %Q_as_int) { store i8 1, ptr %Q ret void } + +; Verify that extractvalue of a coerced argument are noalias a function local object +define void @test6([2 x i64] %Q.coerce) { + ; CHECK-LABEL: Function: test6: + ; CHECK: NoAlias: i8* %P, i8* %Q + %P = alloca i8 + %Q_as_int = extractvalue [2 x i64] %Q.coerce, 1 + %Q = inttoptr i64 %Q_as_int to ptr + store i8 0, ptr %P + store i8 1, ptr %Q + ret void +}