Exemple #1
0
/// Determine the number of iterations the loop is at most executed. The loop
/// might contain early exits so this is the maximum if no early exits are
/// taken.
static Optional<uint64_t> getMaxLoopTripCount(SILLoop *Loop,
                                              SILBasicBlock *Preheader,
                                              SILBasicBlock *Header,
                                              SILBasicBlock *Latch) {

  // Skip a split backedge.
  SILBasicBlock *OrigLatch = Latch;
  if (!Loop->isLoopExiting(Latch) && !(Latch = Latch->getSinglePredecessor()))
    return None;
  if (!Loop->isLoopExiting(Latch))
    return None;

  // Get the loop exit condition.
  auto *CondBr = dyn_cast<CondBranchInst>(Latch->getTerminator());
  if (!CondBr)
    return None;

  // Match an add 1 recurrence.
  SILArgument *RecArg;
  IntegerLiteralInst *End;
  SILValue RecNext;

  if (!match(CondBr->getCondition(),
             m_BuiltinInst(BuiltinValueKind::ICMP_EQ, m_SILValue(RecNext),
                           m_IntegerLiteralInst(End))))
    return None;
  if (!match(RecNext,
             m_TupleExtractInst(m_ApplyInst(BuiltinValueKind::SAddOver,
                                            m_SILArgument(RecArg), m_One()),
                                0)))
    return None;

  if (RecArg->getParent() != Header)
    return None;

  auto *Start = dyn_cast_or_null<IntegerLiteralInst>(
      RecArg->getIncomingValue(Preheader).getDef());
  if (!Start)
    return None;

  if (RecNext != RecArg->getIncomingValue(OrigLatch))
    return None;

  auto StartVal = Start->getValue();
  auto EndVal = End->getValue();
  if (StartVal.sgt(EndVal))
    return None;

  auto Dist = EndVal - StartVal;
  if (Dist.getBitWidth() > 64)
    return None;

  if (Dist == 0)
    return None;

  return Dist.getZExtValue();
}
Exemple #2
0
void EpilogueARCContext::initializeDataflow() {
  for (auto &B : *F) {
    // Find the exit blocks.
    if (isInterestedFunctionExitingBlock(&B)) {
      ExitBlocks.insert(&B);
    }
    // Allocate the storage.
    EpilogueARCBlockStates[&B] =
              new (BPA.Allocate()) EpilogueARCBlockState();
  }

  // Split the SILargument into local arguments to each specific basic block.
  llvm::SmallVector<SILValue, 4> ToProcess;
  llvm::DenseSet<SILValue> Processed;
  ToProcess.push_back(Arg);
  while (!ToProcess.empty()) {
    SILValue CArg = ToProcess.pop_back_val();
    if (!CArg)
      continue;
    if (Processed.find(CArg) != Processed.end())
       continue;
    Processed.insert(CArg);
    SILArgument *A = dyn_cast<SILArgument>(CArg);
    if (A && !A->isFunctionArg()) {
      // Find predecessor and break the SILArgument to predecessors.
      for (auto X : A->getParent()->getPreds()) {
        // Try to find the predecessor edge-value.
        SILValue IA = A->getIncomingValue(X);
        EpilogueARCBlockStates[X]->LocalArg = IA;
        // Maybe the edge value is another SILArgument.
        ToProcess.push_back(IA);
      }
    }
  }
}
Exemple #3
0
void
ConsumedResultToEpilogueRetainMatcher::
findMatchingRetains(SILBasicBlock *BB) {
  // Iterate over the instructions post-order and find retains associated with
  // return value.
  SILValue RV = SILValue();
  for (auto II = BB->rbegin(), IE = BB->rend(); II != IE; ++II) {
    if (ReturnInst *RI = dyn_cast<ReturnInst>(&*II)) {
      RV = RI->getOperand();
      break;
    }
  }

  // Somehow, we managed not to find a return value.
  if (!RV)
    return;

  // OK. we've found the return value, now iterate on the CFG to find all the
  // post-dominating retains.
  //
  // The ConsumedArgToEpilogueReleaseMatcher finds the final releases
  // in the following way. 
  //
  // 1. If an instruction, which is not releaseinst nor releasevalue, that
  // could decrement reference count is found. bail out.
  //
  // 2. If a release is found and the release that can not be mapped to any
  // @owned argument. bail as this release may well be the final release of
  // an @owned argument, but somehow rc-identity fails to prove that.
  //
  // 3. A release that is mapped to an argument which already has a release
  // that overlaps with this release. This release for sure is not the final
  // release.
  constexpr unsigned WorkListMaxSize = 4;

  llvm::DenseSet<SILBasicBlock *> RetainFrees;
  llvm::SmallVector<BasicBlockRetainValue, 4> WorkList;
  llvm::DenseSet<SILBasicBlock *> HandledBBs;
  WorkList.push_back(std::make_pair(BB, RV));
  HandledBBs.insert(BB);
  while (!WorkList.empty()) {
    // Too many blocks ?.
    if (WorkList.size() > WorkListMaxSize) {
      EpilogueRetainInsts.clear();
      return;
    }

    // Try to find a retain %value in this basic block.
    auto R = WorkList.pop_back_val();
    RetainKindValue Kind = findMatchingRetainsInBasicBlock(R.first, R.second);

    // We've found a retain on this path.
    if (Kind.first == FindRetainKind::Found) { 
      EpilogueRetainInsts.push_back(Kind.second);
      continue;
    }

    // There is a MayDecrement instruction.
    if (Kind.first == FindRetainKind::Blocked) {
      EpilogueRetainInsts.clear();
      return;
    }

    // There is a self-recursion. Use the apply instruction as the retain.
    if (Kind.first == FindRetainKind::Recursion) {
      EpilogueRetainInsts.push_back(Kind.second);
      continue;
    }
  
    // Did not find a retain in this block, try to go to its predecessors.
    if (Kind.first == FindRetainKind::None) {
      // We can not find a retain in a block with no predecessors.
      if (R.first->getPreds().begin() == R.first->getPreds().end()) {
        EpilogueRetainInsts.clear();
        return;
      }

      // This block does not have a retain.
      RetainFrees.insert(R.first);

      // If this is a SILArgument of current basic block, we can split it up to
      // values in the predecessors.
      SILArgument *SA = dyn_cast<SILArgument>(R.second);
      if (SA && SA->getParent() != R.first)
        SA = nullptr;

      for (auto X : R.first->getPreds()) {
        if (HandledBBs.find(X) != HandledBBs.end())
          continue;
        // Try to use the predecessor edge-value.
        if (SA && SA->getIncomingValue(X)) {
          WorkList.push_back(std::make_pair(X, SA->getIncomingValue(X)));
        }
        else 
          WorkList.push_back(std::make_pair(X, R.second));
   
        HandledBBs.insert(X);
      }
    }
  }

  // Lastly, check whether all the successor blocks are retain-free.
  if (!isTransitiveSuccessorsRetainFree(RetainFrees))
    EpilogueRetainInsts.clear();

  // At this point, we've either failed to find any epilogue retains or
  // all the post-dominating epilogue retains.
}