void BlockState::processWrite(RLEContext &Ctx, SILInstruction *I, SILValue Mem,
                              SILValue Val, RLEKind Kind) {
  // Initialize the LSLocation.
  LSLocation L(Mem);

  // If we cant figure out the Base or Projection Path for the write,
  // process it as an unknown memory instruction.
  if (!L.isValid()) {
    // we can ignore unknown store instructions if we are computing the
    // AvailSetMax.
    if (!isComputeAvailSetMax(Kind)) {
      processUnknownWriteInst(Ctx, I, Kind);
    }
    return;
  }

  // Expand the given location and val into individual fields and process
  // them as separate writes.
  LSLocationList Locs;
  LSLocation::expand(L, &I->getModule(), Locs, Ctx.getTE());

  if (isComputeAvailSetMax(Kind)) {
    for (unsigned i = 0; i < Locs.size(); ++i) {
      updateMaxAvailForwardSetForWrite(Ctx, Ctx.getLocationBit(Locs[i]));
    }
    return;
  }

  // Are we computing the genset and killset ?
  if (isComputeAvailGenKillSet(Kind)) {
    for (unsigned i = 0; i < Locs.size(); ++i) {
      updateGenKillSetForWrite(Ctx, Ctx.getLocationBit(Locs[i]));
    }
    return;
  }

  // Are we computing available set ?
  if (isComputeAvailSet(Kind)) {
    for (unsigned i = 0; i < Locs.size(); ++i) {
      updateForwardSetForWrite(Ctx, Ctx.getLocationBit(Locs[i]));
    }
    return;
  }

  // Are we computing available value or performing RLE?
  if (isComputeAvailValue(Kind) || isPerformingRLE(Kind)) {
    LSValueList Vals;
    LSValue::expand(Val, &I->getModule(), Vals, Ctx.getTE());
    for (unsigned i = 0; i < Locs.size(); ++i) {
      updateForwardSetAndValForWrite(Ctx, Ctx.getLocationBit(Locs[i]),
                                     Ctx.getValueBit(Vals[i]));
    }
    return;
  }

  llvm_unreachable("Unknown RLE compute kind");
}
void BlockState::processRead(RLEContext &Ctx, SILInstruction *I, SILValue Mem,
                             SILValue Val, RLEKind Kind) {
  // Initialize the LSLocation.
  LSLocation L(Mem);

  // If we cant figure out the Base or Projection Path for the read, simply
  // ignore it for now.
  if (!L.isValid())
    return;

  // Expand the given LSLocation and Val into individual fields and process
  // them as separate reads.
  LSLocationList Locs;
  LSLocation::expand(L, &I->getModule(), Locs, Ctx.getTE());

  // Are we computing available set ?.
  if (isComputeAvailSet(Kind)) {
    for (auto &X : Locs) {
      if (isTrackingLSLocation(Ctx.getLSLocationBit(X)))
        continue;
      updateForwardSetForRead(Ctx, Ctx.getLSLocationBit(X));
    }
    return;
  }

  // Are we computing available values ?.
  bool CanForward = true;
  if (isComputeAvailValue(Kind) || isPerformRLE(Kind)) {
    LSValueList Vals;
    LSValue::expand(Val, &I->getModule(), Vals, Ctx.getTE());
    for (unsigned i = 0; i < Locs.size(); ++i) {
      if (isTrackingLSLocation(Ctx.getLSLocationBit(Locs[i])))
        continue;
      updateForwardValForRead(Ctx, Ctx.getLSLocationBit(Locs[i]),
                              Ctx.getLSValueBit(Vals[i]));
      CanForward = false;
    }
  }

  // Simply return if we are not performing RLE or we do not have all the
  // values available to perform RLE.
  if (!isPerformRLE(Kind) || !CanForward)
    return;

  // Lastly, forward value to the load.
  setupRLE(Ctx, I, Mem);
}
SILValue BlockState::reduceValuesAtEndOfBlock(RLEContext &Ctx, LSLocation &L) {
  // First, collect current available locations and their corresponding values
  // into a map.
  LSLocationValueMap Values;

  LSLocationList Locs;
  LSLocation::expand(L, &BB->getModule(), Locs, Ctx.getTE());

  // Find the values that this basic block defines and the locations which
  // we do not have a concrete value in the current basic block.
  ValueTableMap &OTM = getForwardValOut();
  for (unsigned i = 0; i < Locs.size(); ++i) {
    Values[Locs[i]] = Ctx.getLSValue(OTM[Ctx.getLSLocationBit(Locs[i])]);
  }

  // Second, reduce the available values into a single SILValue we can use to
  // forward.
  SILValue TheForwardingValue;
  TheForwardingValue = LSValue::reduce(L, &BB->getModule(), Values,
                                       BB->getTerminator(), Ctx.getTE());
  /// Return the forwarding value.
  return TheForwardingValue;
}
bool BlockState::setupRLE(RLEContext &Ctx, SILInstruction *I, SILValue Mem) {
  // Try to construct a SILValue for the current LSLocation.
  //
  // Collect the locations and their corresponding values into a map.
  LSLocation L(Mem);
  LSLocationValueMap Values;
  // Use the ForwardValIn as we are currently processing the basic block.
  if (!Ctx.gatherLocationValues(I->getParent(), L, Values, getForwardValIn()))
    return false;

  // Reduce the available values into a single SILValue we can use to forward.
  SILModule *Mod = &I->getModule();
  SILValue TheForwardingValue;
  TheForwardingValue = LSValue::reduce(L, Mod, Values, I, Ctx.getTE());
  if (!TheForwardingValue)
    return false;

  // Now we have the forwarding value, record it for forwarding!.
  //
  // NOTE: we do not perform the RLE right here because doing so could introduce
  // new LSLocations.
  //
  // e.g.
  //    %0 = load %x
  //    %1 = load %x
  //    %2 = extract_struct %1, #a
  //    %3 = load %2
  //
  // If we perform the RLE and replace %1 with %0, we end up having a memory
  // location we do not have before, i.e. Base == %0, and Path == #a.
  //
  // We may be able to add the LSLocation to the vault, but it gets
  // complicated very quickly, e.g. we need to resize the bit vectors size,
  // etc.
  //
  // However, since we already know the instruction to replace and the value to
  // replace it with, we can record it for now and forwarded it after all the
  // forwardable values are recorded in the function.
  //
  RedundantLoads[I] = TheForwardingValue;
  return true;
}
BlockState::ValueState BlockState::getValueStateAtEndOfBlock(RLEContext &Ctx,
                                                             LSLocation &L) {
  LSLocationList Locs;
  LSLocation::expand(L, &BB->getModule(), Locs, Ctx.getTE());

  // Find number of covering value and concrete values for the locations
  // expanded from the given location.
  unsigned CSCount = 0, CTCount = 0;
  ValueTableMap &OTM = getForwardValOut();
  for (auto &X : Locs) {
    LSValue &V = Ctx.getLSValue(OTM[Ctx.getLSLocationBit(X)]);
    if (V.isCoveringValue()) {
      ++CSCount;
      continue;
    }
    ++CTCount;
  }

  if (CSCount == Locs.size())
    return ValueState::CoverValues;
  if (CTCount == Locs.size())
    return ValueState::ConcreteValues;
  return ValueState::CoverAndConcreteValues;
}