- const TargetLibraryInfo &TLI = getAnalysis<TargetLibraryInfo>();
- ModRefResult Min = ModRef;
-
- // Finally, handle specific knowledge of intrinsics.
- const IntrinsicInst *II = dyn_cast<IntrinsicInst>(CS.getInstruction());
- if (II != 0)
- switch (II->getIntrinsicID()) {
- default: break;
- case Intrinsic::memcpy:
- case Intrinsic::memmove: {
- uint64_t Len = UnknownSize;
- if (ConstantInt *LenCI = dyn_cast<ConstantInt>(II->getArgOperand(2)))
- Len = LenCI->getZExtValue();
- Value *Dest = II->getArgOperand(0);
- Value *Src = II->getArgOperand(1);
- // If it can't overlap the source dest, then it doesn't modref the loc.
- if (isNoAlias(Location(Dest, Len), Loc)) {
- if (isNoAlias(Location(Src, Len), Loc))
- return NoModRef;
- // If it can't overlap the dest, then worst case it reads the loc.
- Min = Ref;
- } else if (isNoAlias(Location(Src, Len), Loc)) {
- // If it can't overlap the source, then worst case it mutates the loc.
- Min = Mod;
- }
- break;
- }
- case Intrinsic::memset:
- // Since memset is 'accesses arguments' only, the AliasAnalysis base class
- // will handle it for the variable length case.
- if (ConstantInt *LenCI = dyn_cast<ConstantInt>(II->getArgOperand(2))) {
- uint64_t Len = LenCI->getZExtValue();
- Value *Dest = II->getArgOperand(0);
- if (isNoAlias(Location(Dest, Len), Loc))
- return NoModRef;
- }
- // We know that memset doesn't load anything.
- Min = Mod;
- break;
- case Intrinsic::lifetime_start:
- case Intrinsic::lifetime_end:
- case Intrinsic::invariant_start: {
- uint64_t PtrSize =
- cast<ConstantInt>(II->getArgOperand(0))->getZExtValue();
- if (isNoAlias(Location(II->getArgOperand(1),
- PtrSize,
- II->getMetadata(LLVMContext::MD_tbaa)),
- Loc))
- return NoModRef;
- break;
- }
- case Intrinsic::invariant_end: {
- uint64_t PtrSize =
- cast<ConstantInt>(II->getArgOperand(1))->getZExtValue();
- if (isNoAlias(Location(II->getArgOperand(2),
- PtrSize,
- II->getMetadata(LLVMContext::MD_tbaa)),
- Loc))
- return NoModRef;
- break;
- }
- case Intrinsic::arm_neon_vld1: {
- // LLVM's vld1 and vst1 intrinsics currently only support a single
- // vector register.
- uint64_t Size =
- TD ? TD->getTypeStoreSize(II->getType()) : UnknownSize;
- if (isNoAlias(Location(II->getArgOperand(0), Size,
- II->getMetadata(LLVMContext::MD_tbaa)),
- Loc))
- return NoModRef;
- break;
- }
- case Intrinsic::arm_neon_vst1: {
- uint64_t Size =
- TD ? TD->getTypeStoreSize(II->getArgOperand(1)->getType()) : UnknownSize;
- if (isNoAlias(Location(II->getArgOperand(0), Size,
- II->getMetadata(LLVMContext::MD_tbaa)),
- Loc))
- return NoModRef;
- break;
- }
- }
-
- // We can bound the aliasing properties of memset_pattern16 just as we can
- // for memcpy/memset. This is particularly important because the
- // LoopIdiomRecognizer likes to turn loops into calls to memset_pattern16
- // whenever possible.
- else if (TLI.has(LibFunc::memset_pattern16) &&
- CS.getCalledFunction() &&
- CS.getCalledFunction()->getName() == "memset_pattern16") {
- const Function *MS = CS.getCalledFunction();
- FunctionType *MemsetType = MS->getFunctionType();
- if (!MemsetType->isVarArg() && MemsetType->getNumParams() == 3 &&
- isa<PointerType>(MemsetType->getParamType(0)) &&
- isa<PointerType>(MemsetType->getParamType(1)) &&
- isa<IntegerType>(MemsetType->getParamType(2))) {
- uint64_t Len = UnknownSize;
- if (const ConstantInt *LenCI = dyn_cast<ConstantInt>(CS.getArgument(2)))
- Len = LenCI->getZExtValue();
- const Value *Dest = CS.getArgument(0);
- const Value *Src = CS.getArgument(1);
- // If it can't overlap the source dest, then it doesn't modref the loc.
- if (isNoAlias(Location(Dest, Len), Loc)) {
- // Always reads 16 bytes of the source.
- if (isNoAlias(Location(Src, 16), Loc))
- return NoModRef;
- // If it can't overlap the dest, then worst case it reads the loc.
- Min = Ref;
- // Always reads 16 bytes of the source.
- } else if (isNoAlias(Location(Src, 16), Loc)) {
- // If it can't overlap the source, then worst case it mutates the loc.
- Min = Mod;
- }
- }
- }