/// getLocForWrite - Return a Location stored to by the specified instruction. /// If isRemovable returns true, this function and getLocForRead completely /// describe the memory operations for this instruction. static AliasAnalysis::Location getLocForWrite(Instruction *Inst, AliasAnalysis &AA) { if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) return AA.getLocation(SI); if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(Inst)) { // memcpy/memmove/memset. AliasAnalysis::Location Loc = AA.getLocationForDest(MI); // If we don't have target data around, an unknown size in Location means // that we should use the size of the pointee type. This isn't valid for // memset/memcpy, which writes more than an i8. if (Loc.Size == AliasAnalysis::UnknownSize && AA.getTargetData() == 0) return AliasAnalysis::Location(); return Loc; } IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst); if (II == 0) return AliasAnalysis::Location(); switch (II->getIntrinsicID()) { default: return AliasAnalysis::Location(); // Unhandled intrinsic. case Intrinsic::init_trampoline: // If we don't have target data around, an unknown size in Location means // that we should use the size of the pointee type. This isn't valid for // init.trampoline, which writes more than an i8. if (AA.getTargetData() == 0) return AliasAnalysis::Location(); // FIXME: We don't know the size of the trampoline, so we can't really // handle it here. return AliasAnalysis::Location(II->getArgOperand(0)); case Intrinsic::lifetime_end: { uint64_t Len = cast<ConstantInt>(II->getArgOperand(0))->getZExtValue(); return AliasAnalysis::Location(II->getArgOperand(1), Len); } } }
static uint64_t getPointerSize(Value *V, AliasAnalysis &AA) { const TargetData *TD = AA.getTargetData(); if (TD == 0) return AliasAnalysis::UnknownSize; if (AllocaInst *A = dyn_cast<AllocaInst>(V)) { // Get size information for the alloca if (ConstantInt *C = dyn_cast<ConstantInt>(A->getArraySize())) return C->getZExtValue() * TD->getTypeAllocSize(A->getAllocatedType()); return AliasAnalysis::UnknownSize; } assert(isa<Argument>(V) && "Expected AllocaInst or Argument!"); const PointerType *PT = cast<PointerType>(V->getType()); return TD->getTypeAllocSize(PT->getElementType()); }
static uint64_t getPointerSize(const Value *V, AliasAnalysis &AA) { const TargetData *TD = AA.getTargetData(); if (const CallInst *CI = extractMallocCall(V)) { if (const ConstantInt *C = dyn_cast<ConstantInt>(CI->getArgOperand(0))) return C->getZExtValue(); } if (const CallInst *CI = extractCallocCall(V)) { if (const ConstantInt *C1 = dyn_cast<ConstantInt>(CI->getArgOperand(0))) if (const ConstantInt *C2 = dyn_cast<ConstantInt>(CI->getArgOperand(1))) return (C1->getValue() * C2->getValue()).getZExtValue(); } if (TD == 0) return AliasAnalysis::UnknownSize; if (const AllocaInst *A = dyn_cast<AllocaInst>(V)) { // Get size information for the alloca if (const ConstantInt *C = dyn_cast<ConstantInt>(A->getArraySize())) return C->getZExtValue() * TD->getTypeAllocSize(A->getAllocatedType()); } if (const Argument *A = dyn_cast<Argument>(V)) { if (A->hasByValAttr()) if (PointerType *PT = dyn_cast<PointerType>(A->getType())) return TD->getTypeAllocSize(PT->getElementType()); } if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) { if (!GV->mayBeOverridden()) return TD->getTypeAllocSize(GV->getType()->getElementType()); } return AliasAnalysis::UnknownSize; }
/// isOverwrite - Return 'OverwriteComplete' if a store to the 'Later' location /// completely overwrites a store to the 'Earlier' location. /// 'OverwriteEnd' if the end of the 'Earlier' location is completely /// overwritten by 'Later', or 'OverwriteUnknown' if nothing can be determined static OverwriteResult isOverwrite(const AliasAnalysis::Location &Later, const AliasAnalysis::Location &Earlier, AliasAnalysis &AA, int64_t &EarlierOff, int64_t &LaterOff) { const Value *P1 = Earlier.Ptr->stripPointerCasts(); const Value *P2 = Later.Ptr->stripPointerCasts(); // If the start pointers are the same, we just have to compare sizes to see if // the later store was larger than the earlier store. if (P1 == P2) { // If we don't know the sizes of either access, then we can't do a // comparison. if (Later.Size == AliasAnalysis::UnknownSize || Earlier.Size == AliasAnalysis::UnknownSize) { // If we have no TargetData information around, then the size of the store // is inferrable from the pointee type. If they are the same type, then // we know that the store is safe. if (AA.getTargetData() == 0 && Later.Ptr->getType() == Earlier.Ptr->getType()) return OverwriteComplete; return OverwriteUnknown; } // Make sure that the Later size is >= the Earlier size. if (Later.Size >= Earlier.Size) return OverwriteComplete; } // Otherwise, we have to have size information, and the later store has to be // larger than the earlier one. if (Later.Size == AliasAnalysis::UnknownSize || Earlier.Size == AliasAnalysis::UnknownSize || AA.getTargetData() == 0) return OverwriteUnknown; // Check to see if the later store is to the entire object (either a global, // an alloca, or a byval argument). If so, then it clearly overwrites any // other store to the same object. const TargetData &TD = *AA.getTargetData(); const Value *UO1 = GetUnderlyingObject(P1, &TD), *UO2 = GetUnderlyingObject(P2, &TD); // If we can't resolve the same pointers to the same object, then we can't // analyze them at all. if (UO1 != UO2) return OverwriteUnknown; // If the "Later" store is to a recognizable object, get its size. uint64_t ObjectSize = getPointerSize(UO2, AA); if (ObjectSize != AliasAnalysis::UnknownSize) if (ObjectSize == Later.Size && ObjectSize >= Earlier.Size) return OverwriteComplete; // Okay, we have stores to two completely different pointers. Try to // decompose the pointer into a "base + constant_offset" form. If the base // pointers are equal, then we can reason about the two stores. EarlierOff = 0; LaterOff = 0; const Value *BP1 = GetPointerBaseWithConstantOffset(P1, EarlierOff, TD); const Value *BP2 = GetPointerBaseWithConstantOffset(P2, LaterOff, TD); // If the base pointers still differ, we have two completely different stores. if (BP1 != BP2) return OverwriteUnknown; // The later store completely overlaps the earlier store if: // // 1. Both start at the same offset and the later one's size is greater than // or equal to the earlier one's, or // // |--earlier--| // |-- later --| // // 2. The earlier store has an offset greater than the later offset, but which // still lies completely within the later store. // // |--earlier--| // |----- later ------| // // We have to be careful here as *Off is signed while *.Size is unsigned. if (EarlierOff >= LaterOff && Later.Size > Earlier.Size && uint64_t(EarlierOff - LaterOff) + Earlier.Size <= Later.Size) return OverwriteComplete; // The other interesting case is if the later store overwrites the end of // the earlier store // // |--earlier--| // |-- later --| // // In this case we may want to trim the size of earlier to avoid generating // writes to addresses which will definitely be overwritten later if (LaterOff > EarlierOff && LaterOff < int64_t(EarlierOff + Earlier.Size) && int64_t(LaterOff + Later.Size) >= int64_t(EarlierOff + Earlier.Size)) return OverwriteEnd; // Otherwise, they don't completely overlap. return OverwriteUnknown; }
/// isCompleteOverwrite - Return true if a store to the 'Later' location /// completely overwrites a store to the 'Earlier' location. static bool isCompleteOverwrite(const AliasAnalysis::Location &Later, const AliasAnalysis::Location &Earlier, AliasAnalysis &AA) { const Value *P1 = Earlier.Ptr->stripPointerCasts(); const Value *P2 = Later.Ptr->stripPointerCasts(); // If the start pointers are the same, we just have to compare sizes to see if // the later store was larger than the earlier store. if (P1 == P2) { // If we don't know the sizes of either access, then we can't do a // comparison. if (Later.Size == AliasAnalysis::UnknownSize || Earlier.Size == AliasAnalysis::UnknownSize) { // If we have no TargetData information around, then the size of the store // is inferrable from the pointee type. If they are the same type, then // we know that the store is safe. if (AA.getTargetData() == 0) return Later.Ptr->getType() == Earlier.Ptr->getType(); return false; } // Make sure that the Later size is >= the Earlier size. if (Later.Size < Earlier.Size) return false; return true; } // Otherwise, we have to have size information, and the later store has to be // larger than the earlier one. if (Later.Size == AliasAnalysis::UnknownSize || Earlier.Size == AliasAnalysis::UnknownSize || Later.Size <= Earlier.Size || AA.getTargetData() == 0) return false; // Check to see if the later store is to the entire object (either a global, // an alloca, or a byval argument). If so, then it clearly overwrites any // other store to the same object. const TargetData &TD = *AA.getTargetData(); const Value *UO1 = P1->getUnderlyingObject(), *UO2 = P2->getUnderlyingObject(); // If we can't resolve the same pointers to the same object, then we can't // analyze them at all. if (UO1 != UO2) return false; // If the "Later" store is to a recognizable object, get its size. if (isObjectPointerWithTrustworthySize(UO2)) { uint64_t ObjectSize = TD.getTypeAllocSize(cast<PointerType>(UO2->getType())->getElementType()); if (ObjectSize == Later.Size) return true; } // Okay, we have stores to two completely different pointers. Try to // decompose the pointer into a "base + constant_offset" form. If the base // pointers are equal, then we can reason about the two stores. int64_t Off1 = 0, Off2 = 0; const Value *BP1 = GetPointerBaseWithConstantOffset(P1, Off1, TD); const Value *BP2 = GetPointerBaseWithConstantOffset(P2, Off2, TD); // If the base pointers still differ, we have two completely different stores. if (BP1 != BP2) return false; // Otherwise, we might have a situation like: // store i16 -> P + 1 Byte // store i32 -> P // In this case, we see if the later store completely overlaps all bytes // stored by the previous store. if (Off1 < Off2 || // Earlier starts before Later. Off1+Earlier.Size > Off2+Later.Size) // Earlier goes beyond Later. return false; // Otherwise, we have complete overlap. return true; }