Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -2960,12 +2960,15 @@ return true; } - // For gc.relocate, look through relocations - if (const IntrinsicInst *I = dyn_cast(V)) + if (const IntrinsicInst *I = dyn_cast(V)) { if (I->getIntrinsicID() == Intrinsic::experimental_gc_relocate) { + // For gc.relocate, look through relocations GCRelocateOperands RelocateInst(I); return isDereferenceablePointer(RelocateInst.derivedPtr(), DL, Visited); + } else if (I->getIntrinsicID() == Intrinsic::noalias) { + return isDereferenceablePointer(I->getOperand(0), DL, Visited); } + } if (const AddrSpaceCastInst *ASC = dyn_cast(V)) return isDereferenceablePointer(ASC->getOperand(0), DL, Visited); @@ -2983,7 +2986,8 @@ Type *Ty = VTy->getPointerElementType(); if (Ty->isSized()) { APInt Offset(DL.getTypeStoreSizeInBits(VTy), 0); - const Value *BV = V->stripAndAccumulateInBoundsConstantOffsets(DL, Offset); + const Value *BV = V->stripAndAccumulateInBoundsConstantOffsets(DL, Offset, + /*LookThroughNoAlias*/true); if (Offset.isNonNegative()) if (isDereferenceableFromAttribute(BV, Offset, Ty, DL)) Index: test/Analysis/ValueTracking/memory-dereferenceable.ll =================================================================== --- test/Analysis/ValueTracking/memory-dereferenceable.ll +++ test/Analysis/ValueTracking/memory-dereferenceable.ll @@ -25,10 +25,17 @@ %tok = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 addrspace(1)* %dparam) %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %tok, i32 4, i32 4) %load4 = load i32, i32 addrspace(1)* %relocate - %nparam = getelementptr i32, i32 addrspace(1)* %dparam, i32 5 + %dpa = call i32 addrspace(1)* @llvm.noalias.p1i32(i32 addrspace(1)* %dparam, metadata !1) + %nparam = getelementptr i32, i32 addrspace(1)* %dpa, i32 5 %load5 = load i32, i32 addrspace(1)* %nparam ret void } declare i32 @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()*, i32, i32, ...) declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32, i32, i32) + +declare i32 addrspace(1)* @llvm.noalias.p1i32(i32 addrspace(1)*, metadata) nounwind + +!0 = !{!0, !"some domain"} +!1 = !{!1, !0, !"some scope"} +