Index: llvm/include/llvm/IR/Value.h =================================================================== --- llvm/include/llvm/IR/Value.h +++ llvm/include/llvm/IR/Value.h @@ -654,15 +654,16 @@ ->stripPointerCastsSameRepresentation()); } - /// Strip off pointer casts, all-zero GEPs and invariant group info. + /// Strip off pointer casts, all-zero GEPs, single-argument phi nodes and + /// invariant group info. /// /// Returns the original uncasted value. If this is called on a non-pointer /// value, it returns 'this'. This function should be used only in /// Alias analysis. - const Value *stripPointerCastsAndInvariantGroups() const; - Value *stripPointerCastsAndInvariantGroups() { + const Value *stripPointerCastsForAliasAnalysis() const; + Value *stripPointerCastsForAliasAnalysis() { return const_cast(static_cast(this) - ->stripPointerCastsAndInvariantGroups()); + ->stripPointerCastsForAliasAnalysis()); } /// Strip off pointer casts and all-constant inbounds GEPs. Index: llvm/lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -1470,8 +1470,8 @@ return NoAlias; // Strip off any casts if they exist. - V1 = V1->stripPointerCastsAndInvariantGroups(); - V2 = V2->stripPointerCastsAndInvariantGroups(); + V1 = V1->stripPointerCastsForAliasAnalysis(); + V2 = V2->stripPointerCastsForAliasAnalysis(); // If V1 or V2 is undef, the result is NoAlias because we can always pick a // value for undef that aliases nothing in the program. Index: llvm/lib/Analysis/GlobalsModRef.cpp =================================================================== --- llvm/lib/Analysis/GlobalsModRef.cpp +++ llvm/lib/Analysis/GlobalsModRef.cpp @@ -828,9 +828,9 @@ AAQueryInfo &AAQI) { // Get the base object these pointers point to. const Value *UV1 = - getUnderlyingObject(LocA.Ptr->stripPointerCastsAndInvariantGroups()); + getUnderlyingObject(LocA.Ptr->stripPointerCastsForAliasAnalysis()); const Value *UV2 = - getUnderlyingObject(LocB.Ptr->stripPointerCastsAndInvariantGroups()); + getUnderlyingObject(LocB.Ptr->stripPointerCastsForAliasAnalysis()); // If either of the underlying values is a global, they may be non-addr-taken // globals, which we can answer queries about. Index: llvm/lib/IR/Value.cpp =================================================================== --- llvm/lib/IR/Value.cpp +++ llvm/lib/IR/Value.cpp @@ -551,7 +551,7 @@ PSK_ZeroIndices, PSK_ZeroIndicesAndAliases, PSK_ZeroIndicesSameRepresentation, - PSK_ZeroIndicesAndInvariantGroups, + PSK_ForAliasAnalysis, PSK_InBoundsConstantIndices, PSK_InBounds }; @@ -577,7 +577,7 @@ case PSK_ZeroIndices: case PSK_ZeroIndicesAndAliases: case PSK_ZeroIndicesSameRepresentation: - case PSK_ZeroIndicesAndInvariantGroups: + case PSK_ForAliasAnalysis: if (!GEP->hasAllZeroIndices()) return V; break; @@ -602,6 +602,9 @@ V = cast(V)->getOperand(0); } else if (StripKind == PSK_ZeroIndicesAndAliases && isa(V)) { V = cast(V)->getAliasee(); + } else if (StripKind == PSK_ForAliasAnalysis && isa(V) && + cast(V)->getNumIncomingValues() == 1) { + V = cast(V)->getIncomingValue(0); } else { if (const auto *Call = dyn_cast(V)) { if (const Value *RV = Call->getReturnedArgOperand()) { @@ -611,7 +614,7 @@ // The result of launder.invariant.group must alias it's argument, // but it can't be marked with returned attribute, that's why it needs // special case. - if (StripKind == PSK_ZeroIndicesAndInvariantGroups && + if (StripKind == PSK_ForAliasAnalysis && (Call->getIntrinsicID() == Intrinsic::launder_invariant_group || Call->getIntrinsicID() == Intrinsic::strip_invariant_group)) { V = Call->getArgOperand(0); @@ -643,8 +646,8 @@ return stripPointerCastsAndOffsets(this); } -const Value *Value::stripPointerCastsAndInvariantGroups() const { - return stripPointerCastsAndOffsets(this); +const Value *Value::stripPointerCastsForAliasAnalysis() const { + return stripPointerCastsAndOffsets(this); } const Value *Value::stripAndAccumulateConstantOffsets( Index: llvm/lib/Target/AMDGPU/AMDGPUAliasAnalysis.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPUAliasAnalysis.cpp +++ llvm/lib/Target/AMDGPU/AMDGPUAliasAnalysis.cpp @@ -87,7 +87,7 @@ if (asA == AMDGPUAS::FLAT_ADDRESS && (asB == AMDGPUAS::LOCAL_ADDRESS || asB == AMDGPUAS::PRIVATE_ADDRESS)) { const auto *ObjA = - getUnderlyingObject(A.Ptr->stripPointerCastsAndInvariantGroups()); + getUnderlyingObject(A.Ptr->stripPointerCastsForAliasAnalysis()); if (const LoadInst *LI = dyn_cast(ObjA)) { // If a generic pointer is loaded from the constant address space, it // could only be a GLOBAL or CONSTANT one as that address space is soley Index: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -390,7 +390,13 @@ InstCombinerImpl &IC) { auto *Arg = II.getArgOperand(0); auto *StrippedArg = Arg->stripPointerCasts(); - auto *StrippedInvariantGroupsArg = Arg->stripPointerCastsAndInvariantGroups(); + auto *StrippedInvariantGroupsArg = StrippedArg; + while (auto *Intr = dyn_cast(StrippedInvariantGroupsArg)) { + if (Intr->getIntrinsicID() != Intrinsic::launder_invariant_group && + Intr->getIntrinsicID() != Intrinsic::strip_invariant_group) + break; + StrippedInvariantGroupsArg = Intr->getArgOperand(0)->stripPointerCasts(); + } if (StrippedArg == StrippedInvariantGroupsArg) return nullptr; // No launders/strips to remove. Index: llvm/test/Analysis/BasicAA/phi-aa.ll =================================================================== --- llvm/test/Analysis/BasicAA/phi-aa.ll +++ llvm/test/Analysis/BasicAA/phi-aa.ll @@ -199,9 +199,9 @@ } ; CHECK-LABEL: single_arg_phi -; CHECK: MayAlias: i32* %ptr, i32* %ptr.next +; CHECK: NoAlias: i32* %ptr, i32* %ptr.next +; CHECK: MustAlias: i32* %ptr, i32* %ptr.phi ; CHECK: MustAlias: i32* %ptr.next, i32* %ptr.next.phi -; TODO: The first one could be MustAlias as well. define void @single_arg_phi(i32* %ptr.base) { entry: br label %loop