Index: llvm/lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -132,16 +132,8 @@ /// Returns true if the pointer is one which would have been considered an /// escape by isNonEscapingLocalObject. static bool isEscapeSource(const Value *V) { - if (auto CS = ImmutableCallSite(V)) { - // launder_invariant_group captures its argument only by returning it, - // so it might not be considered an escape by isNonEscapingLocalObject. - // Note that adding similar special cases for intrinsics in CaptureTracking - // requires handling them here too. - if (CS.getIntrinsicID() == Intrinsic::launder_invariant_group) - return false; - + if (ImmutableCallSite(V)) return true; - } if (isa(V)) return true; @@ -438,11 +430,16 @@ const GEPOperator *GEPOp = dyn_cast(Op); if (!GEPOp) { - if (auto CS = ImmutableCallSite(V)) + if (auto CS = ImmutableCallSite(V)) { if (const Value *RV = CS.getReturnedArgOperand()) { V = RV; continue; } + if (CS.getIntrinsicID() == Intrinsic::launder_invariant_group) { + V = CS.getArgOperand(0); + continue; + } + } // If it's not a GEP, hand it off to SimplifyInstruction to see if it // can come up with something. This matches what GetUnderlyingObject does. Index: llvm/lib/Analysis/CaptureTracking.cpp =================================================================== --- llvm/lib/Analysis/CaptureTracking.cpp +++ llvm/lib/Analysis/CaptureTracking.cpp @@ -250,7 +250,8 @@ // launder.invariant.group only captures pointer by returning it, // so the pointer wasn't captured if returned pointer is not captured. // Note that adding similar special cases for intrinsics requires handling - // them in 'isEscapeSource' in BasicAA. + // them in GetUnderlyingObject in ValueTracking and DecomposeGEPExpression + // in BasicAliasAnalysis. if (CS.getIntrinsicID() == Intrinsic::launder_invariant_group) { AddUses(I); break; Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -3426,11 +3426,16 @@ // An alloca can't be further simplified. return V; } else { - if (auto CS = CallSite(V)) + if (auto CS = CallSite(V)) { if (Value *RV = CS.getReturnedArgOperand()) { V = RV; continue; } + if (CS.getIntrinsicID() == Intrinsic::launder_invariant_group) { + V = CS.getArgOperand(0); + continue; + } + } // See if InstructionSimplify knows any relevant tricks. if (Instruction *I = dyn_cast(V)) Index: llvm/test/Transforms/Inline/launder.invariant.group.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/Inline/launder.invariant.group.ll @@ -0,0 +1,31 @@ +; RUN: opt -S -inline < %s | FileCheck %s +; RUN: opt -S -O3 < %s | FileCheck %s + +; This test checks if value returned from the launder is considered aliasing +; with it's argument. Due to bug caused by handling launder in capture tracking +; sometimes it would be considered noalias. + +%struct.A = type <{ i32 (...)**, i32, [4 x i8] }> + +; CHECK: define i32 @bar(%struct.A* noalias +define i32 @bar(%struct.A* noalias) { +; CHECK-NOT: noalias + %2 = bitcast %struct.A* %0 to i8* + %3 = call i8* @llvm.launder.invariant.group.p0i8(i8* %2) + %4 = getelementptr inbounds i8, i8* %3, i64 8 + %5 = bitcast i8* %4 to i32* + store i32 42, i32* %5, align 8 + %6 = getelementptr inbounds %struct.A, %struct.A* %0, i64 0, i32 1 + %7 = load i32, i32* %6, align 8 + ret i32 %7 +} + +; CHECK-LABEL: define i32 @foo(%struct.A* noalias +define i32 @foo(%struct.A* noalias) { + ; CHECK-NOT: call i32 @bar( + ; CHECK-NOT: noalias + %2 = tail call i32 @bar(%struct.A* %0) + ret i32 %2 +} + +declare i8* @llvm.launder.invariant.group.p0i8(i8*)