/// A definition of a register may mark the end of a range. void LiveDebugValues::transferRegisterDef(MachineInstr &MI, OpenRangesSet &OpenRanges, const VarLocMap &VarLocIDs) { MachineFunction *MF = MI.getParent()->getParent(); const TargetLowering *TLI = MF->getSubtarget().getTargetLowering(); unsigned SP = TLI->getStackPointerRegisterToSaveRestore(); SparseBitVector<> KillSet; for (const MachineOperand &MO : MI.operands()) { if (MO.isReg() && MO.isDef() && MO.getReg() && TRI->isPhysicalRegister(MO.getReg())) { // Remove ranges of all aliased registers. for (MCRegAliasIterator RAI(MO.getReg(), TRI, true); RAI.isValid(); ++RAI) for (unsigned ID : OpenRanges.getVarLocs()) if (VarLocIDs[ID].isDescribedByReg() == *RAI) KillSet.set(ID); } else if (MO.isRegMask()) { // Remove ranges of all clobbered registers. Register masks don't usually // list SP as preserved. While the debug info may be off for an // instruction or two around callee-cleanup calls, transferring the // DEBUG_VALUE across the call is still a better user experience. for (unsigned ID : OpenRanges.getVarLocs()) { unsigned Reg = VarLocIDs[ID].isDescribedByReg(); if (Reg && Reg != SP && MO.clobbersPhysReg(Reg)) KillSet.set(ID); } } } OpenRanges.erase(KillSet, VarLocIDs); }
void LazyLiveness::computeBackedgeChain(MachineFunction& mf, MachineBasicBlock* MBB) { SparseBitVector<128> tmp = rv[MBB]; tmp.set(preorder[MBB]); tmp &= backedge_source; calculated.set(preorder[MBB]); for (SparseBitVector<128>::iterator I = tmp.begin(); I != tmp.end(); ++I) { assert(rev_preorder.size() > *I && "Unknown block!"); MachineBasicBlock* SrcMBB = rev_preorder[*I]; for (MachineBasicBlock::succ_iterator SI = SrcMBB->succ_begin(), SE = SrcMBB->succ_end(); SI != SE; ++SI) { MachineBasicBlock* TgtMBB = *SI; if (backedges.count(std::make_pair(SrcMBB, TgtMBB)) && !rv[MBB].test(preorder[TgtMBB])) { if (!calculated.test(preorder[TgtMBB])) computeBackedgeChain(mf, TgtMBB); tv[MBB].set(preorder[TgtMBB]); SparseBitVector<128> right = tv[TgtMBB]; tv[MBB] |= right; } } tv[MBB].reset(preorder[MBB]); } }
void SIFixWWMLiveness::addDefs(const MachineInstr &MI, SparseBitVector<> &Regs) { for (const MachineOperand &Op : MI.defs()) { if (Op.isReg()) { unsigned Reg = Op.getReg(); if (TRI->isVGPR(*MRI, Reg)) Regs.set(Reg); } } }
Error llvm::pdb::readSparseBitVector(BinaryStreamReader &Stream, SparseBitVector<> &V) { uint32_t NumWords; if (auto EC = Stream.readInteger(NumWords)) return joinErrors( std::move(EC), make_error<RawError>(raw_error_code::corrupt_file, "Expected hash table number of words")); for (uint32_t I = 0; I != NumWords; ++I) { uint32_t Word; if (auto EC = Stream.readInteger(Word)) return joinErrors(std::move(EC), make_error<RawError>(raw_error_code::corrupt_file, "Expected hash table word")); for (unsigned Idx = 0; Idx < 32; ++Idx) if (Word & (1U << Idx)) V.set((I * 32) + Idx); } return Error::success(); }
Error NameMap::load(StreamReader &Stream) { // This is some sort of weird string-set/hash table encoded in the stream. // It starts with the number of bytes in the table. uint32_t NumberOfBytes; if (auto EC = Stream.readInteger(NumberOfBytes)) return joinErrors(std::move(EC), make_error<RawError>(raw_error_code::corrupt_file, "Expected name map length")); if (Stream.bytesRemaining() < NumberOfBytes) return make_error<RawError>(raw_error_code::corrupt_file, "Invalid name map length"); // Following that field is the starting offset of strings in the name table. uint32_t StringsOffset = Stream.getOffset(); Stream.setOffset(StringsOffset + NumberOfBytes); // This appears to be equivalent to the total number of strings *actually* // in the name table. uint32_t HashSize; if (auto EC = Stream.readInteger(HashSize)) return joinErrors(std::move(EC), make_error<RawError>(raw_error_code::corrupt_file, "Expected name map hash size")); // This appears to be an upper bound on the number of strings in the name // table. uint32_t MaxNumberOfStrings; if (auto EC = Stream.readInteger(MaxNumberOfStrings)) return joinErrors(std::move(EC), make_error<RawError>(raw_error_code::corrupt_file, "Expected name map max strings")); if (MaxNumberOfStrings > (UINT32_MAX / sizeof(uint32_t))) return make_error<RawError>(raw_error_code::corrupt_file, "Implausible number of strings"); const uint32_t MaxNumberOfWords = UINT32_MAX / (sizeof(uint32_t) * 8); // This appears to be a hash table which uses bitfields to determine whether // or not a bucket is 'present'. uint32_t NumPresentWords; if (auto EC = Stream.readInteger(NumPresentWords)) return joinErrors(std::move(EC), make_error<RawError>(raw_error_code::corrupt_file, "Expected name map num words")); if (NumPresentWords > MaxNumberOfWords) return make_error<RawError>(raw_error_code::corrupt_file, "Number of present words is too large"); SparseBitVector<> Present; for (uint32_t I = 0; I != NumPresentWords; ++I) { uint32_t Word; if (auto EC = Stream.readInteger(Word)) return joinErrors(std::move(EC), make_error<RawError>(raw_error_code::corrupt_file, "Expected name map word")); for (unsigned Idx = 0; Idx < 32; ++Idx) if (Word & (1U << Idx)) Present.set((I * 32) + Idx); } // This appears to be a hash table which uses bitfields to determine whether // or not a bucket is 'deleted'. uint32_t NumDeletedWords; if (auto EC = Stream.readInteger(NumDeletedWords)) return joinErrors( std::move(EC), make_error<RawError>(raw_error_code::corrupt_file, "Expected name map num deleted words")); if (NumDeletedWords > MaxNumberOfWords) return make_error<RawError>(raw_error_code::corrupt_file, "Number of deleted words is too large"); SparseBitVector<> Deleted; for (uint32_t I = 0; I != NumDeletedWords; ++I) { uint32_t Word; if (auto EC = Stream.readInteger(Word)) return joinErrors(std::move(EC), make_error<RawError>(raw_error_code::corrupt_file, "Expected name map word")); for (unsigned Idx = 0; Idx < 32; ++Idx) if (Word & (1U << Idx)) Deleted.set((I * 32) + Idx); } for (unsigned I : Present) { // For all present entries, dump out their mapping. (void)I; // This appears to be an offset relative to the start of the strings. // It tells us where the null-terminated string begins. uint32_t NameOffset; if (auto EC = Stream.readInteger(NameOffset)) return joinErrors(std::move(EC), make_error<RawError>(raw_error_code::corrupt_file, "Expected name map name offset")); // This appears to be a stream number into the stream directory. uint32_t NameIndex; if (auto EC = Stream.readInteger(NameIndex)) return joinErrors(std::move(EC), make_error<RawError>(raw_error_code::corrupt_file, "Expected name map name index")); // Compute the offset of the start of the string relative to the stream. uint32_t StringOffset = StringsOffset + NameOffset; uint32_t OldOffset = Stream.getOffset(); // Pump out our c-string from the stream. StringRef Str; Stream.setOffset(StringOffset); if (auto EC = Stream.readZeroString(Str)) return joinErrors(std::move(EC), make_error<RawError>(raw_error_code::corrupt_file, "Expected name map name")); Stream.setOffset(OldOffset); // Add this to a string-map from name to stream number. Mapping.insert({Str, NameIndex}); } return Error::success(); }