diff options
Diffstat (limited to 'lib/CodeGen')
25 files changed, 634 insertions, 545 deletions
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index bc3af9a..6d12581 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -42,8 +42,8 @@ AsmVerbose("asm-verbose", cl::desc("Add comments to directives."), char AsmPrinter::ID = 0; AsmPrinter::AsmPrinter(raw_ostream &o, TargetMachine &tm, - const TargetAsmInfo *T, CodeGenOpt::Level OL, bool VDef) - : MachineFunctionPass(&ID), FunctionNumber(0), OptLevel(OL), O(o), + const TargetAsmInfo *T, bool VDef) + : MachineFunctionPass(&ID), FunctionNumber(0), O(o), TM(tm), TAI(T), TRI(tm.getRegisterInfo()), IsInTextSection(false), LastMI(0), LastFn(0), Counter(~0U), PrevDLT(0, ~0U, ~0U) { diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index cbe542b..547140f 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -221,7 +221,7 @@ DbgScope::~DbgScope() { } // end llvm namespace DwarfDebug::DwarfDebug(raw_ostream &OS, AsmPrinter *A, const TargetAsmInfo *T) - : Dwarf(OS, A, T, "dbg"), MainCU(0), + : Dwarf(OS, A, T, "dbg"), ModuleCU(0), AbbreviationsSet(InitAbbreviationsSetSize), Abbreviations(), ValuesSet(InitValuesSetSize), Values(), StringPool(), SectionMap(), SectionSourceLines(), didInitial(false), shouldEmit(false), @@ -678,9 +678,6 @@ void DwarfDebug::ConstructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer, if (Element.getTag() == dwarf::DW_TAG_subprogram) ElemDie = CreateSubprogramDIE(DW_Unit, DISubprogram(Element.getGV())); - else if (Element.getTag() == dwarf::DW_TAG_variable) // ?? - ElemDie = CreateGlobalVariableDIE(DW_Unit, - DIGlobalVariable(Element.getGV())); else ElemDie = CreateMemberDIE(DW_Unit, DIDerivedType(Element.getGV())); @@ -1093,13 +1090,8 @@ void DwarfDebug::ConstructFunctionDbgScope(DbgScope *RootScope, // Get the subprogram debug information entry. DISubprogram SPD(Desc.getGV()); - // Get the compile unit context. - CompileUnit *Unit = MainCU; - if (!Unit) - Unit = &FindCompileUnit(SPD.getCompileUnit()); - // Get the subprogram die. - DIE *SPDie = Unit->getDieMapSlotFor(SPD.getGV()); + DIE *SPDie = ModuleCU->getDieMapSlotFor(SPD.getGV()); assert(SPDie && "Missing subprogram descriptor"); if (!AbstractScope) { @@ -1112,55 +1104,27 @@ void DwarfDebug::ConstructFunctionDbgScope(DbgScope *RootScope, AddAddress(SPDie, dwarf::DW_AT_frame_base, Location); } - ConstructDbgScope(RootScope, 0, 0, SPDie, Unit); + ConstructDbgScope(RootScope, 0, 0, SPDie, ModuleCU); } /// ConstructDefaultDbgScope - Construct a default scope for the subprogram. /// void DwarfDebug::ConstructDefaultDbgScope(MachineFunction *MF) { const char *FnName = MF->getFunction()->getNameStart(); - if (MainCU) { - StringMap<DIE*> &Globals = MainCU->getGlobals(); - StringMap<DIE*>::iterator GI = Globals.find(FnName); - if (GI != Globals.end()) { - DIE *SPDie = GI->second; - - // Add the function bounds. - AddLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, - DWLabel("func_begin", SubprogramCount)); - AddLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, - DWLabel("func_end", SubprogramCount)); - - MachineLocation Location(RI->getFrameRegister(*MF)); - AddAddress(SPDie, dwarf::DW_AT_frame_base, Location); - return; - } - } else { - for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i) { - CompileUnit *Unit = CompileUnits[i]; - StringMap<DIE*> &Globals = Unit->getGlobals(); - StringMap<DIE*>::iterator GI = Globals.find(FnName); - if (GI != Globals.end()) { - DIE *SPDie = GI->second; - - // Add the function bounds. - AddLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, - DWLabel("func_begin", SubprogramCount)); - AddLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, - DWLabel("func_end", SubprogramCount)); - - MachineLocation Location(RI->getFrameRegister(*MF)); - AddAddress(SPDie, dwarf::DW_AT_frame_base, Location); - return; - } - } + StringMap<DIE*> &Globals = ModuleCU->getGlobals(); + StringMap<DIE*>::iterator GI = Globals.find(FnName); + if (GI != Globals.end()) { + DIE *SPDie = GI->second; + + // Add the function bounds. + AddLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, + DWLabel("func_begin", SubprogramCount)); + AddLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, + DWLabel("func_end", SubprogramCount)); + + MachineLocation Location(RI->getFrameRegister(*MF)); + AddAddress(SPDie, dwarf::DW_AT_frame_base, Location); } - -#if 0 - // FIXME: This is causing an abort because C++ mangled names are compared with - // their unmangled counterparts. See PR2885. Don't do this assert. - assert(0 && "Couldn't find DIE for machine function!"); -#endif } /// GetOrCreateSourceID - Look up the source id with the given directory and @@ -1233,10 +1197,11 @@ void DwarfDebug::ConstructCompileUnit(GlobalVariable *GV) { dwarf::DW_FORM_data1, RVer); CompileUnit *Unit = new CompileUnit(ID, Die); - if (DIUnit.isMain()) { - assert(!MainCU && "Multiple main compile units are found!"); - MainCU = Unit; - } + if (!ModuleCU && DIUnit.isMain()) { + // Use first compile unit marked as isMain as the compile unit + // for this module. + ModuleCU = Unit; + } CompileUnitMap[DIUnit.getGV()] = Unit; CompileUnits.push_back(Unit); @@ -1244,16 +1209,13 @@ void DwarfDebug::ConstructCompileUnit(GlobalVariable *GV) { void DwarfDebug::ConstructGlobalVariableDIE(GlobalVariable *GV) { DIGlobalVariable DI_GV(GV); - CompileUnit *DW_Unit = MainCU; - if (!DW_Unit) - DW_Unit = &FindCompileUnit(DI_GV.getCompileUnit()); // Check for pre-existence. - DIE *&Slot = DW_Unit->getDieMapSlotFor(DI_GV.getGV()); + DIE *&Slot = ModuleCU->getDieMapSlotFor(DI_GV.getGV()); if (Slot) return; - DIE *VariableDie = CreateGlobalVariableDIE(DW_Unit, DI_GV); + DIE *VariableDie = CreateGlobalVariableDIE(ModuleCU, DI_GV); // Add address. DIEBlock *Block = new DIEBlock(); @@ -1267,22 +1229,19 @@ void DwarfDebug::ConstructGlobalVariableDIE(GlobalVariable *GV) { Slot = VariableDie; // Add to context owner. - DW_Unit->getDie()->AddChild(VariableDie); + ModuleCU->getDie()->AddChild(VariableDie); // Expose as global. FIXME - need to check external flag. std::string Name; - DW_Unit->AddGlobal(DI_GV.getName(Name), VariableDie); + ModuleCU->AddGlobal(DI_GV.getName(Name), VariableDie); return; } void DwarfDebug::ConstructSubprogram(GlobalVariable *GV) { DISubprogram SP(GV); - CompileUnit *Unit = MainCU; - if (!Unit) - Unit = &FindCompileUnit(SP.getCompileUnit()); // Check for pre-existence. - DIE *&Slot = Unit->getDieMapSlotFor(GV); + DIE *&Slot = ModuleCU->getDieMapSlotFor(GV); if (Slot) return; @@ -1291,17 +1250,17 @@ void DwarfDebug::ConstructSubprogram(GlobalVariable *GV) { // class type. return; - DIE *SubprogramDie = CreateSubprogramDIE(Unit, SP); + DIE *SubprogramDie = CreateSubprogramDIE(ModuleCU, SP); // Add to map. Slot = SubprogramDie; // Add to context owner. - Unit->getDie()->AddChild(SubprogramDie); + ModuleCU->getDie()->AddChild(SubprogramDie); // Expose as global. std::string Name; - Unit->AddGlobal(SP.getName(Name), SubprogramDie); + ModuleCU->AddGlobal(SP.getName(Name), SubprogramDie); return; } @@ -1331,6 +1290,11 @@ void DwarfDebug::BeginModule(Module *M, MachineModuleInfo *mmi) { return; } + // If main compile unit for this module is not seen than randomly + // select first compile unit. + if (!ModuleCU) + ModuleCU = CompileUnits[0]; + // If there is not any debug info available for any global variables and any // subprograms then there is not any debug info to emit. if (GVs.empty() && SPs.empty()) { @@ -1707,9 +1671,6 @@ unsigned DwarfDebug::RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU, if (TimePassesIsEnabled) DebugTimer->startTimer(); - CompileUnit *Unit = MainCU; - if (!Unit) - Unit = &FindCompileUnit(SP.getCompileUnit()); GlobalVariable *GV = SP.getGV(); DenseMap<const GlobalVariable *, DbgScope *>::iterator II = AbstractInstanceRootMap.find(GV); @@ -1720,9 +1681,9 @@ unsigned DwarfDebug::RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU, DbgScope *Scope = new DbgScope(NULL, DIDescriptor(GV)); // Get the compile unit context. - DIE *SPDie = Unit->getDieMapSlotFor(GV); + DIE *SPDie = ModuleCU->getDieMapSlotFor(GV); if (!SPDie) - SPDie = CreateSubprogramDIE(Unit, SP, false, true); + SPDie = CreateSubprogramDIE(ModuleCU, SP, false, true); // Mark as being inlined. This makes this subprogram entry an abstract // instance root. @@ -1741,12 +1702,12 @@ unsigned DwarfDebug::RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU, // Create a concrete inlined instance for this inlined function. DbgConcreteScope *ConcreteScope = new DbgConcreteScope(DIDescriptor(GV)); DIE *ScopeDie = new DIE(dwarf::DW_TAG_inlined_subroutine); - ScopeDie->setAbstractCompileUnit(Unit); + ScopeDie->setAbstractCompileUnit(ModuleCU); - DIE *Origin = Unit->getDieMapSlotFor(GV); + DIE *Origin = ModuleCU->getDieMapSlotFor(GV); AddDIEEntry(ScopeDie, dwarf::DW_AT_abstract_origin, dwarf::DW_FORM_ref4, Origin); - AddUInt(ScopeDie, dwarf::DW_AT_call_file, 0, Unit->getID()); + AddUInt(ScopeDie, dwarf::DW_AT_call_file, 0, ModuleCU->getID()); AddUInt(ScopeDie, dwarf::DW_AT_call_line, 0, Line); AddUInt(ScopeDie, dwarf::DW_AT_call_column, 0, Col); @@ -1907,22 +1868,8 @@ void DwarfDebug::SizeAndOffsets() { sizeof(int32_t) + // Offset Into Abbrev. Section sizeof(int8_t); // Pointer Size (in bytes) - // Process base compile unit. - if (MainCU) { - SizeAndOffsetDie(MainCU->getDie(), Offset, true); - CompileUnitOffsets[MainCU] = 0; - return; - } - - // Process all compile units. - unsigned PrevOffset = 0; - - for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i) { - CompileUnit *Unit = CompileUnits[i]; - CompileUnitOffsets[Unit] = PrevOffset; - PrevOffset += SizeAndOffsetDie(Unit->getDie(), Offset, true) - + sizeof(int32_t); // FIXME - extra pad for gdb bug. - } + SizeAndOffsetDie(ModuleCU->getDie(), Offset, true); + CompileUnitOffsets[ModuleCU] = 0; } /// EmitInitial - Emit initial Dwarf declarations. This is necessary for cc @@ -2067,13 +2014,7 @@ void DwarfDebug::EmitDebugInfo() { // Start debug info section. Asm->SwitchToDataSection(TAI->getDwarfInfoSection()); - if (MainCU) { - EmitDebugInfoPerCU(MainCU); - return; - } - - for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i) - EmitDebugInfoPerCU(CompileUnits[i]); + EmitDebugInfoPerCU(ModuleCU); } /// EmitAbbreviations - Emit the abbreviation section. @@ -2405,13 +2346,7 @@ void DwarfDebug::EmitDebugPubNames() { // Start the dwarf pubnames section. Asm->SwitchToDataSection(TAI->getDwarfPubNamesSection()); - if (MainCU) { - EmitDebugPubNamesPerCU(MainCU); - return; - } - - for (unsigned i = 0, e = CompileUnits.size(); i != e; ++i) - EmitDebugPubNamesPerCU(CompileUnits[i]); + EmitDebugPubNamesPerCU(ModuleCU); } /// EmitDebugStr - Emit visible names into a debug str section. @@ -2521,7 +2456,7 @@ void DwarfDebug::EmitDebugInlineInfo() { if (!TAI->doesDwarfUsesInlineInfoSection()) return; - if (!MainCU) + if (!ModuleCU) return; Asm->SwitchToDataSection(TAI->getDwarfDebugInlineSection()); @@ -2555,7 +2490,7 @@ void DwarfDebug::EmitDebugInlineInfo() { for (SmallVector<unsigned, 4>::iterator LI = Labels.begin(), LE = Labels.end(); LI != LE; ++LI) { - DIE *SP = MainCU->getDieMapSlotFor(GV); + DIE *SP = ModuleCU->getDieMapSlotFor(GV); Asm->EmitInt32(SP->getOffset()); Asm->EOL("DIE offset"); if (TD->getPointerSize() == sizeof(int32_t)) diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index 111ec33..101dc70 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -70,9 +70,8 @@ class VISIBILITY_HIDDEN DwarfDebug : public Dwarf { /// SmallVector<CompileUnit *, 8> CompileUnits; - /// MainCU - Some platform prefers one compile unit per .o file. In such - /// cases, all dies are inserted in MainCU. - CompileUnit *MainCU; + /// ModuleCU - All DIEs are inserted in ModuleCU. + CompileUnit *ModuleCU; /// AbbreviationsSet - Used to uniquely define abbreviations. /// diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt index eeefe31..48f17d0 100644 --- a/lib/CodeGen/CMakeLists.txt +++ b/lib/CodeGen/CMakeLists.txt @@ -64,4 +64,4 @@ add_llvm_library(LLVMCodeGen VirtRegRewriter.cpp ) -target_link_libraries (LLVMCodeGen LLVMCore) +target_link_libraries (LLVMCodeGen LLVMCore LLVMScalarOpts) diff --git a/lib/CodeGen/ELF.h b/lib/CodeGen/ELF.h index 8d92373..7e983a4 100644 --- a/lib/CodeGen/ELF.h +++ b/lib/CodeGen/ELF.h @@ -20,14 +20,12 @@ #ifndef CODEGEN_ELF_H #define CODEGEN_ELF_H -#include "llvm/GlobalVariable.h" #include "llvm/CodeGen/BinaryObject.h" #include "llvm/CodeGen/MachineRelocation.h" #include "llvm/Support/DataTypes.h" -#include <cstring> namespace llvm { - class BinaryObject; + class GlobalValue; // Identification Indexes enum { @@ -172,41 +170,25 @@ namespace llvm { IsConstant(false), NameIdx(0), Value(0), Size(0), Info(0), Other(STV_DEFAULT), SectionIdx(ELFSection::SHN_UNDEF), - SymTabIdx(0) { - if (!GV) - return; - - switch (GV->getVisibility()) { - default: - assert(0 && "unknown visibility type"); - case GlobalValue::DefaultVisibility: - Other = STV_DEFAULT; - break; - case GlobalValue::HiddenVisibility: - Other = STV_HIDDEN; - break; - case GlobalValue::ProtectedVisibility: - Other = STV_PROTECTED; - break; - } - } - - unsigned getBind() { - return (Info >> 4) & 0xf; - } + SymTabIdx(0) {} - unsigned getType() { - return Info & 0xf; - } + unsigned getBind() { return (Info >> 4) & 0xf; } + unsigned getType() { return Info & 0xf; } void setBind(unsigned X) { assert(X == (X & 0xF) && "Bind value out of range!"); Info = (Info & 0x0F) | (X << 4); } + void setType(unsigned X) { assert(X == (X & 0xF) && "Type value out of range!"); Info = (Info & 0xF0) | X; } + + void setVisibility(unsigned V) { + assert(V == (V & 0x3) && "Type value out of range!"); + Other = V; + } }; /// ELFRelocation - This class contains all the information necessary to diff --git a/lib/CodeGen/ELFCodeEmitter.cpp b/lib/CodeGen/ELFCodeEmitter.cpp index 168fed5..691f194 100644 --- a/lib/CodeGen/ELFCodeEmitter.cpp +++ b/lib/CodeGen/ELFCodeEmitter.cpp @@ -9,6 +9,8 @@ #define DEBUG_TYPE "elfce" +#include "ELF.h" +#include "ELFWriter.h" #include "ELFCodeEmitter.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" @@ -16,8 +18,10 @@ #include "llvm/CodeGen/BinaryObject.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineRelocation.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetAsmInfo.h" #include "llvm/Support/Debug.h" //===----------------------------------------------------------------------===// @@ -40,10 +44,11 @@ void ELFCodeEmitter::startFunction(MachineFunction &MF) { BufferBegin = &BD[0]; BufferEnd = BufferBegin + BD.capacity(); - // Align the output buffer with function alignment, and - // upgrade the section alignment if required - unsigned Align = - TM.getELFWriterInfo()->getFunctionAlignment(MF.getFunction()); + // Get the function alignment in bytes + unsigned Align = (1 << MF.getAlignment()); + + // Align the section size with the function alignment, so the function can + // start in a aligned offset, also update the section alignment if needed. if (ES->Align < Align) ES->Align = Align; ES->Size = (ES->Size + (Align-1)) & (-Align); @@ -66,47 +71,35 @@ void ELFCodeEmitter::startFunction(MachineFunction &MF) { /// finishFunction - This callback is invoked after the function is completely /// finished. bool ELFCodeEmitter::finishFunction(MachineFunction &MF) { - // Add a symbol to represent the function. - ELFSym FnSym(MF.getFunction()); - // Update Section Size ES->Size = CurBufferPtr - BufferBegin; - // Set the symbol type as a function + // Add a symbol to represent the function. + const Function *F = MF.getFunction(); + ELFSym FnSym(F); FnSym.setType(ELFSym::STT_FUNC); + FnSym.setBind(EW.getGlobalELFLinkage(F)); + FnSym.setVisibility(EW.getGlobalELFVisibility(F)); FnSym.SectionIdx = ES->SectionIdx; FnSym.Size = CurBufferPtr-FnStartPtr; // Offset from start of Section FnSym.Value = FnStartPtr-BufferBegin; - // Figure out the binding (linkage) of the symbol. - switch (MF.getFunction()->getLinkage()) { - default: - // appending linkage is illegal for functions. - assert(0 && "Unknown linkage type!"); - case GlobalValue::ExternalLinkage: - FnSym.setBind(ELFSym::STB_GLOBAL); - EW.SymbolList.push_back(FnSym); - break; - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: - FnSym.setBind(ELFSym::STB_WEAK); - EW.SymbolList.push_back(FnSym); - break; - case GlobalValue::PrivateLinkage: - assert (0 && "PrivateLinkage should not be in the symbol table."); - case GlobalValue::InternalLinkage: - FnSym.setBind(ELFSym::STB_LOCAL); - EW.SymbolList.push_front(FnSym); - break; + // Locals should go on the symbol list front + if (!F->hasPrivateLinkage()) { + if (FnSym.getBind() == ELFSym::STB_LOCAL) + EW.SymbolList.push_front(FnSym); + else + EW.SymbolList.push_back(FnSym); } // Emit constant pool to appropriate section(s) emitConstantPool(MF.getConstantPool()); + // Emit jump tables to appropriate section + emitJumpTables(MF.getJumpTableInfo()); + // Relocations // ----------- // If we have emitted any relocations to function-specific objects such as @@ -126,13 +119,22 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) { Addr = getConstantPoolEntryAddress(MR.getConstantPoolIndex()); MR.setConstantVal(CPSections[MR.getConstantPoolIndex()]); MR.setResultPointer((void*)Addr); + } else if (MR.isJumpTableIndex()) { + Addr = getJumpTableEntryAddress(MR.getJumpTableIndex()); + MR.setResultPointer((void*)Addr); + MR.setConstantVal(JumpTableSectionIdx); } else { assert(0 && "Unhandled relocation type"); } ES->addRelocation(MR); } - Relocations.clear(); + // Clear per-function data structures. + Relocations.clear(); + CPLocations.clear(); + CPSections.clear(); + JTLocations.clear(); + MBBLocations.clear(); return false; } @@ -168,4 +170,56 @@ void ELFCodeEmitter::emitConstantPool(MachineConstantPool *MCP) { } } +/// emitJumpTables - Emit all the jump tables for a given jump table info +/// record to the appropriate section. +void ELFCodeEmitter::emitJumpTables(MachineJumpTableInfo *MJTI) { + const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); + if (JT.empty()) return; + + // FIXME: handle PIC codegen + assert(TM.getRelocationModel() != Reloc::PIC_ && + "PIC codegen not yet handled for elf jump tables!"); + + const TargetAsmInfo *TAI = TM.getTargetAsmInfo(); + + // Get the ELF Section to emit the jump table + unsigned Align = TM.getTargetData()->getPointerABIAlignment(); + std::string JTName(TAI->getJumpTableDataSection()); + ELFSection &JTSection = EW.getJumpTableSection(JTName, Align); + JumpTableSectionIdx = JTSection.SectionIdx; + + // Entries in the JT Section are relocated against the text section + ELFSection &TextSection = EW.getTextSection(); + + // For each JT, record its offset from the start of the section + for (unsigned i = 0, e = JT.size(); i != e; ++i) { + const std::vector<MachineBasicBlock*> &MBBs = JT[i].MBBs; + + DOUT << "JTSection.size(): " << JTSection.size() << "\n"; + DOUT << "JTLocations.size: " << JTLocations.size() << "\n"; + + // Record JT 'i' offset in the JT section + JTLocations.push_back(JTSection.size()); + + // Each MBB entry in the Jump table section has a relocation entry + // against the current text section. + for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) { + MachineRelocation MR = + MachineRelocation::getBB(JTSection.size(), + MachineRelocation::VANILLA, + MBBs[mi]); + + // Offset of JT 'i' in JT section + MR.setResultPointer((void*)getMachineBasicBlockAddress(MBBs[mi])); + MR.setConstantVal(TextSection.SectionIdx); + + // Add the relocation to the Jump Table section + JTSection.addRelocation(MR); + + // Output placeholder for MBB in the JT section + JTSection.emitWord(0); + } + } +} + } // end namespace llvm diff --git a/lib/CodeGen/ELFCodeEmitter.h b/lib/CodeGen/ELFCodeEmitter.h index c309ef7..982aebf 100644 --- a/lib/CodeGen/ELFCodeEmitter.h +++ b/lib/CodeGen/ELFCodeEmitter.h @@ -10,11 +10,12 @@ #ifndef ELFCODEEMITTER_H #define ELFCODEEMITTER_H -#include "ELFWriter.h" #include "llvm/CodeGen/MachineCodeEmitter.h" #include <vector> namespace llvm { + class ELFWriter; + class ELFSection; /// ELFCodeEmitter - This class is used by the ELFWriter to /// emit the code for functions to the ELF file. @@ -39,6 +40,10 @@ namespace llvm { /// containing the constant pool entry for that index. std::vector<unsigned> CPSections; + /// JTLocations - This is a map of jump table indices to offsets from the + /// start of the section for that jump table index. + std::vector<uintptr_t> JTLocations; + /// MBBLocations - This vector is a mapping from MBB ID's to their address. /// It is filled in by the StartMachineBasicBlock callback and queried by /// the getMachineBasicBlockAddress callback. @@ -47,8 +52,12 @@ namespace llvm { /// FnStartPtr - Pointer to the start location of the current function /// in the buffer uint8_t *FnStartPtr; + + /// JumpTableSectionIdx - Holds the index of the Jump Table Section + unsigned JumpTableSectionIdx; public: - explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM) {} + explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM), + JumpTableSectionIdx(0) {} void startFunction(MachineFunction &F); bool finishFunction(MachineFunction &F); @@ -63,25 +72,20 @@ namespace llvm { MBBLocations[MBB->getNumber()] = getCurrentPCOffset(); } - virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) { - assert(MBBLocations.size() > (unsigned)MBB->getNumber() && - MBBLocations[MBB->getNumber()] && "MBB not emitted!"); - return MBBLocations[MBB->getNumber()]; - } - virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const { assert(CPLocations.size() > Index && "CP not emitted!"); return CPLocations[Index]; } virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const { - assert(0 && "JT not implementated yet!"); - return 0; + assert(JTLocations.size() > Index && "JT not emitted!"); + return JTLocations[Index]; } virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const { - assert(0 && "JT not implementated yet!"); - return 0; + assert(MBBLocations.size() > (unsigned)MBB->getNumber() && + MBBLocations[MBB->getNumber()] && "MBB not emitted!"); + return MBBLocations[MBB->getNumber()]; } virtual uintptr_t getLabelAddress(uint64_t Label) const { @@ -99,7 +103,11 @@ namespace llvm { /// the constant should live in and emit the constant. void emitConstantPool(MachineConstantPool *MCP); - virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) { } + /// emitJumpTables - Emit all the jump tables for a given jump table info + /// record to the appropriate section. + void emitJumpTables(MachineJumpTableInfo *MJTI); + + virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) {} /// JIT SPECIFIC FUNCTIONS - DO NOT IMPLEMENT THESE HERE! void startGVStub(const GlobalValue* F, unsigned StubSize, diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp index 041defa..9e91524 100644 --- a/lib/CodeGen/ELFWriter.cpp +++ b/lib/CodeGen/ELFWriter.cpp @@ -30,9 +30,9 @@ #define DEBUG_TYPE "elfwriter" +#include "ELF.h" #include "ELFWriter.h" #include "ELFCodeEmitter.h" -#include "ELF.h" #include "llvm/Constants.h" #include "llvm/Module.h" #include "llvm/PassManager.h" @@ -41,14 +41,14 @@ #include "llvm/CodeGen/FileWriters.h" #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetELFWriterInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Support/Mangler.h" #include "llvm/Support/Streams.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Debug.h" -#include <list> using namespace llvm; char ELFWriter::ID = 0; @@ -141,7 +141,22 @@ bool ELFWriter::doInitialization(Module &M) { return false; } -unsigned ELFWriter::getGlobalELFLinkage(const GlobalVariable *GV) { +unsigned ELFWriter::getGlobalELFVisibility(const GlobalValue *GV) { + switch (GV->getVisibility()) { + default: + assert(0 && "unknown visibility type"); + case GlobalValue::DefaultVisibility: + return ELFSym::STV_DEFAULT; + case GlobalValue::HiddenVisibility: + return ELFSym::STV_HIDDEN; + case GlobalValue::ProtectedVisibility: + return ELFSym::STV_PROTECTED; + } + + return 0; +} + +unsigned ELFWriter::getGlobalELFLinkage(const GlobalValue *GV) { if (GV->hasInternalLinkage()) return ELFSym::STB_LOCAL; @@ -151,43 +166,51 @@ unsigned ELFWriter::getGlobalELFLinkage(const GlobalVariable *GV) { return ELFSym::STB_GLOBAL; } +// getElfSectionFlags - Get the ELF Section Header based on the +// flags defined in ELFTargetAsmInfo. +unsigned ELFWriter::getElfSectionFlags(unsigned Flags) { + unsigned ElfSectionFlags = ELFSection::SHF_ALLOC; + + if (Flags & SectionFlags::Code) + ElfSectionFlags |= ELFSection::SHF_EXECINSTR; + if (Flags & SectionFlags::Writeable) + ElfSectionFlags |= ELFSection::SHF_WRITE; + if (Flags & SectionFlags::Mergeable) + ElfSectionFlags |= ELFSection::SHF_MERGE; + if (Flags & SectionFlags::TLS) + ElfSectionFlags |= ELFSection::SHF_TLS; + if (Flags & SectionFlags::Strings) + ElfSectionFlags |= ELFSection::SHF_STRINGS; + + return ElfSectionFlags; +} + // For global symbols without a section, return the Null section as a // placeholder ELFSection &ELFWriter::getGlobalSymELFSection(const GlobalVariable *GV, ELFSym &Sym) { - const Section *S = TAI->SectionForGlobal(GV); - unsigned Flags = S->getFlags(); - unsigned SectionType = ELFSection::SHT_PROGBITS; - unsigned SHdrFlags = ELFSection::SHF_ALLOC; - DOUT << "Section " << S->getName() << " for global " << GV->getName() << "\n"; - - // If this is an external global, the symbol does not have a section. + // If this is a declaration, the symbol does not have a section. if (!GV->hasInitializer()) { Sym.SectionIdx = ELFSection::SHN_UNDEF; return getNullSection(); } + // Get the name and flags of the section for the global + const Section *S = TAI->SectionForGlobal(GV); + unsigned SectionType = ELFSection::SHT_PROGBITS; + unsigned SectionFlags = getElfSectionFlags(S->getFlags()); + DOUT << "Section " << S->getName() << " for global " << GV->getName() << "\n"; + const TargetData *TD = TM.getTargetData(); unsigned Align = TD->getPreferredAlignment(GV); Constant *CV = GV->getInitializer(); - if (Flags & SectionFlags::Code) - SHdrFlags |= ELFSection::SHF_EXECINSTR; - if (Flags & SectionFlags::Writeable) - SHdrFlags |= ELFSection::SHF_WRITE; - if (Flags & SectionFlags::Mergeable) - SHdrFlags |= ELFSection::SHF_MERGE; - if (Flags & SectionFlags::TLS) - SHdrFlags |= ELFSection::SHF_TLS; - if (Flags & SectionFlags::Strings) - SHdrFlags |= ELFSection::SHF_STRINGS; - // If this global has a zero initializer, go to .bss or common section. // Variables are part of the common block if they are zero initialized // and allowed to be merged with other symbols. if (CV->isNullValue() || isa<UndefValue>(CV)) { SectionType = ELFSection::SHT_NOBITS; - ELFSection &ElfS = getSection(S->getName(), SectionType, SHdrFlags); + ELFSection &ElfS = getSection(S->getName(), SectionType, SectionFlags); if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() || GV->hasCommonLinkage()) { Sym.SectionIdx = ELFSection::SHN_COMMON; @@ -203,7 +226,7 @@ ELFSection &ELFWriter::getGlobalSymELFSection(const GlobalVariable *GV, } Sym.IsConstant = true; - ELFSection &ElfS = getSection(S->getName(), SectionType, SHdrFlags); + ELFSection &ElfS = getSection(S->getName(), SectionType, SectionFlags); Sym.SectionIdx = ElfS.SectionIdx; ElfS.Align = std::max(ElfS.Align, Align); return ElfS; @@ -213,6 +236,7 @@ void ELFWriter::EmitFunctionDeclaration(const Function *F) { ELFSym GblSym(F); GblSym.setBind(ELFSym::STB_GLOBAL); GblSym.setType(ELFSym::STT_NOTYPE); + GblSym.setVisibility(ELFSym::STV_DEFAULT); GblSym.SectionIdx = ELFSection::SHN_UNDEF; SymbolList.push_back(GblSym); } @@ -222,6 +246,7 @@ void ELFWriter::EmitGlobalVar(const GlobalVariable *GV) { unsigned Align=0, Size=0; ELFSym GblSym(GV); GblSym.setBind(SymBind); + GblSym.setVisibility(getGlobalELFVisibility(GV)); if (GV->hasInitializer()) { GblSym.setType(ELFSym::STT_OBJECT); @@ -402,6 +427,7 @@ bool ELFWriter::doFinalization(Module &M) { SectionSym.Size = 0; SectionSym.setBind(ELFSym::STB_LOCAL); SectionSym.setType(ELFSym::STT_SECTION); + SectionSym.setVisibility(ELFSym::STV_DEFAULT); // Local symbols go in the list front SymbolList.push_front(SectionSym); @@ -443,7 +469,8 @@ void ELFWriter::EmitRelocations() { // Get the relocation section for section 'I' bool HasRelA = TEW->hasRelocationAddend(); - ELFSection &RelSec = getRelocSection(I->getName(), HasRelA); + ELFSection &RelSec = getRelocSection(I->getName(), HasRelA, + TEW->getPrefELFAlignment()); // 'Link' - Section hdr idx of the associated symbol table // 'Info' - Section hdr idx of the section to which the relocation applies diff --git a/lib/CodeGen/ELFWriter.h b/lib/CodeGen/ELFWriter.h index e0e71d0..bab118c 100644 --- a/lib/CodeGen/ELFWriter.h +++ b/lib/CodeGen/ELFWriter.h @@ -16,21 +16,23 @@ #include "llvm/ADT/SetVector.h" #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/Support/Debug.h" -#include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/TargetELFWriterInfo.h" -#include "ELF.h" #include <list> #include <map> namespace llvm { class BinaryObject; + class Constant; class ConstantStruct; class ELFCodeEmitter; class GlobalVariable; class Mangler; class MachineCodeEmitter; + class TargetAsmInfo; + class TargetELFWriterInfo; class raw_ostream; + class ELFSection; + class ELFSym; + class ELFRelocation; /// ELFWriter - This class implements the common target-independent code for /// writing ELF files. Targets should derive a class from this to @@ -116,19 +118,33 @@ namespace llvm { /// is seen, the symbol will move from this list to the SymbolList. SetVector<GlobalValue*> PendingGlobals; + // Remove tab from section name prefix. This is necessary becase TAI + // sometimes return a section name prefixed with a "\t" char. This is + // a little bit dirty. FIXME: find a better approach, maybe add more + // methods to TAI to get the clean name? + void fixNameForSection(std::string &Name) { + size_t Pos = Name.find("\t"); + if (Pos != std::string::npos) + Name.erase(Pos, 1); + + Pos = Name.find(".section "); + if (Pos != std::string::npos) + Name.erase(Pos, 9); + + Pos = Name.find("\n"); + if (Pos != std::string::npos) + Name.erase(Pos, 1); + } + /// getSection - Return the section with the specified name, creating a new /// section if one does not already exist. ELFSection &getSection(const std::string &Name, unsigned Type, unsigned Flags = 0, unsigned Align = 0) { - ELFSection *&SN = SectionLookup[Name]; - if (SN) return *SN; - - // Remove tab from section name prefix. This is necessary becase TAI - // sometimes return a section name prefixed with a "\t" char. std::string SectionName(Name); - size_t Pos = SectionName.find("\t"); - if (Pos != std::string::npos) - SectionName.erase(Pos, 1); + fixNameForSection(SectionName); + + ELFSection *&SN = SectionLookup[SectionName]; + if (SN) return *SN; SectionList.push_back(ELFSection(SectionName, isLittleEndian, is64Bit)); SN = &SectionList.back(); @@ -147,6 +163,12 @@ namespace llvm { ELFSection::SHF_EXECINSTR | ELFSection::SHF_ALLOC); } + /// Get jump table section on the section name returned by TAI + ELFSection &getJumpTableSection(std::string SName, unsigned Align) { + return getSection(SName, ELFSection::SHT_PROGBITS, + ELFSection::SHF_ALLOC, Align); + } + /// Get a constant pool section based on the section name returned by TAI ELFSection &getConstantPoolSection(std::string SName, unsigned Align) { return getSection(SName, ELFSection::SHT_PROGBITS, @@ -155,14 +177,14 @@ namespace llvm { /// Return the relocation section of section 'S'. 'RelA' is true /// if the relocation section contains entries with addends. - ELFSection &getRelocSection(std::string SName, bool RelA) { + ELFSection &getRelocSection(std::string SName, bool RelA, unsigned Align) { std::string RelSName(".rel"); unsigned SHdrTy = RelA ? ELFSection::SHT_RELA : ELFSection::SHT_REL; if (RelA) RelSName.append("a"); RelSName.append(SName); - return getSection(RelSName, SHdrTy, 0, TEW->getPrefELFAlignment()); + return getSection(RelSName, SHdrTy, 0, Align); } ELFSection &getNonExecStackSection() { @@ -195,6 +217,11 @@ namespace llvm { return getSection("", ELFSection::SHT_NULL, 0); } + // Helpers for obtaining ELF specific info. + unsigned getGlobalELFLinkage(const GlobalValue *GV); + unsigned getGlobalELFVisibility(const GlobalValue *GV); + unsigned getElfSectionFlags(unsigned Flags); + // As we complete the ELF file, we need to update fields in the ELF header // (e.g. the location of the section table). These members keep track of // the offset in ELFHeader of these various pieces to update and other @@ -209,7 +236,6 @@ namespace llvm { void EmitGlobalConstant(const Constant *C, ELFSection &GblS); void EmitGlobalConstantStruct(const ConstantStruct *CVS, ELFSection &GblS); - unsigned getGlobalELFLinkage(const GlobalVariable *GV); ELFSection &getGlobalSymELFSection(const GlobalVariable *GV, ELFSym &Sym); void EmitRelocations(); void EmitRelocation(BinaryObject &RelSec, ELFRelocation &Rel, bool HasRelA); diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index 21bb5dc..52a30bc 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -23,6 +23,7 @@ #include "llvm/CodeGen/LiveVariables.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" @@ -33,6 +34,8 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/STLExtras.h" #include <algorithm> @@ -98,6 +101,120 @@ void LiveIntervals::releaseMemory() { } } +/// processImplicitDefs - Process IMPLICIT_DEF instructions and make sure +/// there is one implicit_def for each use. Add isUndef marker to +/// implicit_def defs and their uses. +void LiveIntervals::processImplicitDefs() { + SmallSet<unsigned, 8> ImpDefRegs; + SmallVector<MachineInstr*, 8> ImpDefMIs; + MachineBasicBlock *Entry = mf_->begin(); + SmallPtrSet<MachineBasicBlock*,16> Visited; + for (df_ext_iterator<MachineBasicBlock*, SmallPtrSet<MachineBasicBlock*,16> > + DFI = df_ext_begin(Entry, Visited), E = df_ext_end(Entry, Visited); + DFI != E; ++DFI) { + MachineBasicBlock *MBB = *DFI; + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); + I != E; ) { + MachineInstr *MI = &*I; + ++I; + if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) { + unsigned Reg = MI->getOperand(0).getReg(); + MI->getOperand(0).setIsUndef(); + ImpDefRegs.insert(Reg); + ImpDefMIs.push_back(MI); + continue; + } + + bool ChangedToImpDef = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand& MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isUse()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; + if (!ImpDefRegs.count(Reg)) + continue; + // Use is a copy, just turn it into an implicit_def. + unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; + if (tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg) && + Reg == SrcReg) { + bool isKill = MO.isKill(); + MI->setDesc(tii_->get(TargetInstrInfo::IMPLICIT_DEF)); + for (int j = MI->getNumOperands() - 1, ee = 0; j > ee; --j) + MI->RemoveOperand(j); + if (isKill) + ImpDefRegs.erase(Reg); + ChangedToImpDef = true; + break; + } + + MO.setIsUndef(); + if (MO.isKill() || MI->isRegTiedToDefOperand(i)) + ImpDefRegs.erase(Reg); + } + + if (ChangedToImpDef) { + // Backtrack to process this new implicit_def. + --I; + } else { + for (unsigned i = 0; i != MI->getNumOperands(); ++i) { + MachineOperand& MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + ImpDefRegs.erase(MO.getReg()); + } + } + } + + // Any outstanding liveout implicit_def's? + for (unsigned i = 0, e = ImpDefMIs.size(); i != e; ++i) { + MachineInstr *MI = ImpDefMIs[i]; + unsigned Reg = MI->getOperand(0).getReg(); + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + // Physical registers are not liveout (yet). + continue; + if (!ImpDefRegs.count(Reg)) + continue; + + // If there are multiple defs of the same register and at least one + // is not an implicit_def, do not insert implicit_def's before the + // uses. + bool Skip = false; + for (MachineRegisterInfo::def_iterator DI = mri_->def_begin(Reg), + DE = mri_->def_end(); DI != DE; ++DI) { + if (DI->getOpcode() != TargetInstrInfo::IMPLICIT_DEF) { + Skip = true; + break; + } + } + if (Skip) + continue; + + for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(Reg), + UE = mri_->use_end(); UI != UE; ) { + MachineOperand &RMO = UI.getOperand(); + MachineInstr *RMI = &*UI; + ++UI; + MachineBasicBlock *RMBB = RMI->getParent(); + if (RMBB == MBB) + continue; + const TargetRegisterClass* RC = mri_->getRegClass(Reg); + unsigned NewVReg = mri_->createVirtualRegister(RC); + MachineInstrBuilder MIB = + BuildMI(*RMBB, RMI, RMI->getDebugLoc(), + tii_->get(TargetInstrInfo::IMPLICIT_DEF), NewVReg); + (*MIB).getOperand(0).setIsUndef(); + RMO.setReg(NewVReg); + RMO.setIsUndef(); + RMO.setIsKill(); + } + } + ImpDefRegs.clear(); + ImpDefMIs.clear(); + } +} + void LiveIntervals::computeNumbering() { Index2MiMap OldI2MI = i2miMap_; std::vector<IdxMBBPair> OldI2MBB = Idx2MBBMap; @@ -299,6 +416,7 @@ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) { lv_ = &getAnalysis<LiveVariables>(); allocatableRegs_ = tri_->getAllocatableSet(fn); + processImplicitDefs(); computeNumbering(); computeIntervals(); @@ -1782,8 +1900,10 @@ LiveIntervals::handleSpilledImpDefs(const LiveInterval &li, VirtRegMap &vrm, NewLIs.push_back(&getOrCreateInterval(NewVReg)); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { MachineOperand &MO = MI->getOperand(i); - if (MO.isReg() && MO.getReg() == li.reg) + if (MO.isReg() && MO.getReg() == li.reg) { MO.setReg(NewVReg); + MO.setIsUndef(); + } } } } diff --git a/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp index 2d2b59e..599efb8 100644 --- a/lib/CodeGen/MachineFunction.cpp +++ b/lib/CodeGen/MachineFunction.cpp @@ -14,6 +14,10 @@ //===----------------------------------------------------------------------===// #include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Config/config.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -22,15 +26,12 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetFrameInfo.h" -#include "llvm/Function.h" -#include "llvm/Instructions.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/GraphWriter.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/Config/config.h" #include <fstream> #include <sstream> using namespace llvm; @@ -124,6 +125,7 @@ MachineFunction::MachineFunction(const Function *F, MachineFrameInfo(*TM.getFrameInfo()); ConstantPool = new (Allocator.Allocate<MachineConstantPool>()) MachineConstantPool(TM.getTargetData()); + Alignment = TM.getTargetLowering()->getFunctionAlignment(F); // Set up jump table. const TargetData &TD = *TM.getTargetData(); diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index c977508..d44305f 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -120,7 +120,7 @@ void MachineOperand::ChangeToImmediate(int64_t ImmVal) { /// the specified value. If an operand is known to be an register already, /// the setReg method should be used. void MachineOperand::ChangeToRegister(unsigned Reg, bool isDef, bool isImp, - bool isKill, bool isDead) { + bool isKill, bool isDead, bool isUndef) { // If this operand is already a register operand, use setReg to update the // register's use/def lists. if (isReg()) { @@ -143,6 +143,7 @@ void MachineOperand::ChangeToRegister(unsigned Reg, bool isDef, bool isImp, IsImp = isImp; IsKill = isKill; IsDead = isDead; + IsUndef = isUndef; IsEarlyClobber = false; SubReg = 0; } @@ -206,11 +207,11 @@ void MachineOperand::print(raw_ostream &OS, const TargetMachine *TM) const { OS << "%mreg" << getReg(); } - if (getSubReg() != 0) { + if (getSubReg() != 0) OS << ':' << getSubReg(); - } - if (isDef() || isKill() || isDead() || isImplicit() || isEarlyClobber()) { + if (isDef() || isKill() || isDead() || isImplicit() || isUndef() || + isEarlyClobber()) { OS << '<'; bool NeedComma = false; if (isImplicit()) { @@ -224,10 +225,15 @@ void MachineOperand::print(raw_ostream &OS, const TargetMachine *TM) const { OS << "def"; NeedComma = true; } - if (isKill() || isDead()) { + if (isKill() || isDead() || isUndef()) { if (NeedComma) OS << ','; if (isKill()) OS << "kill"; if (isDead()) OS << "dead"; + if (isUndef()) { + if (isKill() || isDead()) + OS << ','; + OS << "undef"; + } } OS << '>'; } diff --git a/lib/CodeGen/MachineLoopInfo.cpp b/lib/CodeGen/MachineLoopInfo.cpp index 68ddb7b..ff56f4d 100644 --- a/lib/CodeGen/MachineLoopInfo.cpp +++ b/lib/CodeGen/MachineLoopInfo.cpp @@ -30,7 +30,7 @@ const PassInfo *const llvm::MachineLoopInfoID = &X; bool MachineLoopInfo::runOnMachineFunction(MachineFunction &) { releaseMemory(); - LI->Calculate(getAnalysis<MachineDominatorTree>().getBase()); // Update + LI.Calculate(getAnalysis<MachineDominatorTree>().getBase()); // Update return false; } diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp index 41a42fd..904b4cb 100644 --- a/lib/CodeGen/RegAllocLinearScan.cpp +++ b/lib/CodeGen/RegAllocLinearScan.cpp @@ -545,26 +545,6 @@ void RALinScan::linearScan() if (!isPhys && vrm_->getPreSplitReg(cur.reg)) continue; - // A register defined by an implicit_def can be liveout the def BB and livein - // to a use BB. Add it to the livein set of the use BB's. - if (!isPhys && cur.empty()) { - if (MachineInstr *DefMI = mri_->getVRegDef(cur.reg)) { - assert(DefMI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF); - MachineBasicBlock *DefMBB = DefMI->getParent(); - SmallPtrSet<MachineBasicBlock*, 4> Seen; - Seen.insert(DefMBB); - for (MachineRegisterInfo::reg_iterator ri = mri_->reg_begin(cur.reg), - re = mri_->reg_end(); ri != re; ++ri) { - MachineInstr *UseMI = &*ri; - MachineBasicBlock *UseMBB = UseMI->getParent(); - if (Seen.insert(UseMBB)) { - assert(TargetRegisterInfo::isPhysicalRegister(Reg) && - "Adding a virtual register to livein set?"); - UseMBB->addLiveIn(Reg); - } - } - } - } for (LiveInterval::Ranges::const_iterator I = cur.begin(), E = cur.end(); I != E; ++I) { const LiveRange &LR = *I; diff --git a/lib/CodeGen/RegisterScavenging.cpp b/lib/CodeGen/RegisterScavenging.cpp index 3feb92f..d7fe7a2 100644 --- a/lib/CodeGen/RegisterScavenging.cpp +++ b/lib/CodeGen/RegisterScavenging.cpp @@ -36,7 +36,7 @@ static bool RedefinesSuperRegPart(const MachineInstr *MI, unsigned SubReg, bool SeenSuperDef = false; for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); - if (!MO.isReg()) + if (!MO.isReg() || MO.isUndef()) continue; if (TRI->isSuperRegister(SubReg, MO.getReg())) { if (MO.isUse()) @@ -57,28 +57,22 @@ static bool RedefinesSuperRegPart(const MachineInstr *MI, } /// setUsed - Set the register and its sub-registers as being used. -void RegScavenger::setUsed(unsigned Reg, bool ImpDef) { +void RegScavenger::setUsed(unsigned Reg) { RegsAvailable.reset(Reg); - ImplicitDefed[Reg] = ImpDef; for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); - unsigned SubReg = *SubRegs; ++SubRegs) { + unsigned SubReg = *SubRegs; ++SubRegs) RegsAvailable.reset(SubReg); - ImplicitDefed[SubReg] = ImpDef; - } } /// setUnused - Set the register and its sub-registers as being unused. void RegScavenger::setUnused(unsigned Reg, const MachineInstr *MI) { RegsAvailable.set(Reg); - ImplicitDefed.reset(Reg); for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); unsigned SubReg = *SubRegs; ++SubRegs) - if (!RedefinesSuperRegPart(MI, Reg, TRI)) { + if (!RedefinesSuperRegPart(MI, Reg, TRI)) RegsAvailable.set(SubReg); - ImplicitDefed.reset(SubReg); - } } void RegScavenger::enterBasicBlock(MachineBasicBlock *mbb) { @@ -94,7 +88,6 @@ void RegScavenger::enterBasicBlock(MachineBasicBlock *mbb) { if (!MBB) { NumPhysRegs = TRI->getNumRegs(); RegsAvailable.resize(NumPhysRegs); - ImplicitDefed.resize(NumPhysRegs); // Create reserved registers bitvector. ReservedRegs = TRI->getReservedRegs(MF); @@ -113,7 +106,6 @@ void RegScavenger::enterBasicBlock(MachineBasicBlock *mbb) { ScavengeRestore = NULL; CurrDist = 0; DistanceMap.clear(); - ImplicitDefed.reset(); // All registers started out unused. RegsAvailable.set(); @@ -195,7 +187,10 @@ void RegScavenger::forward() { ScavengeRestore = NULL; } - bool IsImpDef = MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF; +#if 0 + if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) + return; +#endif // Separate register operands into 3 classes: uses, defs, earlyclobbers. SmallVector<std::pair<const MachineOperand*,unsigned>, 4> UseMOs; @@ -203,7 +198,7 @@ void RegScavenger::forward() { SmallVector<std::pair<const MachineOperand*,unsigned>, 4> EarlyClobberMOs; for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); - if (!MO.isReg() || MO.getReg() == 0) + if (!MO.isReg() || MO.getReg() == 0 || MO.isUndef()) continue; if (MO.isUse()) UseMOs.push_back(std::make_pair(&MO,i)); @@ -221,14 +216,7 @@ void RegScavenger::forward() { assert(isUsed(Reg) && "Using an undefined register!"); - // Kill of implicit_def defined registers are ignored. e.g. - // entry: 0x2029ab8, LLVM BB @0x1b06080, ID#0: - // Live Ins: %R0 - // %R0<def> = IMPLICIT_DEF - // %R0<def> = IMPLICIT_DEF - // STR %R0<kill>, %R0, %reg0, 0, 14, %reg0, Mem:ST(4,4) [0x1b06510 + 0] - // %R1<def> = LDR %R0, %reg0, 24, 14, %reg0, Mem:LD(4,4) [0x1b065bc + 0] - if (MO.isKill() && !isReserved(Reg) && !isImplicitlyDefined(Reg)) { + if (MO.isKill() && !isReserved(Reg)) { KillRegs.set(Reg); // Mark sub-registers as used. @@ -254,6 +242,8 @@ void RegScavenger::forward() { unsigned Idx = (i < NumECs) ? EarlyClobberMOs[i].second : DefMOs[i-NumECs].second; unsigned Reg = MO.getReg(); + if (MO.isUndef()) + continue; // If it's dead upon def, then it is now free. if (MO.isDead()) { @@ -262,7 +252,9 @@ void RegScavenger::forward() { } // Skip two-address destination operand. - if (MI->isRegTiedToUseOperand(Idx)) { + unsigned UseIdx; + if (MI->isRegTiedToUseOperand(Idx, &UseIdx) && + !MI->getOperand(UseIdx).isUndef()) { assert(isUsed(Reg) && "Using an undefined register!"); continue; } @@ -274,10 +266,9 @@ void RegScavenger::forward() { // Implicit def is allowed to "re-define" any register. Similarly, // implicitly defined registers can be clobbered. assert((isReserved(Reg) || isUnused(Reg) || - IsImpDef || isImplicitlyDefined(Reg) || isLiveInButUnusedBefore(Reg, MI, MBB, TRI, MRI)) && "Re-defining a live register!"); - setUsed(Reg, IsImpDef); + setUsed(Reg); } } @@ -297,7 +288,7 @@ void RegScavenger::backward() { SmallVector<std::pair<const MachineOperand*,unsigned>, 4> EarlyClobberMOs; for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); - if (!MO.isReg() || MO.getReg() == 0) + if (!MO.isReg() || MO.getReg() == 0 || MO.isUndef()) continue; if (MO.isUse()) UseMOs.push_back(std::make_pair(&MO,i)); @@ -316,6 +307,8 @@ void RegScavenger::backward() { ? *DefMOs[i].first : *EarlyClobberMOs[i-NumDefs].first; unsigned Idx = (i < NumECs) ? DefMOs[i].second : EarlyClobberMOs[i-NumDefs].second; + if (MO.isUndef()) + continue; // Skip two-address destination operand. if (MI->isRegTiedToUseOperand(Idx)) diff --git a/lib/CodeGen/SelectionDAG/CMakeLists.txt b/lib/CodeGen/SelectionDAG/CMakeLists.txt index 9ea59ea..4ffe88f 100644 --- a/lib/CodeGen/SelectionDAG/CMakeLists.txt +++ b/lib/CodeGen/SelectionDAG/CMakeLists.txt @@ -20,3 +20,5 @@ add_llvm_library(LLVMSelectionDAG SelectionDAGPrinter.cpp TargetLowering.cpp ) + +target_link_libraries (LLVMSelectionDAG LLVMAnalysis LLVMAsmPrinter LLVMCodeGen) diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index 24fccf0..cd2d5ac 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -326,19 +326,14 @@ bool FastISel::SelectCall(User *I) { default: break; case Intrinsic::dbg_stoppoint: { DbgStopPointInst *SPI = cast<DbgStopPointInst>(I); - if (DIDescriptor::ValidDebugInfo(SPI->getContext(), CodeGenOpt::None)) { - DICompileUnit CU(cast<GlobalVariable>(SPI->getContext())); - unsigned Line = SPI->getLine(); - unsigned Col = SPI->getColumn(); - unsigned Idx = MF.getOrCreateDebugLocID(CU.getGV(), Line, Col); - setCurDebugLoc(DebugLoc::get(Idx)); - } + if (isValidDebugInfoIntrinsic(*SPI, CodeGenOpt::None)) + setCurDebugLoc(ExtractDebugLocation(*SPI, MF.getDebugLocInfo())); return true; } case Intrinsic::dbg_region_start: { DbgRegionStartInst *RSI = cast<DbgRegionStartInst>(I); - if (DIDescriptor::ValidDebugInfo(RSI->getContext(), CodeGenOpt::None) && - DW && DW->ShouldEmitDwarfDebug()) { + if (isValidDebugInfoIntrinsic(*RSI, CodeGenOpt::None) && DW + && DW->ShouldEmitDwarfDebug()) { unsigned ID = DW->RecordRegionStart(cast<GlobalVariable>(RSI->getContext())); const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL); @@ -348,11 +343,11 @@ bool FastISel::SelectCall(User *I) { } case Intrinsic::dbg_region_end: { DbgRegionEndInst *REI = cast<DbgRegionEndInst>(I); - if (DIDescriptor::ValidDebugInfo(REI->getContext(), CodeGenOpt::None) && - DW && DW->ShouldEmitDwarfDebug()) { + if (isValidDebugInfoIntrinsic(*REI, CodeGenOpt::None) && DW + && DW->ShouldEmitDwarfDebug()) { unsigned ID = 0; DISubprogram Subprogram(cast<GlobalVariable>(REI->getContext())); - if (!Subprogram.isNull() && !Subprogram.describes(MF.getFunction())) { + if (isInlinedFnEnd(*REI, MF.getFunction())) { // This is end of an inlined function. const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL); ID = DW->RecordInlinedFnEnd(Subprogram); @@ -372,81 +367,67 @@ bool FastISel::SelectCall(User *I) { } case Intrinsic::dbg_func_start: { DbgFuncStartInst *FSI = cast<DbgFuncStartInst>(I); - Value *SP = FSI->getSubprogram(); - if (!DIDescriptor::ValidDebugInfo(SP, CodeGenOpt::None)) + if (!isValidDebugInfoIntrinsic(*FSI, CodeGenOpt::None) || !DW + || !DW->ShouldEmitDwarfDebug()) return true; - // llvm.dbg.func.start implicitly defines a dbg_stoppoint which is what - // (most?) gdb expects. - DebugLoc PrevLoc = DL; - DISubprogram Subprogram(cast<GlobalVariable>(SP)); - DICompileUnit CompileUnit = Subprogram.getCompileUnit(); - - if (!Subprogram.describes(MF.getFunction())) { + if (isInlinedFnStart(*FSI, MF.getFunction())) { // This is a beginning of an inlined function. - + // If llvm.dbg.func.start is seen in a new block before any // llvm.dbg.stoppoint intrinsic then the location info is unknown. // FIXME : Why DebugLoc is reset at the beginning of each block ? + DebugLoc PrevLoc = DL; if (PrevLoc.isUnknown()) return true; // Record the source line. - unsigned Line = Subprogram.getLineNumber(); - setCurDebugLoc(DebugLoc::get(MF.getOrCreateDebugLocID( - CompileUnit.getGV(), Line, 0))); - - if (DW && DW->ShouldEmitDwarfDebug()) { - DebugLocTuple PrevLocTpl = MF.getDebugLocTuple(PrevLoc); - unsigned LabelID = DW->RecordInlinedFnStart(Subprogram, - DICompileUnit(PrevLocTpl.CompileUnit), - PrevLocTpl.Line, - PrevLocTpl.Col); - const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL); - BuildMI(MBB, DL, II).addImm(LabelID); - } - } else { - // Record the source line. - unsigned Line = Subprogram.getLineNumber(); - MF.setDefaultDebugLoc(DebugLoc::get(MF.getOrCreateDebugLocID( - CompileUnit.getGV(), Line, 0))); - if (DW && DW->ShouldEmitDwarfDebug()) { - // llvm.dbg.func_start also defines beginning of function scope. - DW->RecordRegionStart(cast<GlobalVariable>(FSI->getSubprogram())); - } + setCurDebugLoc(ExtractDebugLocation(*FSI, MF.getDebugLocInfo())); + + DebugLocTuple PrevLocTpl = MF.getDebugLocTuple(PrevLoc); + DISubprogram SP(cast<GlobalVariable>(FSI->getSubprogram())); + unsigned LabelID = DW->RecordInlinedFnStart(SP, + DICompileUnit(PrevLocTpl.CompileUnit), + PrevLocTpl.Line, + PrevLocTpl.Col); + const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL); + BuildMI(MBB, DL, II).addImm(LabelID); + return true; } - + + // This is a beginning of a new function. + MF.setDefaultDebugLoc(ExtractDebugLocation(*FSI, MF.getDebugLocInfo())); + + // llvm.dbg.func_start also defines beginning of function scope. + DW->RecordRegionStart(cast<GlobalVariable>(FSI->getSubprogram())); return true; } case Intrinsic::dbg_declare: { DbgDeclareInst *DI = cast<DbgDeclareInst>(I); + if (!isValidDebugInfoIntrinsic(*DI, CodeGenOpt::None) || !DW + || !DW->ShouldEmitDwarfDebug()) + return true; + Value *Variable = DI->getVariable(); - if (DIDescriptor::ValidDebugInfo(Variable, CodeGenOpt::None) && - DW && DW->ShouldEmitDwarfDebug()) { - // Determine the address of the declared object. - Value *Address = DI->getAddress(); - if (BitCastInst *BCI = dyn_cast<BitCastInst>(Address)) - Address = BCI->getOperand(0); - AllocaInst *AI = dyn_cast<AllocaInst>(Address); - // Don't handle byval struct arguments or VLAs, for example. - if (!AI) break; - DenseMap<const AllocaInst*, int>::iterator SI = - StaticAllocaMap.find(AI); - if (SI == StaticAllocaMap.end()) break; // VLAs. - int FI = SI->second; - - // Determine the debug globalvariable. - GlobalValue *GV = cast<GlobalVariable>(Variable); - - // Build the DECLARE instruction. - const TargetInstrDesc &II = TII.get(TargetInstrInfo::DECLARE); - MachineInstr *DeclareMI - = BuildMI(MBB, DL, II).addFrameIndex(FI).addGlobalAddress(GV); - DIVariable DV(cast<GlobalVariable>(GV)); - if (!DV.isNull()) { - // This is a local variable - DW->RecordVariableScope(DV, DeclareMI); - } - } + Value *Address = DI->getAddress(); + if (BitCastInst *BCI = dyn_cast<BitCastInst>(Address)) + Address = BCI->getOperand(0); + AllocaInst *AI = dyn_cast<AllocaInst>(Address); + // Don't handle byval struct arguments or VLAs, for example. + if (!AI) break; + DenseMap<const AllocaInst*, int>::iterator SI = + StaticAllocaMap.find(AI); + if (SI == StaticAllocaMap.end()) break; // VLAs. + int FI = SI->second; + + // Determine the debug globalvariable. + GlobalValue *GV = cast<GlobalVariable>(Variable); + + // Build the DECLARE instruction. + const TargetInstrDesc &II = TII.get(TargetInstrInfo::DECLARE); + MachineInstr *DeclareMI + = BuildMI(MBB, DL, II).addFrameIndex(FI).addGlobalAddress(GV); + DIVariable DV(cast<GlobalVariable>(GV)); + DW->RecordVariableScope(DV, DeclareMI); return true; } case Intrinsic::eh_exception: { diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index ef365e6..1413d95 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -1900,7 +1900,7 @@ SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, const Type *RetTy = Node->getValueType(0).getTypeForMVT(); std::pair<SDValue, SDValue> CallInfo = TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false, - CallingConv::C, false, Callee, Args, DAG, + 0, CallingConv::C, false, Callee, Args, DAG, Node->getDebugLoc()); // Legalize the call sequence, starting with the chain. This will advance @@ -2305,7 +2305,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, TargetLowering::ArgListTy Args; std::pair<SDValue, SDValue> CallResult = TLI.LowerCallTo(Node->getOperand(0), Type::VoidTy, - false, false, false, false, CallingConv::C, false, + false, false, false, false, 0, CallingConv::C, false, DAG.getExternalSymbol("abort", TLI.getPointerTy()), Args, DAG, dl); Results.push_back(CallResult.second); diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp index 00d71e1..3135a44 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp @@ -1006,7 +1006,7 @@ SDValue DAGTypeLegalizer::MakeLibCall(RTLIB::Libcall LC, MVT RetVT, const Type *RetTy = RetVT.getTypeForMVT(); std::pair<SDValue,SDValue> CallInfo = TLI.LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false, - false, CallingConv::C, false, Callee, Args, DAG, dl); + false, 0, CallingConv::C, false, Callee, Args, DAG, dl); return CallInfo.first; } diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp index e372b5b..7926339 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp @@ -617,7 +617,7 @@ void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone, bool IsCloned, for (; NumVals; --NumVals, ++i) { unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg(); MI->addOperand(MachineOperand::CreateReg(Reg, true, false, false, - false, 0, true)); + false, false, true)); } break; case 1: // Use of register. diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 0342f67..c8f4b52 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -3375,7 +3375,7 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, // FIXME: pass in DebugLoc std::pair<SDValue,SDValue> CallResult = TLI.LowerCallTo(Chain, Type::VoidTy, - false, false, false, false, CallingConv::C, false, + false, false, false, false, 0, CallingConv::C, false, getExternalSymbol("memcpy", TLI.getPointerTy()), Args, *this, dl); return CallResult.second; @@ -3421,7 +3421,7 @@ SDValue SelectionDAG::getMemmove(SDValue Chain, DebugLoc dl, SDValue Dst, // FIXME: pass in DebugLoc std::pair<SDValue,SDValue> CallResult = TLI.LowerCallTo(Chain, Type::VoidTy, - false, false, false, false, CallingConv::C, false, + false, false, false, false, 0, CallingConv::C, false, getExternalSymbol("memmove", TLI.getPointerTy()), Args, *this, dl); return CallResult.second; @@ -3473,7 +3473,7 @@ SDValue SelectionDAG::getMemset(SDValue Chain, DebugLoc dl, SDValue Dst, // FIXME: pass in DebugLoc std::pair<SDValue,SDValue> CallResult = TLI.LowerCallTo(Chain, Type::VoidTy, - false, false, false, false, CallingConv::C, false, + false, false, false, false, 0, CallingConv::C, false, getExternalSymbol("memset", TLI.getPointerTy()), Args, *this, dl); return CallResult.second; @@ -3605,7 +3605,8 @@ SelectionDAG::getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList, SDValue SelectionDAG::getCall(unsigned CallingConv, DebugLoc dl, bool IsVarArgs, bool IsTailCall, bool IsInreg, SDVTList VTs, - const SDValue *Operands, unsigned NumOperands) { + const SDValue *Operands, unsigned NumOperands, + unsigned NumFixedArgs) { // Do not include isTailCall in the folding set profile. FoldingSetNodeID ID; AddNodeIDNode(ID, ISD::CALL, VTs, Operands, NumOperands); @@ -3621,7 +3622,7 @@ SelectionDAG::getCall(unsigned CallingConv, DebugLoc dl, bool IsVarArgs, } SDNode *N = NodeAllocator.Allocate<CallSDNode>(); new (N) CallSDNode(CallingConv, dl, IsVarArgs, IsTailCall, IsInreg, - VTs, Operands, NumOperands); + VTs, Operands, NumOperands, NumFixedArgs); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); return SDValue(N, 0); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index 48ebd0f..260911e 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -332,30 +332,14 @@ void FunctionLoweringInfo::set(Function &fn, MachineFunction &mf, default: break; case Intrinsic::dbg_stoppoint: { DbgStopPointInst *SPI = cast<DbgStopPointInst>(I); - - if (DIDescriptor::ValidDebugInfo(SPI->getContext(), - CodeGenOpt::Default)) { - DICompileUnit CU(cast<GlobalVariable>(SPI->getContext())); - unsigned idx = MF->getOrCreateDebugLocID(CU.getGV(), - SPI->getLine(), - SPI->getColumn()); - DL = DebugLoc::get(idx); - } - + if (isValidDebugInfoIntrinsic(*SPI, CodeGenOpt::Default)) + DL = ExtractDebugLocation(*SPI, MF->getDebugLocInfo()); break; } case Intrinsic::dbg_func_start: { DbgFuncStartInst *FSI = cast<DbgFuncStartInst>(I); - Value *SP = FSI->getSubprogram(); - - if (DIDescriptor::ValidDebugInfo(SP, CodeGenOpt::Default)) { - DISubprogram Subprogram(cast<GlobalVariable>(SP)); - DICompileUnit CU(Subprogram.getCompileUnit()); - unsigned Line = Subprogram.getLineNumber(); - DL = DebugLoc::get(MF->getOrCreateDebugLocID(CU.getGV(), - Line, 0)); - } - + if (isValidDebugInfoIntrinsic(*FSI, CodeGenOpt::Default)) + DL = ExtractDebugLocation(*FSI, MF->getDebugLocInfo()); break; } } @@ -3887,13 +3871,11 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { } case Intrinsic::dbg_stoppoint: { DbgStopPointInst &SPI = cast<DbgStopPointInst>(I); - if (DIDescriptor::ValidDebugInfo(SPI.getContext(), OptLevel)) { + if (isValidDebugInfoIntrinsic(SPI, CodeGenOpt::Default)) { MachineFunction &MF = DAG.getMachineFunction(); - DICompileUnit CU(cast<GlobalVariable>(SPI.getContext())); - DebugLoc Loc = DebugLoc::get(MF.getOrCreateDebugLocID(CU.getGV(), - SPI.getLine(), SPI.getColumn())); + DebugLoc Loc = ExtractDebugLocation(SPI, MF.getDebugLocInfo()); setCurDebugLoc(Loc); - + if (OptLevel == CodeGenOpt::None) DAG.setRoot(DAG.getDbgStopPoint(Loc, getRoot(), SPI.getLine(), @@ -3905,135 +3887,103 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { case Intrinsic::dbg_region_start: { DwarfWriter *DW = DAG.getDwarfWriter(); DbgRegionStartInst &RSI = cast<DbgRegionStartInst>(I); - - if (DIDescriptor::ValidDebugInfo(RSI.getContext(), OptLevel) && - DW && DW->ShouldEmitDwarfDebug()) { + if (isValidDebugInfoIntrinsic(RSI, OptLevel) && DW + && DW->ShouldEmitDwarfDebug()) { unsigned LabelID = DW->RecordRegionStart(cast<GlobalVariable>(RSI.getContext())); DAG.setRoot(DAG.getLabel(ISD::DBG_LABEL, getCurDebugLoc(), getRoot(), LabelID)); } - return 0; } case Intrinsic::dbg_region_end: { DwarfWriter *DW = DAG.getDwarfWriter(); DbgRegionEndInst &REI = cast<DbgRegionEndInst>(I); - if (DIDescriptor::ValidDebugInfo(REI.getContext(), OptLevel) && - DW && DW->ShouldEmitDwarfDebug()) { - MachineFunction &MF = DAG.getMachineFunction(); - DISubprogram Subprogram(cast<GlobalVariable>(REI.getContext())); + if (!isValidDebugInfoIntrinsic(REI, OptLevel) || !DW + || !DW->ShouldEmitDwarfDebug()) + return 0; - if (Subprogram.isNull() || Subprogram.describes(MF.getFunction())) { - unsigned LabelID = - DW->RecordRegionEnd(cast<GlobalVariable>(REI.getContext())); - DAG.setRoot(DAG.getLabel(ISD::DBG_LABEL, getCurDebugLoc(), - getRoot(), LabelID)); - } else { - // This is end of inlined function. Debugging information for inlined - // function is not handled yet (only supported by FastISel). - if (OptLevel == CodeGenOpt::None) { - unsigned ID = DW->RecordInlinedFnEnd(Subprogram); - if (ID != 0) - // Returned ID is 0 if this is unbalanced "end of inlined - // scope". This could happen if optimizer eats dbg intrinsics or - // "beginning of inlined scope" is not recoginized due to missing - // location info. In such cases, do ignore this region.end. - DAG.setRoot(DAG.getLabel(ISD::DBG_LABEL, getCurDebugLoc(), - getRoot(), ID)); - } + MachineFunction &MF = DAG.getMachineFunction(); + DISubprogram Subprogram(cast<GlobalVariable>(REI.getContext())); + + if (isInlinedFnEnd(REI, MF.getFunction())) { + // This is end of inlined function. Debugging information for inlined + // function is not handled yet (only supported by FastISel). + if (OptLevel == CodeGenOpt::None) { + unsigned ID = DW->RecordInlinedFnEnd(Subprogram); + if (ID != 0) + // Returned ID is 0 if this is unbalanced "end of inlined + // scope". This could happen if optimizer eats dbg intrinsics or + // "beginning of inlined scope" is not recoginized due to missing + // location info. In such cases, do ignore this region.end. + DAG.setRoot(DAG.getLabel(ISD::DBG_LABEL, getCurDebugLoc(), + getRoot(), ID)); } - } + return 0; + } + unsigned LabelID = + DW->RecordRegionEnd(cast<GlobalVariable>(REI.getContext())); + DAG.setRoot(DAG.getLabel(ISD::DBG_LABEL, getCurDebugLoc(), + getRoot(), LabelID)); return 0; } case Intrinsic::dbg_func_start: { DwarfWriter *DW = DAG.getDwarfWriter(); DbgFuncStartInst &FSI = cast<DbgFuncStartInst>(I); - Value *SP = FSI.getSubprogram(); - if (!DIDescriptor::ValidDebugInfo(SP, OptLevel)) + if (!isValidDebugInfoIntrinsic(FSI, CodeGenOpt::None) || !DW + || !DW->ShouldEmitDwarfDebug()) return 0; MachineFunction &MF = DAG.getMachineFunction(); - if (OptLevel == CodeGenOpt::None) { - // llvm.dbg.func.start implicitly defines a dbg_stoppoint which is what - // (most?) gdb expects. + // This is a beginning of an inlined function. + if (isInlinedFnStart(FSI, MF.getFunction())) { + if (OptLevel != CodeGenOpt::None) + // FIXME: Debugging informaation for inlined function is only + // supported at CodeGenOpt::Node. + return 0; + DebugLoc PrevLoc = CurDebugLoc; - DISubprogram Subprogram(cast<GlobalVariable>(SP)); - DICompileUnit CompileUnit = Subprogram.getCompileUnit(); - - if (!Subprogram.describes(MF.getFunction())) { - // This is a beginning of an inlined function. - - // If llvm.dbg.func.start is seen in a new block before any - // llvm.dbg.stoppoint intrinsic then the location info is unknown. - // FIXME : Why DebugLoc is reset at the beginning of each block ? - if (PrevLoc.isUnknown()) - return 0; - - // Record the source line. - unsigned Line = Subprogram.getLineNumber(); - setCurDebugLoc(DebugLoc::get( - MF.getOrCreateDebugLocID(CompileUnit.getGV(), Line, 0))); - - if (DW && DW->ShouldEmitDwarfDebug()) { - DebugLocTuple PrevLocTpl = MF.getDebugLocTuple(PrevLoc); - unsigned LabelID = DW->RecordInlinedFnStart(Subprogram, - DICompileUnit(PrevLocTpl.CompileUnit), - PrevLocTpl.Line, - PrevLocTpl.Col); - DAG.setRoot(DAG.getLabel(ISD::DBG_LABEL, getCurDebugLoc(), - getRoot(), LabelID)); - } - } else { - // Record the source line. - unsigned Line = Subprogram.getLineNumber(); - MF.setDefaultDebugLoc(DebugLoc::get( - MF.getOrCreateDebugLocID(CompileUnit.getGV(), Line, 0))); - if (DW && DW->ShouldEmitDwarfDebug()) { - // llvm.dbg.func_start also defines beginning of function scope. - DW->RecordRegionStart(cast<GlobalVariable>(FSI.getSubprogram())); - } - } - } else { - DISubprogram Subprogram(cast<GlobalVariable>(SP)); - - std::string SPName; - Subprogram.getLinkageName(SPName); - if (!SPName.empty() - && strcmp(SPName.c_str(), MF.getFunction()->getNameStart())) { - // This is beginning of inlined function. Debugging information for - // inlined function is not handled yet (only supported by FastISel). + // If llvm.dbg.func.start is seen in a new block before any + // llvm.dbg.stoppoint intrinsic then the location info is unknown. + // FIXME : Why DebugLoc is reset at the beginning of each block ? + if (PrevLoc.isUnknown()) return 0; - } - - // llvm.dbg.func.start implicitly defines a dbg_stoppoint which is - // what (most?) gdb expects. - DICompileUnit CompileUnit = Subprogram.getCompileUnit(); - - // Record the source line but does not create a label for the normal - // function start. It will be emitted at asm emission time. However, - // create a label if this is a beginning of inlined function. - unsigned Line = Subprogram.getLineNumber(); - setCurDebugLoc(DebugLoc::get( - MF.getOrCreateDebugLocID(CompileUnit.getGV(), Line, 0))); - // FIXME - Start new region because llvm.dbg.func_start also defines - // beginning of function scope. + + // Record the source line. + setCurDebugLoc(ExtractDebugLocation(FSI, MF.getDebugLocInfo())); + + DebugLocTuple PrevLocTpl = MF.getDebugLocTuple(PrevLoc); + DISubprogram SP(cast<GlobalVariable>(FSI.getSubprogram())); + DICompileUnit CU(PrevLocTpl.CompileUnit); + unsigned LabelID = DW->RecordInlinedFnStart(SP, CU, + PrevLocTpl.Line, + PrevLocTpl.Col); + DAG.setRoot(DAG.getLabel(ISD::DBG_LABEL, getCurDebugLoc(), + getRoot(), LabelID)); + return 0; } + // This is a beginning of a new function. + MF.setDefaultDebugLoc(ExtractDebugLocation(FSI, MF.getDebugLocInfo())); + + // llvm.dbg.func_start also defines beginning of function scope. + DW->RecordRegionStart(cast<GlobalVariable>(FSI.getSubprogram())); return 0; } case Intrinsic::dbg_declare: { - if (OptLevel == CodeGenOpt::None) { - DbgDeclareInst &DI = cast<DbgDeclareInst>(I); - Value *Variable = DI.getVariable(); - if (DIDescriptor::ValidDebugInfo(Variable, OptLevel)) - DAG.setRoot(DAG.getNode(ISD::DECLARE, dl, MVT::Other, getRoot(), - getValue(DI.getAddress()), getValue(Variable))); - } else { - // FIXME: Do something sensible here when we support debug declare. - } + if (OptLevel != CodeGenOpt::None) + // FIXME: Variable debug info is not supported here. + return 0; + + DbgDeclareInst &DI = cast<DbgDeclareInst>(I); + if (!isValidDebugInfoIntrinsic(DI, CodeGenOpt::None)) + return 0; + + Value *Variable = DI.getVariable(); + DAG.setRoot(DAG.getNode(ISD::DECLARE, dl, MVT::Other, getRoot(), + getValue(DI.getAddress()), getValue(Variable))); return 0; } case Intrinsic::eh_exception: { @@ -4466,7 +4416,7 @@ void SelectionDAGLowering::LowerCallTo(CallSite CS, SDValue Callee, TLI.LowerCallTo(getRoot(), CS.getType(), CS.paramHasAttr(0, Attribute::SExt), CS.paramHasAttr(0, Attribute::ZExt), FTy->isVarArg(), - CS.paramHasAttr(0, Attribute::InReg), + CS.paramHasAttr(0, Attribute::InReg), FTy->getNumParams(), CS.getCallingConv(), IsTailCall && PerformTailCallOpt, Callee, Args, DAG, getCurDebugLoc()); @@ -5518,7 +5468,7 @@ void SelectionDAGLowering::visitMalloc(MallocInst &I) { std::pair<SDValue,SDValue> Result = TLI.LowerCallTo(getRoot(), I.getType(), false, false, false, false, - CallingConv::C, PerformTailCallOpt, + 0, CallingConv::C, PerformTailCallOpt, DAG.getExternalSymbol("malloc", IntPtr), Args, DAG, getCurDebugLoc()); setValue(&I, Result.first); // Pointers always fit in registers @@ -5534,7 +5484,7 @@ void SelectionDAGLowering::visitFree(FreeInst &I) { MVT IntPtr = TLI.getPointerTy(); std::pair<SDValue,SDValue> Result = TLI.LowerCallTo(getRoot(), Type::VoidTy, false, false, false, false, - CallingConv::C, PerformTailCallOpt, + 0, CallingConv::C, PerformTailCallOpt, DAG.getExternalSymbol("free", IntPtr), Args, DAG, getCurDebugLoc()); DAG.setRoot(Result.second); @@ -5707,7 +5657,7 @@ void TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG, std::pair<SDValue, SDValue> TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, bool RetSExt, bool RetZExt, bool isVarArg, - bool isInreg, + bool isInreg, unsigned NumFixedArgs, unsigned CallingConv, bool isTailCall, SDValue Callee, ArgListTy &Args, SelectionDAG &DAG, DebugLoc dl) { @@ -5805,7 +5755,7 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, isVarArg, isTailCall, isInreg, DAG.getVTList(&LoweredRetTys[0], LoweredRetTys.size()), - &Ops[0], Ops.size() + &Ops[0], Ops.size(), NumFixedArgs ); Chain = Res.getValue(LoweredRetTys.size() - 1); diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index c2105e6..7e7d6b8 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -2669,19 +2669,28 @@ SimpleRegisterCoalescing::TurnCopyIntoImpDef(MachineBasicBlock::iterator &I, CopyMI->setDesc(tii_->get(TargetInstrInfo::IMPLICIT_DEF)); for (int i = CopyMI->getNumOperands() - 1, e = 0; i > e; --i) CopyMI->RemoveOperand(i); + CopyMI->getOperand(0).setIsUndef(); bool NoUse = mri_->use_empty(SrcReg); if (NoUse) { - for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(SrcReg), - E = mri_->reg_end(); I != E; ) { - assert(I.getOperand().isDef()); - MachineInstr *DefMI = &*I; - ++I; + for (MachineRegisterInfo::reg_iterator RI = mri_->reg_begin(SrcReg), + RE = mri_->reg_end(); RI != RE; ) { + assert(RI.getOperand().isDef()); + MachineInstr *DefMI = &*RI; + ++RI; // The implicit_def source has no other uses, delete it. assert(DefMI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF); li_->RemoveMachineInstrFromMaps(DefMI); DefMI->eraseFromParent(); } } + + // Mark uses of implicit_def isUndef. + for (MachineRegisterInfo::use_iterator RI = mri_->use_begin(DstReg), + RE = mri_->use_end(); RI != RE; ++RI) { + assert((*RI).getParent() == MBB); + RI.getOperand().setIsUndef(); + } + ++I; return true; } diff --git a/lib/CodeGen/TargetInstrInfoImpl.cpp b/lib/CodeGen/TargetInstrInfoImpl.cpp index a5e1ee4..b759599 100644 --- a/lib/CodeGen/TargetInstrInfoImpl.cpp +++ b/lib/CodeGen/TargetInstrInfoImpl.cpp @@ -24,14 +24,19 @@ using namespace llvm; // operand 1 and 2. MachineInstr *TargetInstrInfoImpl::commuteInstruction(MachineInstr *MI, bool NewMI) const { - assert(MI->getOperand(1).isReg() && MI->getOperand(2).isReg() && + const TargetInstrDesc &TID = MI->getDesc(); + bool HasDef = TID.getNumDefs(); + unsigned Idx1 = HasDef ? 1 : 0; + unsigned Idx2 = HasDef ? 2 : 1; + + assert(MI->getOperand(Idx1).isReg() && MI->getOperand(Idx2).isReg() && "This only knows how to commute register operands so far"); - unsigned Reg1 = MI->getOperand(1).getReg(); - unsigned Reg2 = MI->getOperand(2).getReg(); - bool Reg1IsKill = MI->getOperand(1).isKill(); - bool Reg2IsKill = MI->getOperand(2).isKill(); + unsigned Reg1 = MI->getOperand(Idx1).getReg(); + unsigned Reg2 = MI->getOperand(Idx2).getReg(); + bool Reg1IsKill = MI->getOperand(Idx1).isKill(); + bool Reg2IsKill = MI->getOperand(Idx2).isKill(); bool ChangeReg0 = false; - if (MI->getOperand(0).getReg() == Reg1) { + if (HasDef && MI->getOperand(0).getReg() == Reg1) { // Must be two address instruction! assert(MI->getDesc().getOperandConstraint(0, TOI::TIED_TO) && "Expecting a two-address instruction!"); @@ -41,21 +46,27 @@ MachineInstr *TargetInstrInfoImpl::commuteInstruction(MachineInstr *MI, if (NewMI) { // Create a new instruction. - unsigned Reg0 = ChangeReg0 ? Reg2 : MI->getOperand(0).getReg(); - bool Reg0IsDead = MI->getOperand(0).isDead(); + unsigned Reg0 = HasDef + ? (ChangeReg0 ? Reg2 : MI->getOperand(0).getReg()) : 0; + bool Reg0IsDead = HasDef ? MI->getOperand(0).isDead() : false; MachineFunction &MF = *MI->getParent()->getParent(); - return BuildMI(MF, MI->getDebugLoc(), MI->getDesc()) - .addReg(Reg0, RegState::Define | getDeadRegState(Reg0IsDead)) - .addReg(Reg2, getKillRegState(Reg2IsKill)) - .addReg(Reg1, getKillRegState(Reg2IsKill)); + if (HasDef) + return BuildMI(MF, MI->getDebugLoc(), MI->getDesc()) + .addReg(Reg0, RegState::Define | getDeadRegState(Reg0IsDead)) + .addReg(Reg2, getKillRegState(Reg2IsKill)) + .addReg(Reg1, getKillRegState(Reg2IsKill)); + else + return BuildMI(MF, MI->getDebugLoc(), MI->getDesc()) + .addReg(Reg2, getKillRegState(Reg2IsKill)) + .addReg(Reg1, getKillRegState(Reg2IsKill)); } if (ChangeReg0) MI->getOperand(0).setReg(Reg2); - MI->getOperand(2).setReg(Reg1); - MI->getOperand(1).setReg(Reg2); - MI->getOperand(2).setIsKill(Reg1IsKill); - MI->getOperand(1).setIsKill(Reg2IsKill); + MI->getOperand(Idx2).setReg(Reg1); + MI->getOperand(Idx1).setReg(Reg2); + MI->getOperand(Idx2).setIsKill(Reg1IsKill); + MI->getOperand(Idx1).setIsKill(Reg2IsKill); return MI; } @@ -66,6 +77,9 @@ MachineInstr *TargetInstrInfoImpl::commuteInstruction(MachineInstr *MI, /// two-address instruction. bool TargetInstrInfoImpl::CommuteChangesDestination(MachineInstr *MI, unsigned &OpIdx) const{ + const TargetInstrDesc &TID = MI->getDesc(); + if (!TID.getNumDefs()) + return false; assert(MI->getOperand(1).isReg() && MI->getOperand(2).isReg() && "This only knows how to commute register operands so far"); if (MI->getOperand(0).getReg() == MI->getOperand(1).getReg()) { diff --git a/lib/CodeGen/VirtRegRewriter.cpp b/lib/CodeGen/VirtRegRewriter.cpp index bd6584a..be0b016 100644 --- a/lib/CodeGen/VirtRegRewriter.cpp +++ b/lib/CodeGen/VirtRegRewriter.cpp @@ -356,7 +356,7 @@ static void InvalidateKills(MachineInstr &MI, SmallVector<unsigned, 2> *KillRegs = NULL) { for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { MachineOperand &MO = MI.getOperand(i); - if (!MO.isReg() || !MO.isUse() || !MO.isKill()) + if (!MO.isReg() || !MO.isUse() || !MO.isKill() || MO.isUndef()) continue; unsigned Reg = MO.getReg(); if (TargetRegisterInfo::isVirtualRegister(Reg)) @@ -390,12 +390,12 @@ static bool InvalidateRegDef(MachineBasicBlock::iterator I, MachineOperand *DefOp = NULL; for (unsigned i = 0, e = DefMI->getNumOperands(); i != e; ++i) { MachineOperand &MO = DefMI->getOperand(i); - if (MO.isReg() && MO.isDef()) { - if (MO.getReg() == Reg) - DefOp = &MO; - else if (!MO.isDead()) - HasLiveDef = true; - } + if (!MO.isReg() || !MO.isUse() || !MO.isKill() || MO.isUndef()) + continue; + if (MO.getReg() == Reg) + DefOp = &MO; + else if (!MO.isDead()) + HasLiveDef = true; } if (!DefOp) return false; @@ -430,7 +430,7 @@ static void UpdateKills(MachineInstr &MI, const TargetRegisterInfo* TRI, std::vector<MachineOperand*> &KillOps) { for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { MachineOperand &MO = MI.getOperand(i); - if (!MO.isReg() || !MO.isUse()) + if (!MO.isReg() || !MO.isUse() || MO.isUndef()) continue; unsigned Reg = MO.getReg(); if (Reg == 0) @@ -1289,8 +1289,7 @@ private: if (InvalidateRegDef(PrevMII, *MII, KillRegs[j], HasOtherDef)) { MachineInstr *DeadDef = PrevMII; if (ReMatDefs.count(DeadDef) && !HasOtherDef) { - // FIXME: This assumes a remat def does not have side - // effects. + // FIXME: This assumes a remat def does not have side effects. VRM.RemoveMachineInstrFromMaps(DeadDef); MBB.erase(DeadDef); ++NumDRM; @@ -1569,6 +1568,8 @@ private: if (MO.isImplicit()) // If the virtual register is implicitly defined, emit a implicit_def // before so scavenger knows it's "defined". + // FIXME: This is a horrible hack done the by register allocator to + // remat a definition with virtual register operand. VirtUseOps.insert(VirtUseOps.begin(), i); else VirtUseOps.push_back(i); @@ -1595,6 +1596,7 @@ private: MI.getOperand(i).setReg(RReg); MI.getOperand(i).setSubReg(0); if (VRM.isImplicitlyDefined(VirtReg)) + // FIXME: Is this needed? BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(TargetInstrInfo::IMPLICIT_DEF), RReg); continue; @@ -1604,22 +1606,16 @@ private: if (!MO.isUse()) continue; // Handle defs in the loop below (handle use&def here though) - bool AvoidReload = false; - if (LIs->hasInterval(VirtReg)) { - LiveInterval &LI = LIs->getInterval(VirtReg); - if (!LI.liveAt(LIs->getUseIndex(LI.beginNumber()))) - // Must be defined by an implicit def. It should not be spilled. Note, - // this is for correctness reason. e.g. - // 8 %reg1024<def> = IMPLICIT_DEF - // 12 %reg1024<def> = INSERT_SUBREG %reg1024<kill>, %reg1025, 2 - // The live range [12, 14) are not part of the r1024 live interval since - // it's defined by an implicit def. It will not conflicts with live - // interval of r1025. Now suppose both registers are spilled, you can - // easily see a situation where both registers are reloaded before - // the INSERT_SUBREG and both target registers that would overlap. - AvoidReload = true; - } - + bool AvoidReload = MO.isUndef(); + // Check if it is defined by an implicit def. It should not be spilled. + // Note, this is for correctness reason. e.g. + // 8 %reg1024<def> = IMPLICIT_DEF + // 12 %reg1024<def> = INSERT_SUBREG %reg1024<kill>, %reg1025, 2 + // The live range [12, 14) are not part of the r1024 live interval since + // it's defined by an implicit def. It will not conflicts with live + // interval of r1025. Now suppose both registers are spilled, you can + // easily see a situation where both registers are reloaded before + // the INSERT_SUBREG and both target registers that would overlap. bool DoReMat = VRM.isReMaterialized(VirtReg); int SSorRMId = DoReMat ? VRM.getReMatId(VirtReg) : VRM.getStackSlot(VirtReg); @@ -2033,8 +2029,12 @@ private: if (!TargetRegisterInfo::isVirtualRegister(VirtReg)) { // Check to see if this is a noop copy. If so, eliminate the // instruction before considering the dest reg to be changed. + // Also check if it's copying from an "undef", if so, we can't + // eliminate this or else the undef marker is lost and it will + // confuses the scavenger. This is extremely rare. unsigned Src, Dst, SrcSR, DstSR; - if (TII->isMoveInstr(MI, Src, Dst, SrcSR, DstSR) && Src == Dst) { + if (TII->isMoveInstr(MI, Src, Dst, SrcSR, DstSR) && Src == Dst && + !MI.findRegisterUseOperand(Src)->isUndef()) { ++NumDCE; DOUT << "Removing now-noop copy: " << MI; SmallVector<unsigned, 2> KillRegs; @@ -2053,7 +2053,7 @@ private: Spills.disallowClobberPhysReg(VirtReg); goto ProcessNextInst; } - + // If it's not a no-op copy, it clobbers the value in the destreg. Spills.ClobberPhysReg(VirtReg); ReusedOperands.markClobbered(VirtReg); |