Beispiel #1
0
/// optimizeCheck - replace the given check CallInst with the check's fast
/// version if all the source memory objects can be found and it is obvious
/// that none of them have been freed at the point where the check is made.
/// Returns the new call if possible and NULL otherwise.
///
/// This currently works only with memory objects that can't be freed:
/// * global variables
/// * allocas that trivially have function scope
/// * byval arguments
///
bool ExactCheckOpt::optimizeCheck(CallInst *CI, CheckInfoType *Info) {
  // Examined values
  SmallSet<Value*, 16> Visited;
  // Potential memory objects
  SmallSet<Value*, 4> Objects;

  std::queue<Value*> Q;
  // Start from the the pointer operand
  Value *StartPtr = CI->getArgOperand(Info->PtrArgNo)->stripPointerCasts();
  Q.push(StartPtr);

  // Use BFS to find all potential memory objects
  while(!Q.empty()) {
    Value *o = Q.front()->stripPointerCasts();
    Q.pop();
    if(Visited.count(o))
      continue;
    Visited.insert(o);

    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(o)) {
      if (CE->getOpcode() == Instruction::GetElementPtr) {
        Q.push(CE->getOperand(0));
      } else {
        // Exit early if any of the objects are unsupported.
        if (!isSimpleMemoryObject(o))
          return false;
        Objects.insert(o);
      }
    } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(o)) {
      Q.push(GEP->getPointerOperand());
      // It is fine to ignore the case of indexing into null with a pointer
      // because that case is invalid for LLVM-aware objects such as allocas,
      // globals, and objects pointed to by noalias pointers.
    } else if(PHINode *PHI = dyn_cast<PHINode>(o)) {
      for (unsigned i = 0, num = PHI->getNumIncomingValues(); i != num; ++i)
        Q.push(PHI->getIncomingValue(i));
    } else if (SelectInst *SI = dyn_cast<SelectInst>(o)) {
      Q.push(SI->getTrueValue());
      Q.push(SI->getFalseValue());
    } else {
      // Exit early if any of the objects are unsupported.
      if (!isSimpleMemoryObject(o))
        return false;
      Objects.insert(o);
    }
  }

  // Mapping from the initial value to the corresponding size and void pointer:
  // * memory object -> its size and pointer
  // * phi/select -> corresponding phi/select for the sizes and pointers
  // * anything else -> the corresponding size and pointer on the path
  std::map <Value*, PtrSizePair> M;

  Module &Mod = *CI->getParent()->getParent()->getParent();
  Type *SizeTy = getSizeType(Info, Mod);

  // Add non-instruction non-constant allocation object pointers to the front
  // of the function's entry block.
  BasicBlock &EntryBlock = CI->getParent()->getParent()->getEntryBlock();
  Instruction *FirstInsertionPoint = ++BasicBlock::iterator(EntryBlock.begin());

  for (SmallSet<Value*, 16>::const_iterator It = Objects.begin(),
       E = Objects.end();
       It != E;
       ++It) {
    // Obj is a memory object pointer: alloca, argument, load, callinst, etc.
    Value *Obj = *It;

    // Insert instruction-based allocation pointers just after the allocation.
    Instruction *InsertBefore = FirstInsertionPoint;
    if (Instruction *I = dyn_cast<Instruction>(Obj))
      InsertBefore = ++BasicBlock::iterator(I);
    IRBuilder<> Builder(InsertBefore);

    SizeOffsetEvalType SizeOffset = ObjSizeEval->compute(Obj);
    assert(ObjSizeEval->bothKnown(SizeOffset));
    assert(dyn_cast<ConstantInt>(SizeOffset.second)->isZero());
    Value *Size = Builder.CreateIntCast(SizeOffset.first, SizeTy,
                                        /*isSigned=*/false);

    Value *Ptr = Builder.CreatePointerCast(Obj, VoidPtrTy);
    M[Obj] = std::make_pair(Ptr, Size);
  }

  // Create the rest of the size values and object pointers.
  // The phi nodes will be finished later.
  for (SmallSet<Value*, 16>::const_iterator I = Visited.begin(),
       E = Visited.end();
       I != E;
       ++I) {
    getPtrAndSize(*I, SizeTy, M);
  }

  // Finalize the phi nodes.
  for (SmallSet<Value*, 16>::const_iterator I = Visited.begin(),
       E = Visited.end();
       I != E;
       ++I) {
    if (PHINode *PHI = dyn_cast<PHINode>(*I)) {
      assert(M.count(PHI));
      PHINode *PtrPHI = cast<PHINode>(M[PHI].first);
      PHINode *SizePHI = cast<PHINode>(M[PHI].second);

      for(unsigned i = 0, num = PHI->getNumIncomingValues(); i != num; ++i) {
        Value *IncomingValue = PHI->getIncomingValue(i)->stripPointerCasts();
        assert(M.count(IncomingValue));

        PtrPHI->addIncoming(M[IncomingValue].first, PHI->getIncomingBlock(i));
        SizePHI->addIncoming(M[IncomingValue].second, PHI->getIncomingBlock(i));
      }
    }
  }

  // Insert the fast version of the check just before the regular version.
  assert(M.count(StartPtr) && "The memory object and its size should be known");
  createFastCheck(Info, CI, M[StartPtr].first, M[StartPtr].second);
  return true;
}