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; }