void BlockState::mergePredecessorAvailSetAndValue(RLEContext &Ctx) { // Clear the state if the basic block has no predecessor. if (BB->getPreds().begin() == BB->getPreds().end()) { ForwardSetIn.reset(); ForwardValIn.clear(); return; } auto Iter = BB->pred_begin(); ForwardSetIn = Ctx.getBlockState(*Iter).ForwardSetOut; ForwardValIn = Ctx.getBlockState(*Iter).ForwardValOut; Iter = std::next(Iter); for (auto EndIter = BB->pred_end(); Iter != EndIter; ++Iter) { BlockState &OtherState = Ctx.getBlockState(*Iter); ForwardSetIn &= OtherState.ForwardSetOut; // Merge in the predecessor state. for (unsigned i = 0; i < LocationNum; ++i) { if (OtherState.ForwardSetOut[i]) { // There are multiple values from multiple predecessors, set this as // a covering value. We do not need to track the value itself, as we // can always go to the predecessors BlockState to find it. ForwardValIn[i] = Ctx.getValueBit(LSValue(true)); continue; } // If this location does have an available value, then clear it. stopTrackingValue(ForwardValIn, i); stopTrackingLocation(ForwardSetIn, i); } } }
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()); if (isComputeAvailSetMax(Kind)) { for (unsigned i = 0; i < Locs.size(); ++i) { updateMaxAvailForwardSetForRead(Ctx, Ctx.getLocationBit(Locs[i])); } return; } // Are we computing the genset and killset. if (isComputeAvailGenKillSet(Kind)) { for (unsigned i = 0; i < Locs.size(); ++i) { updateGenKillSetForRead(Ctx, Ctx.getLocationBit(Locs[i])); } return; } // Are we computing available set ?. if (isComputeAvailSet(Kind)) { for (auto &X : Locs) { if (isTrackingLocation(ForwardSetIn, Ctx.getLocationBit(X))) continue; updateForwardSetForRead(Ctx, Ctx.getLocationBit(X)); } return; } // Are we computing available values ?. bool CanForward = true; if (isComputeAvailValue(Kind) || isPerformingRLE(Kind)) { LSValueList Vals; LSValue::expand(Val, &I->getModule(), Vals, Ctx.getTE()); for (unsigned i = 0; i < Locs.size(); ++i) { if (isTrackingLocation(ForwardSetIn, Ctx.getLocationBit(Locs[i]))) continue; updateForwardSetAndValForRead(Ctx, Ctx.getLocationBit(Locs[i]), Ctx.getValueBit(Vals[i])); // We can not perform the forwarding as we are at least missing // some pieces of the read location. CanForward = false; } } // Simply return if we are not performing RLE or we do not have all the // values available to perform RLE. if (!isPerformingRLE(Kind) || !CanForward) return; // Lastly, forward value to the load. setupRLE(Ctx, I, Mem); }