LLVM: lib/CodeGen/PHIElimination.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

43#include

44#include

45#include

46

47using namespace llvm;

48

49#define DEBUG_TYPE "phi-node-elimination"

50

54 cl::desc("Disable critical edge splitting "

55 "during PHI elimination"));

56

60 cl::desc("Split all critical edges during "

61 "PHI elimination"));

62

65 cl::desc("Do not use an early exit if isLiveOutPastPHIs returns true."));

66

67namespace {

68

69class PHIEliminationImpl {

75

76

77

79

82 bool AllEdgesCritical);

83

84

85

86

87

88

90

91

96

97

98

101

102 using BBVRegPair = std::pair<unsigned, Register>;

104

105

106 VRegPHIUse VRegPHIUseCount;

107

108

110

111

112 using LoweredPHIMap =

114 LoweredPHIMap LoweredPHIs;

115

118

119public:

124 auto *MDTWrapper =

126 LV = LVWrapper ? &LVWrapper->getLV() : nullptr;

127 LIS = LISWrapper ? &LISWrapper->getLIS() : nullptr;

128 MLI = MLIWrapper ? &MLIWrapper->getLI() : nullptr;

129 MDT = MDTWrapper ? &MDTWrapper->getDomTree() : nullptr;

130 }

131

137

139};

140

142public:

143 static char ID;

144

147 }

148

150 PHIEliminationImpl Impl(this);

151 return Impl.run(MF);

152 }

153

156 MachineFunctionProperties::Property::NoPHIs);

157 }

158

160};

161

162}

163

167 PHIEliminationImpl Impl(MF, MFAM);

168 bool Changed = Impl.run(MF);

169 if (!Changed)

177 return PA;

178}

179

180STATISTIC(NumLowered, "Number of phis lowered");

181STATISTIC(NumCriticalEdgesSplit, "Number of critical edges split");

182STATISTIC(NumReused, "Number of reused lowered phis");

183

184char PHIElimination::ID = 0;

185

187

189 "Eliminate PHI nodes for register allocation", false,

190 false)

194

195void PHIElimination::getAnalysisUsage(AnalysisUsage &AU) const {

203}

204

207

209 if (P) {

210 auto *MDTWrapper =

212 MDT = MDTWrapper ? &MDTWrapper->getDomTree() : nullptr;

213 } else {

215 }

217

218 bool Changed = false;

219

220

222

223

224 std::vector<SparseBitVector<>> LiveInSets;

225 if (LV) {

226 LiveInSets.resize(MF.size());

227 for (unsigned Index = 0, e = MRI->getNumVirtRegs(); Index != e; ++Index) {

228

229

233 continue;

237 while (AliveBlockItr != EndItr) {

238 unsigned BlockNum = *(AliveBlockItr++);

239 LiveInSets[BlockNum].set(Index);

240 }

241

242

244 if (VI.Kills.size() > 1 ||

245 (VI.Kills.empty() && VI.Kills.front()->getParent() != DefMBB))

246 for (auto *MI : VI.Kills)

247 LiveInSets[MI->getParent()->getNumber()].set(Index);

248 }

249 }

250

251 for (auto &MBB : MF)

252 Changed |=

253 SplitPHIEdges(MF, MBB, MLI, (LV ? &LiveInSets : nullptr), MDTU);

254 }

255

256

257 MRI->leaveSSA();

258

259

260 if (LV || LIS)

261 analyzePHINodes(MF);

262

263

264 for (auto &MBB : MF)

265 Changed |= EliminatePHINodes(MF, MBB);

266

267

270 if (MRI->use_nodbg_empty(DefReg)) {

271 if (LIS)

274 }

275 }

276

277

278 for (auto &I : LoweredPHIs) {

279 if (LIS)

281 MF.deleteMachineInstr(I.first);

282 }

283

284 LoweredPHIs.clear();

285 ImpDefs.clear();

286 VRegPHIUseCount.clear();

287

289

290 return Changed;

291}

292

293

294

295bool PHIEliminationImpl::EliminatePHINodes(MachineFunction &MF,

298 return false;

299

300

303

304

305

306

307

308 bool AllEdgesCritical = MBB.pred_size() >= 2;

310 if (Pred->succ_size() < 2) {

311 AllEdgesCritical = false;

312 break;

313 }

314 }

315

317 LowerPHINode(MBB, LastPHIIt, AllEdgesCritical);

318

319 return true;

320}

321

322

323

327 if (!DI.isImplicitDef())

328 return false;

329 return true;

330}

331

332

335 for (unsigned I = 1, E = MPhi.getNumOperands(); I != E; I += 2) {

338 return false;

339 }

340 return true;

341}

342

345 bool AllEdgesCritical) {

346 ++NumLowered;

347

349

350

352

357

358

360 unsigned IncomingReg = 0;

361 bool EliminateNow = true;

362 bool reusedIncoming = false;

363

364

365

366

370

371

373 TII->get(TargetOpcode::IMPLICIT_DEF), DestReg);

374 else {

375

376

377

378

379 unsigned *Entry = nullptr;

380 if (AllEdgesCritical)

381 Entry = &LoweredPHIs[MPhi];

382 if (Entry && *Entry) {

383

384 IncomingReg = *Entry;

385 reusedIncoming = true;

386 ++NumReused;

388 << *MPhi);

389 } else {

392 if (Entry) {

393 EliminateNow = false;

394 *Entry = IncomingReg;

395 }

396 }

397

398

399 PHICopy = TII->createPHIDestinationCopy(

400 MBB, AfterPHIsIt, MPhi->getDebugLoc(), IncomingReg, DestReg);

401 }

402

404

410 (void)Res;

411 }

412

413

414 if (LV) {

415 if (IncomingReg) {

417

419 bool IsPHICopyAfterOldKill = false;

420

421 if (reusedIncoming && (OldKill = VI.findKill(&MBB))) {

422

423

424

425

426

428 ++I) {

429 if (I == PHICopy)

430 break;

431

432 if (I == OldKill) {

433 IsPHICopyAfterOldKill = true;

434 break;

435 }

436 }

437 }

438

439

440

441

442 if (IsPHICopyAfterOldKill) {

443 LLVM_DEBUG(dbgs() << "Remove old kill from " << *OldKill);

444 LV->removeVirtualRegisterKilled(IncomingReg, *OldKill);

446 }

447

448

449

450

451

452

453 if (!OldKill || IsPHICopyAfterOldKill)

454 LV->addVirtualRegisterKilled(IncomingReg, *PHICopy);

455 }

456

457

458

459

460 LV->removeVirtualRegistersKilled(*MPhi);

461

462

464 LV->addVirtualRegisterDead(DestReg, *PHICopy);

465 LV->removeVirtualRegisterDead(DestReg, *MPhi);

466 }

467 }

468

469

470 if (LIS) {

472

474 if (IncomingReg) {

475

476

479 if (!IncomingVNI)

480 IncomingVNI =

483 MBBStartIndex, DestCopyIndex.getRegSlot(), IncomingVNI));

484 }

485

487 assert(!DestLI.empty() && "PHIs should have non-empty LiveIntervals.");

488

490

492 for (auto &SR : DestLI.subranges())

494

495 for (auto LR : ToUpdate) {

496 auto DestSegment = LR->find(MBBStartIndex);

497 assert(DestSegment != LR->end() &&

498 "PHI destination must be live in block");

499

500 if (LR->endIndex().isDead()) {

501

502

503

504 VNInfo *OrigDestVNI = LR->getVNInfoAt(DestSegment->start);

505 assert(OrigDestVNI && "PHI destination should be live at block entry.");

506 LR->removeSegment(DestSegment->start, DestSegment->start.getDeadSlot());

508 LR->removeValNo(OrigDestVNI);

509 continue;

510 }

511

512

513

514

515 if (DestSegment->start > NewStart) {

516 VNInfo *VNI = LR->getVNInfoAt(DestSegment->start);

517 assert(VNI && "value should be defined for known segment");

518 LR->addSegment(

520 } else if (DestSegment->start < NewStart) {

521 assert(DestSegment->start >= MBBStartIndex);

523 LR->removeSegment(DestSegment->start, NewStart);

524 }

525 VNInfo *DestVNI = LR->getVNInfoAt(NewStart);

526 assert(DestVNI && "PHI destination should be live at its definition.");

527 DestVNI->def = NewStart;

528 }

529 }

530

531

532 if (LV || LIS) {

533 for (unsigned i = 1; i != MPhi->getNumOperands(); i += 2) {

535 --VRegPHIUseCount[BBVRegPair(

538 }

539 }

540 }

541

542

543

545 for (int i = NumSrcs - 1; i >= 0; --i) {

551 "Machine PHI Operands must all be virtual registers!");

552

553

554

556

557

558

559

560 if (!MBBsInsertedInto.insert(&opBlock).second)

561 continue;

562

564 if (SrcRegDef && TII->isUnspillableTerminator(SrcRegDef)) {

567 "Expected operand 0 to be a reg def!");

568

569

571 "Expected a single use from UnspillableTerminator");

573

574

575 if (LV) {

580 }

581

582 continue;

583 }

584

585

586

589

590

592 if (!reusedIncoming && IncomingReg) {

593 if (SrcUndef) {

594

595

596

597 NewSrcInstr =

599 TII->get(TargetOpcode::IMPLICIT_DEF), IncomingReg);

600

601

604 ImpDefs.insert(DefMI);

605 } else {

606

607

608 NewSrcInstr = TII->createPHISourceCopy(opBlock, InsertPos, nullptr,

609 SrcReg, SrcSubReg, IncomingReg);

610 }

611 }

612

613

614

615

616 if (LV && !SrcUndef &&

617 !VRegPHIUseCount[BBVRegPair(opBlock.getNumber(), SrcReg)] &&

618 !LV->isLiveOut(SrcReg, opBlock)) {

619

620

621

622

623

624

625

626

627

628

629

630

631

632

633

634

638 if (Term->readsRegister(SrcReg, nullptr))

639 KillInst = Term;

640 }

641

642 if (KillInst == opBlock.end()) {

643

644

645 if (reusedIncoming || !IncomingReg) {

646

647 KillInst = InsertPos;

648 while (KillInst != opBlock.begin()) {

649 --KillInst;

650 if (KillInst->isDebugInstr())

651 continue;

652 if (KillInst->readsRegister(SrcReg, nullptr))

653 break;

654 }

655 } else {

656

657 KillInst = NewSrcInstr;

658 }

659 }

660 assert(KillInst->readsRegister(SrcReg, nullptr) &&

661 "Cannot find kill instruction");

662

663

664 LV->addVirtualRegisterKilled(SrcReg, *KillInst);

665

666

667 unsigned opBlockNum = opBlock.getNumber();

668 LV->getVarInfo(SrcReg).AliveBlocks.reset(opBlockNum);

669 }

670

671 if (LIS) {

672 if (NewSrcInstr) {

675 }

676

677 if (!SrcUndef &&

678 !VRegPHIUseCount[BBVRegPair(opBlock.getNumber(), SrcReg)]) {

680

685

686

687 if (VNI && VNI->def != startIdx) {

689 break;

690 }

691 }

692

697 if (Term->readsRegister(SrcReg, nullptr))

698 KillInst = Term;

699 }

700

701 if (KillInst == opBlock.end()) {

702

703

704 if (reusedIncoming || !IncomingReg) {

705

706 KillInst = InsertPos;

707 while (KillInst != opBlock.begin()) {

708 --KillInst;

709 if (KillInst->isDebugInstr())

710 continue;

711 if (KillInst->readsRegister(SrcReg, nullptr))

712 break;

713 }

714 } else {

715

716 KillInst = std::prev(InsertPos);

717 }

718 }

719 assert(KillInst->readsRegister(SrcReg, nullptr) &&

720 "Cannot find kill instruction");

721

725 for (auto &SR : SrcLI.subranges()) {

726 SR.removeSegment(LastUseIndex.getRegSlot(),

728 }

729 }

730 }

731 }

732 }

733

734

735 if (EliminateNow) {

736 if (LIS)

739 }

740}

741

742

743

744

745

746void PHIEliminationImpl::analyzePHINodes(const MachineFunction &MF) {

747 for (const auto &MBB : MF) {

748 for (const auto &BBI : MBB) {

749 if (!BBI.isPHI())

750 break;

751 for (unsigned i = 1, e = BBI.getNumOperands(); i != e; i += 2) {

752 if (!BBI.getOperand(i).isUndef()) {

753 ++VRegPHIUseCount[BBVRegPair(

754 BBI.getOperand(i + 1).getMBB()->getNumber(),

755 BBI.getOperand(i).getReg())];

756 }

757 }

758 }

759 }

760}

761

762bool PHIEliminationImpl::SplitPHIEdges(

766 return false;

767

769 bool IsLoopHeader = CurLoop && &MBB == CurLoop->getHeader();

770

771 bool Changed = false;

773 BBI != BBE && BBI->isPHI(); ++BBI) {

774 for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) {

775 Register Reg = BBI->getOperand(i).getReg();

777

779 continue;

780

781

782

784 continue;

787 continue;

788

789

790

791

792

793

794

795 bool ShouldSplit = isLiveOutPastPHIs(Reg, PreMBB);

797 continue;

798 if (ShouldSplit) {

802 }

803

804

805

806

807

808

809

810

811

812 ShouldSplit = ShouldSplit && !isLiveIn(Reg, &MBB);

813

814

815 if (!ShouldSplit && CurLoop != PreLoop) {

817 dbgs() << "Split wouldn't help, maybe avoid loop copies?\n";

818 if (PreLoop)

819 dbgs() << "PreLoop: " << *PreLoop;

820 if (CurLoop)

821 dbgs() << "CurLoop: " << *CurLoop;

822 });

823

824

825

826

827 ShouldSplit = PreLoop && !PreLoop->contains(CurLoop);

828 }

830 continue;

833 LLVM_DEBUG(dbgs() << "Failed to split critical edge.\n");

834 continue;

835 }

836 Changed = true;

837 ++NumCriticalEdgesSplit;

838 }

839 }

840 return Changed;

841}

842

844 assert((LV || LIS) &&

845 "isLiveIn() requires either LiveVariables or LiveIntervals");

846 if (LIS)

848 else

849 return LV->isLiveIn(Reg, *MBB);

850}

851

852bool PHIEliminationImpl::isLiveOutPastPHIs(Register Reg,

854 assert((LV || LIS) &&

855 "isLiveOutPastPHIs() requires either LiveVariables or LiveIntervals");

856

857

858

859

860

861 if (LIS) {

865 return true;

866 return false;

867 } else {

868 return LV->isLiveOut(Reg, *MBB);

869 }

870}

unsigned const MachineRegisterInfo * MRI

for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))

MachineInstrBuilder MachineInstrBuilder & DefMI

Unify divergent function exit nodes

This file defines the DenseMap class.

const HexagonInstrInfo * TII

static bool allPhiOperandsUndefined(const MachineInstr &MPhi, const MachineRegisterInfo &MRI)

Return true if all sources of the phi node are implicit_def's, or undef's.

Eliminate PHI nodes for register allocation

static cl::opt< bool > NoPhiElimLiveOutEarlyExit("no-phi-elim-live-out-early-exit", cl::init(false), cl::Hidden, cl::desc("Do not use an early exit if isLiveOutPastPHIs returns true."))

static bool isImplicitlyDefined(unsigned VirtReg, const MachineRegisterInfo &MRI)

Return true if all defs of VirtReg are implicit-defs.

static cl::opt< bool > DisableEdgeSplitting("disable-phi-elim-edge-splitting", cl::init(false), cl::Hidden, cl::desc("Disable critical edge splitting " "during PHI elimination"))

static cl::opt< bool > SplitAllCriticalEdges("phi-elim-split-all-critical-edges", cl::init(false), cl::Hidden, cl::desc("Split all critical edges during " "PHI elimination"))

#define INITIALIZE_PASS_DEPENDENCY(depName)

#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)

#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

static bool isLiveOut(const MachineBasicBlock &MBB, unsigned Reg)

bool isDead(const MachineInstr &MI, const MachineRegisterInfo &MRI)

This file defines the SmallPtrSet class.

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

A container for analyses that lazily runs them and caches their results.

PassT::Result * getCachedResult(IRUnitT &IR) const

Get the cached result of an analysis pass for a given IR unit.

Represent the analysis usage information of a pass.

LiveInterval - This class represents the liveness of a register, or stack slot.

iterator_range< subrange_iterator > subranges()

SlotIndex getMBBStartIdx(const MachineBasicBlock *mbb) const

Return the first index in the given basic block.

SlotIndex InsertMachineInstrInMaps(MachineInstr &MI)

LiveInterval & getOrCreateEmptyInterval(Register Reg)

Return an existing interval for Reg.

SlotIndex getInstructionIndex(const MachineInstr &Instr) const

Returns the base index of the given instruction.

void RemoveMachineInstrFromMaps(MachineInstr &MI)

VNInfo::Allocator & getVNInfoAllocator()

SlotIndex getMBBEndIdx(const MachineBasicBlock *mbb) const

Return the last index in the given basic block.

LiveInterval & getInterval(Register Reg)

LiveInterval::Segment addSegmentToEndOfBlock(Register Reg, MachineInstr &startInst)

Given a register and an instruction, adds a live segment from that instruction to the end of its MBB.

bool isLiveInToMBB(const LiveRange &LR, const MachineBasicBlock *mbb) const

iterator addSegment(Segment S)

Add the specified Segment to this range, merging segments as appropriate.

bool liveAt(SlotIndex index) const

VNInfo * getNextValue(SlotIndex Def, VNInfo::Allocator &VNInfoAllocator)

getNextValue - Create a new value number and return it.

void removeSegment(SlotIndex Start, SlotIndex End, bool RemoveDeadValNo=false)

Remove the specified interval from this live range.

VNInfo * getVNInfoAt(SlotIndex Idx) const

getVNInfoAt - Return the VNInfo that is live at Idx, or NULL.

bool contains(const LoopT *L) const

Return true if the specified loop is contained within in this loop.

BlockT * getHeader() const

LoopT * getLoopFor(const BlockT *BB) const

Return the inner most loop that BB lives in.

unsigned pred_size() const

bool isEHPad() const

Returns true if the block is a landing pad.

MachineBasicBlock * SplitCriticalEdge(MachineBasicBlock *Succ, Pass &P, std::vector< SparseBitVector<> > *LiveInSets=nullptr, MachineDomTreeUpdater *MDTU=nullptr)

Split the critical edge from this block to the given successor block, and return the newly created bl...

int getNumber() const

MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...

iterator SkipPHIsAndLabels(iterator I)

Return the first instruction in MBB after I that is not a PHI or a label.

MachineInstr * remove(MachineInstr *I)

Remove the unbundled instruction from the instruction list without deleting it.

unsigned succ_size() const

const MachineFunction * getParent() const

Return the MachineFunction containing this basic block.

iterator_range< succ_iterator > successors()

iterator_range< pred_iterator > predecessors()

Analysis pass which computes a MachineDominatorTree.

Analysis pass which computes a MachineDominatorTree.

DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...

MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.

virtual MachineFunctionProperties getSetProperties() const

virtual bool runOnMachineFunction(MachineFunction &MF)=0

runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...

Properties which a MachineFunction may have at a given point in time.

MachineFunctionProperties & set(Property P)

Location of a PHI instruction that is also a debug-info variable value, for the duration of register ...

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

void deleteMachineInstr(MachineInstr *MI)

DeleteMachineInstr - Delete the given MachineInstr.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

DenseMap< unsigned, DebugPHIRegallocPos > DebugPHIPositions

Map of debug instruction numbers to the position of their PHI instructions during register allocation...

Representation of each machine instruction.

bool isImplicitDef() const

const MachineBasicBlock * getParent() const

unsigned getNumOperands() const

Retuns the total number of operands.

unsigned peekDebugInstrNum() const

Examine the instruction number of this MachineInstr.

const DebugLoc & getDebugLoc() const

Returns the debug location id of this MachineInstr.

void eraseFromParent()

Unlink 'this' from the containing basic block and delete it.

const MachineOperand & getOperand(unsigned i) const

Analysis pass that exposes the MachineLoopInfo for a machine function.

MachineOperand class - Representation of each machine instruction operand.

unsigned getSubReg() const

bool isReg() const

isReg - Tests if this is a MO_Register operand.

MachineBasicBlock * getMBB() const

void setReg(Register Reg)

Change the register this operand corresponds to.

Register getReg() const

getReg - Returns the register number.

MachineRegisterInfo - Keep track of information for virtual and physical registers,...

const TargetRegisterClass * getRegClass(Register Reg) const

Return the register class of the specified virtual register.

Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")

createVirtualRegister - Create and return a new virtual register in the function with the specified r...

PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)

static PassRegistry * getPassRegistry()

getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...

A set of analyses that are preserved following a run of a transformation pass.

static PreservedAnalyses all()

Construct a special preserved set that preserves all passes.

Wrapper class representing virtual and physical registers.

static Register index2VirtReg(unsigned Index)

Convert a 0-based index to a virtual register number.

constexpr bool isVirtual() const

Return true if the specified register number is in the virtual register namespace.

SlotIndex - An opaque wrapper around machine indexes.

SlotIndex getRegSlot(bool EC=false) const

Returns the register use/def slot in the current instruction for a normal or early-clobber def.

std::pair< iterator, bool > insert(PtrType Ptr)

Inserts Ptr if and only if there is no element in the container equal to Ptr.

SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

SparseBitVectorIterator iterator

TargetInstrInfo - Interface to description of machine instruction set.

virtual const TargetInstrInfo * getInstrInfo() const

VNInfo - Value Number Information.

SlotIndex def

The index of the defining instruction.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

Reg

All possible values of the reg field in the ModR/M byte.

initializer< Ty > init(const Ty &Val)

PointerTypeMap run(const Module &M)

Compute the PointerTypeMap for the module M.

This is an optimization pass for GlobalISel generic memory operations.

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

PreservedAnalyses getMachineFunctionPassPreservedAnalyses()

Returns the minimum set of Analyses that all machine function passes must preserve.

void initializePHIEliminationPass(PassRegistry &)

raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

char & PHIEliminationID

PHIElimination - This pass eliminates machine instruction PHI nodes by inserting copy instructions.

MachineBasicBlock::iterator findPHICopyInsertPoint(MachineBasicBlock *MBB, MachineBasicBlock *SuccMBB, unsigned SrcReg)

findPHICopyInsertPoint - Find a safe place in MBB to insert a copy from SrcReg when following the CFG...

Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)

Prints virtual and physical registers with or without a TRI instance.

Printable printMBBReference(const MachineBasicBlock &MBB)

Prints a machine basic block reference.

This represents a simple continuous liveness interval for a value.

VarInfo - This represents the regions where a virtual register is live in the program.

SparseBitVector AliveBlocks

AliveBlocks - Set of blocks in which this value is alive completely through.