예제 #1
0
/// 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());
}
예제 #3
0
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;
}
예제 #4
0
/// 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;
}