Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/Analysis/ValueTracking.cpp
Show First 20 Lines • Show All 602 Lines • ▼ Show 20 Lines | if (Function *F = CI->getCalledFunction()) | ||||
case Intrinsic::sideeffect: | case Intrinsic::sideeffect: | ||||
case Intrinsic::dbg_declare: | case Intrinsic::dbg_declare: | ||||
case Intrinsic::dbg_value: | case Intrinsic::dbg_value: | ||||
case Intrinsic::dbg_label: | case Intrinsic::dbg_label: | ||||
case Intrinsic::invariant_start: | case Intrinsic::invariant_start: | ||||
case Intrinsic::invariant_end: | case Intrinsic::invariant_end: | ||||
case Intrinsic::lifetime_start: | case Intrinsic::lifetime_start: | ||||
case Intrinsic::lifetime_end: | case Intrinsic::lifetime_end: | ||||
case Intrinsic::noalias_decl: | |||||
case Intrinsic::noalias: | case Intrinsic::noalias: | ||||
case Intrinsic::provenance_noalias: | |||||
case Intrinsic::noalias_arg_guard: | |||||
case Intrinsic::noalias_copy_guard: | |||||
case Intrinsic::objectsize: | case Intrinsic::objectsize: | ||||
case Intrinsic::ptr_annotation: | case Intrinsic::ptr_annotation: | ||||
case Intrinsic::var_annotation: | case Intrinsic::var_annotation: | ||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 3,472 Lines • ▼ Show 20 Lines | if (isIntrinsicReturningPointerAliasingArgumentWithoutCapturing( | ||||
return Call->getArgOperand(0); | return Call->getArgOperand(0); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
bool llvm::isIntrinsicReturningPointerAliasingArgumentWithoutCapturing( | bool llvm::isIntrinsicReturningPointerAliasingArgumentWithoutCapturing( | ||||
const CallBase *Call, bool MustPreserveNullness) { | const CallBase *Call, bool MustPreserveNullness) { | ||||
switch (Call->getIntrinsicID()) { | switch (Call->getIntrinsicID()) { | ||||
case Intrinsic::launder_invariant_group: | case Intrinsic::launder_invariant_group: | ||||
case Intrinsic::noalias_arg_guard: | |||||
case Intrinsic::noalias_copy_guard: | |||||
case Intrinsic::strip_invariant_group: | case Intrinsic::strip_invariant_group: | ||||
case Intrinsic::aarch64_irg: | case Intrinsic::aarch64_irg: | ||||
case Intrinsic::aarch64_tagp: | case Intrinsic::aarch64_tagp: | ||||
return true; | return true; | ||||
case Intrinsic::ptrmask: | case Intrinsic::ptrmask: | ||||
return !MustPreserveNullness; | return !MustPreserveNullness; | ||||
default: | default: | ||||
return false; | return false; | ||||
Show All 23 Lines | static bool isSameUnderlyingObjectInLoop(const PHINode *PN, | ||||
// ... | // ... | ||||
if (auto *Load = dyn_cast<LoadInst>(PrevValue)) | if (auto *Load = dyn_cast<LoadInst>(PrevValue)) | ||||
if (!L->isLoopInvariant(Load->getPointerOperand())) | if (!L->isLoopInvariant(Load->getPointerOperand())) | ||||
return false; | return false; | ||||
return true; | return true; | ||||
} | } | ||||
Value *llvm::GetUnderlyingObject(Value *V, const DataLayout &DL, | Value *llvm::GetUnderlyingObject(Value *V, const DataLayout &DL, | ||||
unsigned MaxLookup) { | unsigned MaxLookup, | ||||
SmallVectorImpl<Instruction *> *NoAlias) { | |||||
if (!V->getType()->isPointerTy()) | if (!V->getType()->isPointerTy()) | ||||
return V; | return V; | ||||
for (unsigned Count = 0; MaxLookup == 0 || Count < MaxLookup; ++Count) { | for (unsigned Count = 0; MaxLookup == 0 || Count < MaxLookup; ++Count) { | ||||
if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) { | if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) { | ||||
V = GEP->getPointerOperand(); | V = GEP->getPointerOperand(); | ||||
} else if (Operator::getOpcode(V) == Instruction::BitCast || | } else if (Operator::getOpcode(V) == Instruction::BitCast || | ||||
Operator::getOpcode(V) == Instruction::AddrSpaceCast) { | Operator::getOpcode(V) == Instruction::AddrSpaceCast) { | ||||
V = cast<Operator>(V)->getOperand(0); | V = cast<Operator>(V)->getOperand(0); | ||||
if (!V->getType()->isPointerTy()) | if (!V->getType()->isPointerTy()) | ||||
return V; | return V; | ||||
} else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) { | } else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) { | ||||
if (GA->isInterposable()) | if (GA->isInterposable()) | ||||
return V; | return V; | ||||
V = GA->getAliasee(); | V = GA->getAliasee(); | ||||
} else { | } else { | ||||
if (auto *PHI = dyn_cast<PHINode>(V)) { | if (auto *PHI = dyn_cast<PHINode>(V)) { | ||||
// Look through single-arg phi nodes created by LCSSA. | // Look through single-arg phi nodes created by LCSSA. | ||||
if (PHI->getNumIncomingValues() == 1) { | if (PHI->getNumIncomingValues() == 1) { | ||||
V = PHI->getIncomingValue(0); | V = PHI->getIncomingValue(0); | ||||
continue; | continue; | ||||
} | } | ||||
} else if (auto *Call = dyn_cast<CallBase>(V)) { | } else if (auto *Call = dyn_cast<CallBase>(V)) { | ||||
if (NoAlias) { | |||||
// We are gathering information for ScopedAANoAlias - | |||||
// Look through noalias and provenance.noalias intrinsic | |||||
if (Call->getIntrinsicID() == Intrinsic::provenance_noalias || | |||||
Call->getIntrinsicID() == Intrinsic::noalias) { | |||||
NoAlias->push_back(Call); | |||||
V = Call->getArgOperand(0); | |||||
continue; | |||||
} | |||||
// Look trough noalias.arg.guard, and follow the ptr_provenance | |||||
if (Call->getIntrinsicID() == Intrinsic::noalias_arg_guard) { | |||||
V = Call->getArgOperand(1); | |||||
continue; | |||||
} | |||||
} else { | |||||
// We are not gathering information for SCopedAANoAlias - | |||||
// Look through noalias.arg.guard and follow the pointer path | |||||
if (Call->getIntrinsicID() == Intrinsic::noalias_arg_guard) { | |||||
V = Call->getArgOperand(0); | |||||
continue; | |||||
} | |||||
} | |||||
// CaptureTracking can know about special capturing properties of some | // CaptureTracking can know about special capturing properties of some | ||||
// intrinsics like launder.invariant.group, that can't be expressed with | // intrinsics like launder.invariant.group, that can't be expressed with | ||||
// the attributes, but have properties like returning aliasing pointer. | // the attributes, but have properties like returning aliasing pointer. | ||||
// Because some analysis may assume that nocaptured pointer is not | // Because some analysis may assume that nocaptured pointer is not | ||||
// returned from some special intrinsic (because function would have to | // returned from some special intrinsic (because function would have to | ||||
// be marked with returns attribute), it is crucial to use this function | // be marked with returns attribute), it is crucial to use this function | ||||
// because it should be in sync with CaptureTracking. Not using it may | // because it should be in sync with CaptureTracking. Not using it may | ||||
// cause weird miscompilations where 2 aliasing pointers are assumed to | // cause weird miscompilations where 2 aliasing pointers are assumed to | ||||
Show All 9 Lines | for (unsigned Count = 0; MaxLookup == 0 || Count < MaxLookup; ++Count) { | ||||
assert(V->getType()->isPointerTy() && "Unexpected operand type!"); | assert(V->getType()->isPointerTy() && "Unexpected operand type!"); | ||||
} | } | ||||
return V; | return V; | ||||
} | } | ||||
void llvm::GetUnderlyingObjects(const Value *V, | void llvm::GetUnderlyingObjects(const Value *V, | ||||
SmallVectorImpl<const Value *> &Objects, | SmallVectorImpl<const Value *> &Objects, | ||||
const DataLayout &DL, LoopInfo *LI, | const DataLayout &DL, LoopInfo *LI, | ||||
unsigned MaxLookup) { | unsigned MaxLookup, | ||||
SmallVectorImpl<Instruction *> *NoAlias) { | |||||
SmallPtrSet<const Value *, 4> Visited; | SmallPtrSet<const Value *, 4> Visited; | ||||
SmallVector<const Value *, 4> Worklist; | SmallVector<const Value *, 4> Worklist; | ||||
Worklist.push_back(V); | Worklist.push_back(V); | ||||
do { | do { | ||||
const Value *P = Worklist.pop_back_val(); | const Value *P = Worklist.pop_back_val(); | ||||
P = GetUnderlyingObject(P, DL, MaxLookup); | P = GetUnderlyingObject(P, DL, MaxLookup, NoAlias); | ||||
if (!Visited.insert(P).second) | if (!Visited.insert(P).second) | ||||
continue; | continue; | ||||
if (auto *SI = dyn_cast<SelectInst>(P)) { | if (auto *SI = dyn_cast<SelectInst>(P)) { | ||||
Worklist.push_back(SI->getTrueValue()); | Worklist.push_back(SI->getTrueValue()); | ||||
Worklist.push_back(SI->getFalseValue()); | Worklist.push_back(SI->getFalseValue()); | ||||
continue; | continue; | ||||
▲ Show 20 Lines • Show All 2,336 Lines • Show Last 20 Lines |