diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-02-16 09:30:23 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-02-16 09:30:23 +0000 |
commit | f25ddd991a5601d0101602c4c263a58c7af4b8a2 (patch) | |
tree | 4cfca640904d1896e25032757a61f8959c066919 /lib/CodeGen | |
parent | 3fd58f91dd318518f7daa4ba64c0aaf31799d89b (diff) | |
download | FreeBSD-src-f25ddd991a5601d0101602c4c263a58c7af4b8a2.zip FreeBSD-src-f25ddd991a5601d0101602c4c263a58c7af4b8a2.tar.gz |
Update LLVM to r96341.
Diffstat (limited to 'lib/CodeGen')
88 files changed, 5210 insertions, 4490 deletions
diff --git a/lib/CodeGen/AggressiveAntiDepBreaker.cpp b/lib/CodeGen/AggressiveAntiDepBreaker.cpp index ca1f4a3..8840622f 100644 --- a/lib/CodeGen/AggressiveAntiDepBreaker.cpp +++ b/lib/CodeGen/AggressiveAntiDepBreaker.cpp @@ -425,8 +425,7 @@ void AggressiveAntiDepBreaker::PrescanInstruction(MachineInstr *MI, unsigned Reg = MO.getReg(); if (Reg == 0) continue; // Ignore KILLs and passthru registers for liveness... - if ((MI->getOpcode() == TargetInstrInfo::KILL) || - (PassthruRegs.count(Reg) != 0)) + if (MI->isKill() || (PassthruRegs.count(Reg) != 0)) continue; // Update def for Reg and aliases. @@ -481,7 +480,7 @@ void AggressiveAntiDepBreaker::ScanInstruction(MachineInstr *MI, // Form a group of all defs and uses of a KILL instruction to ensure // that all registers are renamed as a group. - if (MI->getOpcode() == TargetInstrInfo::KILL) { + if (MI->isKill()) { DEBUG(dbgs() << "\tKill Group:"); unsigned FirstReg = 0; @@ -792,7 +791,7 @@ unsigned AggressiveAntiDepBreaker::BreakAntiDependencies( // Ignore KILL instructions (they form a group in ScanInstruction // but don't cause any anti-dependence breaking themselves) - if (MI->getOpcode() != TargetInstrInfo::KILL) { + if (!MI->isKill()) { // Attempt to break each anti-dependency... for (unsigned i = 0, e = Edges.size(); i != e; ++i) { SDep *Edge = Edges[i]; diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index f4d8864..fc08384 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "asm-printer" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/Assembly/Writer.h" #include "llvm/DerivedTypes.h" @@ -24,6 +25,7 @@ #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/DebugInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" @@ -31,10 +33,6 @@ #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/FormattedStream.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" @@ -45,37 +43,27 @@ #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/FormattedStream.h" #include <cerrno> using namespace llvm; -static cl::opt<cl::boolOrDefault> -AsmVerbose("asm-verbose", cl::desc("Add comments to directives."), - cl::init(cl::BOU_UNSET)); - -static bool getVerboseAsm(bool VDef) { - switch (AsmVerbose) { - default: - case cl::BOU_UNSET: return VDef; - case cl::BOU_TRUE: return true; - case cl::BOU_FALSE: return false; - } -} +STATISTIC(EmittedInsts, "Number of machine instrs printed"); char AsmPrinter::ID = 0; AsmPrinter::AsmPrinter(formatted_raw_ostream &o, TargetMachine &tm, - const MCAsmInfo *T, bool VDef) - : MachineFunctionPass(&ID), FunctionNumber(0), O(o), + MCContext &Ctx, MCStreamer &Streamer, + const MCAsmInfo *T) + : MachineFunctionPass(&ID), O(o), TM(tm), MAI(T), TRI(tm.getRegisterInfo()), - - OutContext(*new MCContext()), - // FIXME: Pass instprinter to streamer. - OutStreamer(*createAsmStreamer(OutContext, O, *T, - TM.getTargetData()->isLittleEndian(), - getVerboseAsm(VDef), 0)), - + OutContext(Ctx), OutStreamer(Streamer), LastMI(0), LastFn(0), Counter(~0U), PrevDLT(NULL) { DW = 0; MMI = 0; - VerboseAsm = getVerboseAsm(VDef); + VerboseAsm = Streamer.isVerboseAsm(); } AsmPrinter::~AsmPrinter() { @@ -87,6 +75,12 @@ AsmPrinter::~AsmPrinter() { delete &OutContext; } +/// getFunctionNumber - Return a unique ID for the current function. +/// +unsigned AsmPrinter::getFunctionNumber() const { + return MF->getFunctionNumber(); +} + TargetLoweringObjectFile &AsmPrinter::getObjFileLowering() const { return TM.getTargetLowering()->getObjFileLowering(); } @@ -115,11 +109,11 @@ bool AsmPrinter::doInitialization(Module &M) { // Allow the target to emit any magic that it wants at the start of the file. EmitStartOfAsmFile(M); + // Very minimal debug info. It is ignored if we emit actual debug info. If we + // don't, this at least helps the user find where a global came from. if (MAI->hasSingleParameterDotFile()) { - // Very minimal debug info. It is ignored if we emit actual - // debug info. If we don't, this at least helps the user find where - // a function came from. - O << "\t.file\t\"" << M.getModuleIdentifier() << "\"\n"; + // .file "foo.c" + OutStreamer.EmitFileDirective(M.getModuleIdentifier()); } GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>(); @@ -144,6 +138,52 @@ bool AsmPrinter::doInitialization(Module &M) { return false; } +void AsmPrinter::EmitLinkage(unsigned Linkage, MCSymbol *GVSym) const { + switch ((GlobalValue::LinkageTypes)Linkage) { + case GlobalValue::CommonLinkage: + case GlobalValue::LinkOnceAnyLinkage: + case GlobalValue::LinkOnceODRLinkage: + case GlobalValue::WeakAnyLinkage: + case GlobalValue::WeakODRLinkage: + case GlobalValue::LinkerPrivateLinkage: + if (MAI->getWeakDefDirective() != 0) { + // .globl _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); + // .weak_definition _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_WeakDefinition); + } else if (const char *LinkOnce = MAI->getLinkOnceDirective()) { + // .globl _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); + // FIXME: linkonce should be a section attribute, handled by COFF Section + // assignment. + // http://sourceware.org/binutils/docs-2.20/as/Linkonce.html#Linkonce + // .linkonce discard + // FIXME: It would be nice to use .linkonce samesize for non-common + // globals. + O << LinkOnce; + } else { + // .weak _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak); + } + break; + case GlobalValue::DLLExportLinkage: + case GlobalValue::AppendingLinkage: + // FIXME: appending linkage variables should go into a section of + // their name or something. For now, just emit them as external. + case GlobalValue::ExternalLinkage: + // If external or appending, declare as a global symbol. + // .globl _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); + break; + case GlobalValue::PrivateLinkage: + case GlobalValue::InternalLinkage: + break; + default: + llvm_unreachable("Unknown linkage type!"); + } +} + + /// EmitGlobalVariable - Emit the specified global variable to the .s file. void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { if (!GV->hasInitializer()) // External globals require no code. @@ -154,15 +194,10 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { return; MCSymbol *GVSym = GetGlobalValueSymbol(GV); - printVisibility(GVSym, GV->getVisibility()); + EmitVisibility(GVSym, GV->getVisibility()); - if (MAI->hasDotTypeDotSizeDirective()) { - O << "\t.type\t" << *GVSym; - if (MAI->getCommentString()[0] != '@') - O << ",@object\n"; - else - O << ",%object\n"; - } + if (MAI->hasDotTypeDotSizeDirective()) + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject); SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM); @@ -224,47 +259,9 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { OutStreamer.SwitchSection(TheSection); - // TODO: Factor into an 'emit linkage' thing that is shared with function - // bodies. - switch (GV->getLinkage()) { - case GlobalValue::CommonLinkage: - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: - case GlobalValue::LinkerPrivateLinkage: - if (MAI->getWeakDefDirective() != 0) { - // .globl _foo - OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); - // .weak_definition _foo - OutStreamer.EmitSymbolAttribute(GVSym, MCSA_WeakDefinition); - } else if (const char *LinkOnce = MAI->getLinkOnceDirective()) { - // .globl _foo - OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); - // .linkonce same_size - O << LinkOnce; - } else { - // .weak _foo - OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak); - } - break; - case GlobalValue::DLLExportLinkage: - case GlobalValue::AppendingLinkage: - // FIXME: appending linkage variables should go into a section of - // their name or something. For now, just emit them as external. - case GlobalValue::ExternalLinkage: - // If external or appending, declare as a global symbol. - // .globl _foo - OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); - break; - case GlobalValue::PrivateLinkage: - case GlobalValue::InternalLinkage: - break; - default: - llvm_unreachable("Unknown linkage type!"); - } - + EmitLinkage(GV->getLinkage(), GVSym); EmitAlignment(AlignLog, GV); + if (VerboseAsm) { WriteAsOperand(OutStreamer.GetCommentOS(), GV, /*PrintType=*/false, GV->getParent()); @@ -275,7 +272,185 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { EmitGlobalConstant(GV->getInitializer()); if (MAI->hasDotTypeDotSizeDirective()) - O << "\t.size\t" << *GVSym << ", " << Size << '\n'; + // .size foo, 42 + OutStreamer.EmitELFSize(GVSym, MCConstantExpr::Create(Size, OutContext)); + + OutStreamer.AddBlankLine(); +} + +/// EmitFunctionHeader - This method emits the header for the current +/// function. +void AsmPrinter::EmitFunctionHeader() { + // Print out constants referenced by the function + EmitConstantPool(); + + // Print the 'header' of function. + const Function *F = MF->getFunction(); + + OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM)); + EmitVisibility(CurrentFnSym, F->getVisibility()); + + EmitLinkage(F->getLinkage(), CurrentFnSym); + EmitAlignment(MF->getAlignment(), F); + + if (MAI->hasDotTypeDotSizeDirective()) + OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction); + + if (VerboseAsm) { + WriteAsOperand(OutStreamer.GetCommentOS(), F, + /*PrintType=*/false, F->getParent()); + OutStreamer.GetCommentOS() << '\n'; + } + + // Emit the CurrentFnSym. This is a virtual function to allow targets to + // do their wild and crazy things as required. + EmitFunctionEntryLabel(); + + // Add some workaround for linkonce linkage on Cygwin\MinGW. + if (MAI->getLinkOnceDirective() != 0 && + (F->hasLinkOnceLinkage() || F->hasWeakLinkage())) + // FIXME: What is this? + O << "Lllvm$workaround$fake$stub$" << *CurrentFnSym << ":\n"; + + // Emit pre-function debug and/or EH information. + if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling()) + DW->BeginFunction(MF); +} + +/// EmitFunctionEntryLabel - Emit the label that is the entrypoint for the +/// function. This can be overridden by targets as required to do custom stuff. +void AsmPrinter::EmitFunctionEntryLabel() { + OutStreamer.EmitLabel(CurrentFnSym); +} + + +/// EmitComments - Pretty-print comments for instructions. +static void EmitComments(const MachineInstr &MI, raw_ostream &CommentOS) { + const MachineFunction *MF = MI.getParent()->getParent(); + const TargetMachine &TM = MF->getTarget(); + + if (!MI.getDebugLoc().isUnknown()) { + DILocation DLT = MF->getDILocation(MI.getDebugLoc()); + + // Print source line info. + DIScope Scope = DLT.getScope(); + // Omit the directory, because it's likely to be long and uninteresting. + if (!Scope.isNull()) + CommentOS << Scope.getFilename(); + else + CommentOS << "<unknown>"; + CommentOS << ':' << DLT.getLineNumber(); + if (DLT.getColumnNumber() != 0) + CommentOS << ':' << DLT.getColumnNumber(); + CommentOS << '\n'; + } + + // Check for spills and reloads + int FI; + + const MachineFrameInfo *FrameInfo = MF->getFrameInfo(); + + // We assume a single instruction only has a spill or reload, not + // both. + const MachineMemOperand *MMO; + if (TM.getInstrInfo()->isLoadFromStackSlotPostFE(&MI, FI)) { + if (FrameInfo->isSpillSlotObjectIndex(FI)) { + MMO = *MI.memoperands_begin(); + CommentOS << MMO->getSize() << "-byte Reload\n"; + } + } else if (TM.getInstrInfo()->hasLoadFromStackSlot(&MI, MMO, FI)) { + if (FrameInfo->isSpillSlotObjectIndex(FI)) + CommentOS << MMO->getSize() << "-byte Folded Reload\n"; + } else if (TM.getInstrInfo()->isStoreToStackSlotPostFE(&MI, FI)) { + if (FrameInfo->isSpillSlotObjectIndex(FI)) { + MMO = *MI.memoperands_begin(); + CommentOS << MMO->getSize() << "-byte Spill\n"; + } + } else if (TM.getInstrInfo()->hasStoreToStackSlot(&MI, MMO, FI)) { + if (FrameInfo->isSpillSlotObjectIndex(FI)) + CommentOS << MMO->getSize() << "-byte Folded Spill\n"; + } + + // Check for spill-induced copies + unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; + if (TM.getInstrInfo()->isMoveInstr(MI, SrcReg, DstReg, + SrcSubIdx, DstSubIdx)) { + if (MI.getAsmPrinterFlag(MachineInstr::ReloadReuse)) + CommentOS << " Reload Reuse\n"; + } +} + + + +/// EmitFunctionBody - This method emits the body and trailer for a +/// function. +void AsmPrinter::EmitFunctionBody() { + // Emit target-specific gunk before the function body. + EmitFunctionBodyStart(); + + // Print out code for the function. + bool HasAnyRealCode = false; + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E; ++I) { + // Print a label for the basic block. + EmitBasicBlockStart(I); + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + // Print the assembly for the instruction. + if (!II->isLabel()) + HasAnyRealCode = true; + + ++EmittedInsts; + + // FIXME: Clean up processDebugLoc. + processDebugLoc(II, true); + + if (VerboseAsm) + EmitComments(*II, OutStreamer.GetCommentOS()); + + switch (II->getOpcode()) { + case TargetOpcode::DBG_LABEL: + case TargetOpcode::EH_LABEL: + case TargetOpcode::GC_LABEL: + printLabelInst(II); + break; + case TargetOpcode::INLINEASM: + printInlineAsm(II); + break; + case TargetOpcode::IMPLICIT_DEF: + printImplicitDef(II); + break; + case TargetOpcode::KILL: + printKill(II); + break; + default: + EmitInstruction(II); + break; + } + + // FIXME: Clean up processDebugLoc. + processDebugLoc(II, false); + } + } + + // If the function is empty and the object file uses .subsections_via_symbols, + // then we need to emit *something* to the function body to prevent the + // labels from collapsing together. Just emit a 0 byte. + if (MAI->hasSubsectionsViaSymbols() && !HasAnyRealCode) + OutStreamer.EmitIntValue(0, 1, 0/*addrspace*/); + + // Emit target-specific gunk after the function body. + EmitFunctionBodyEnd(); + + if (MAI->hasDotTypeDotSizeDirective()) + O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n'; + + // Emit post-function debug information. + if (MAI->doesSupportDebugInformation() || MAI->doesSupportExceptionHandling()) + DW->EndFunction(MF); + + // Print out jump tables referenced by the function. + EmitJumpTableInfo(); OutStreamer.AddBlankLine(); } @@ -313,7 +488,7 @@ bool AsmPrinter::doFinalization(Module &M) { } } - if (MAI->getSetDirective()) { + if (MAI->hasSetDirective()) { OutStreamer.AddBlankLine(); for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; ++I) { @@ -329,9 +504,11 @@ bool AsmPrinter::doFinalization(Module &M) { else assert(I->hasLocalLinkage() && "Invalid alias linkage"); - printVisibility(Name, I->getVisibility()); + EmitVisibility(Name, I->getVisibility()); - O << MAI->getSetDirective() << ' ' << *Name << ", " << *Target << '\n'; + // Emit the directives as assignments aka .set: + OutStreamer.EmitAssignment(Name, + MCSymbolRefExpr::Create(Target, OutContext)); } } @@ -360,9 +537,9 @@ bool AsmPrinter::doFinalization(Module &M) { } void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { + this->MF = &MF; // Get the function symbol. CurrentFnSym = GetGlobalValueSymbol(MF.getFunction()); - IncrementFunctionNumber(); if (VerboseAsm) LI = &getAnalysis<MachineLoopInfo>(); @@ -383,7 +560,8 @@ namespace { /// used to print out constants which have been "spilled to memory" by /// the code generator. /// -void AsmPrinter::EmitConstantPool(MachineConstantPool *MCP) { +void AsmPrinter::EmitConstantPool() { + const MachineConstantPool *MCP = MF->getConstantPool(); const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants(); if (CP.empty()) return; @@ -470,27 +648,26 @@ void AsmPrinter::EmitConstantPool(MachineConstantPool *MCP) { /// EmitJumpTableInfo - Print assembly representations of the jump tables used /// by the current function to the current output stream. /// -void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI, - MachineFunction &MF) { +void AsmPrinter::EmitJumpTableInfo() { + const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); + if (MJTI == 0) return; const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); if (JT.empty()) return; - bool IsPic = TM.getRelocationModel() == Reloc::PIC_; - // Pick the directive to use to print the jump table entries, and switch to // the appropriate section. - TargetLowering *LoweringInfo = TM.getTargetLowering(); - - const Function *F = MF.getFunction(); + const Function *F = MF->getFunction(); bool JTInDiffSection = false; - if (F->isWeakForLinker() || - (IsPic && !LoweringInfo->usesGlobalOffsetTable())) { - // In PIC mode, we need to emit the jump table to the same section as the - // function body itself, otherwise the label differences won't make sense. - // We should also do if the section name is NULL or function is declared in - // discardable section. - OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, - TM)); + if (// In PIC mode, we need to emit the jump table to the same section as the + // function body itself, otherwise the label differences won't make sense. + // FIXME: Need a better predicate for this: what about custom entries? + MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 || + // We should also do if the section name is NULL or function is declared + // in discardable section + // FIXME: this isn't the right predicate, should be based on the MCSection + // for the function. + F->isWeakForLinker()) { + OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F,Mang,TM)); } else { // Otherwise, drop it in the readonly section. const MCSection *ReadOnlySection = @@ -498,73 +675,106 @@ void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI, OutStreamer.SwitchSection(ReadOnlySection); JTInDiffSection = true; } + + EmitAlignment(Log2_32(MJTI->getEntryAlignment(*TM.getTargetData()))); - EmitAlignment(Log2_32(MJTI->getAlignment())); - - for (unsigned i = 0, e = JT.size(); i != e; ++i) { - const std::vector<MachineBasicBlock*> &JTBBs = JT[i].MBBs; + for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) { + const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; // If this jump table was deleted, ignore it. if (JTBBs.empty()) continue; - // For PIC codegen, if possible we want to use the SetDirective to reduce - // the number of relocations the assembler will generate for the jump table. - // Set directives are all printed before the jump table itself. - SmallPtrSet<MachineBasicBlock*, 16> EmittedSets; - if (MAI->getSetDirective() && IsPic) - for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) - if (EmittedSets.insert(JTBBs[ii])) - printPICJumpTableSetLabel(i, JTBBs[ii]); + // For the EK_LabelDifference32 entry, if the target supports .set, emit a + // .set directive for each unique entry. This reduces the number of + // relocations the assembler will generate for the jump table. + if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 && + MAI->hasSetDirective()) { + SmallPtrSet<const MachineBasicBlock*, 16> EmittedSets; + const TargetLowering *TLI = TM.getTargetLowering(); + const MCExpr *Base = TLI->getPICJumpTableRelocBaseExpr(MF,JTI,OutContext); + for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) { + const MachineBasicBlock *MBB = JTBBs[ii]; + if (!EmittedSets.insert(MBB)) continue; + + // .set LJTSet, LBB32-base + const MCExpr *LHS = + MCSymbolRefExpr::Create(MBB->getSymbol(OutContext), OutContext); + OutStreamer.EmitAssignment(GetJTSetSymbol(JTI, MBB->getNumber()), + MCBinaryExpr::CreateSub(LHS, Base, OutContext)); + } + } // On some targets (e.g. Darwin) we want to emit two consequtive labels // before each jump table. The first label is never referenced, but tells // the assembler and linker the extents of the jump table object. The // second label is actually referenced by the code. if (JTInDiffSection && MAI->getLinkerPrivateGlobalPrefix()[0]) - OutStreamer.EmitLabel(GetJTISymbol(i, true)); + // FIXME: This doesn't have to have any specific name, just any randomly + // named and numbered 'l' label would work. Simplify GetJTISymbol. + OutStreamer.EmitLabel(GetJTISymbol(JTI, true)); - OutStreamer.EmitLabel(GetJTISymbol(i)); + OutStreamer.EmitLabel(GetJTISymbol(JTI)); - for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) { - printPICJumpTableEntry(MJTI, JTBBs[ii], i); - O << '\n'; - } + for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) + EmitJumpTableEntry(MJTI, JTBBs[ii], JTI); } } -void AsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, - const MachineBasicBlock *MBB, - unsigned uid) const { - bool isPIC = TM.getRelocationModel() == Reloc::PIC_; - - // Use JumpTableDirective otherwise honor the entry size from the jump table - // info. - const char *JTEntryDirective = MAI->getJumpTableDirective(isPIC); - bool HadJTEntryDirective = JTEntryDirective != NULL; - if (!HadJTEntryDirective) { - JTEntryDirective = MJTI->getEntrySize() == 4 ? - MAI->getData32bitsDirective() : MAI->getData64bitsDirective(); +/// EmitJumpTableEntry - Emit a jump table entry for the specified MBB to the +/// current stream. +void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, + const MachineBasicBlock *MBB, + unsigned UID) const { + const MCExpr *Value = 0; + switch (MJTI->getEntryKind()) { + case MachineJumpTableInfo::EK_Custom32: + Value = TM.getTargetLowering()->LowerCustomJumpTableEntry(MJTI, MBB, UID, + OutContext); + break; + case MachineJumpTableInfo::EK_BlockAddress: + // EK_BlockAddress - Each entry is a plain address of block, e.g.: + // .word LBB123 + Value = MCSymbolRefExpr::Create(MBB->getSymbol(OutContext), OutContext); + break; + case MachineJumpTableInfo::EK_GPRel32BlockAddress: { + // EK_GPRel32BlockAddress - Each entry is an address of block, encoded + // with a relocation as gp-relative, e.g.: + // .gprel32 LBB123 + MCSymbol *MBBSym = MBB->getSymbol(OutContext); + OutStreamer.EmitGPRel32Value(MCSymbolRefExpr::Create(MBBSym, OutContext)); + return; } - O << JTEntryDirective << ' '; - - // If we have emitted set directives for the jump table entries, print - // them rather than the entries themselves. If we're emitting PIC, then - // emit the table entries as differences between two text section labels. - // If we're emitting non-PIC code, then emit the entries as direct - // references to the target basic blocks. - if (!isPIC) { - O << *GetMBBSymbol(MBB->getNumber()); - } else if (MAI->getSetDirective()) { - O << MAI->getPrivateGlobalPrefix() << getFunctionNumber() - << '_' << uid << "_set_" << MBB->getNumber(); - } else { - O << *GetMBBSymbol(MBB->getNumber()); - // If the arch uses custom Jump Table directives, don't calc relative to - // JT. - if (!HadJTEntryDirective) - O << '-' << *GetJTISymbol(uid); + case MachineJumpTableInfo::EK_LabelDifference32: { + // EK_LabelDifference32 - Each entry is the address of the block minus + // the address of the jump table. This is used for PIC jump tables where + // gprel32 is not supported. e.g.: + // .word LBB123 - LJTI1_2 + // If the .set directive is supported, this is emitted as: + // .set L4_5_set_123, LBB123 - LJTI1_2 + // .word L4_5_set_123 + + // If we have emitted set directives for the jump table entries, print + // them rather than the entries themselves. If we're emitting PIC, then + // emit the table entries as differences between two text section labels. + if (MAI->hasSetDirective()) { + // If we used .set, reference the .set's symbol. + Value = MCSymbolRefExpr::Create(GetJTSetSymbol(UID, MBB->getNumber()), + OutContext); + break; + } + // Otherwise, use the difference as the jump table entry. + Value = MCSymbolRefExpr::Create(MBB->getSymbol(OutContext), OutContext); + const MCExpr *JTI = MCSymbolRefExpr::Create(GetJTISymbol(UID), OutContext); + Value = MCBinaryExpr::CreateSub(Value, JTI, OutContext); + break; + } } + + assert(Value && "Unknown entry kind!"); + + unsigned EntrySize = MJTI->getEntrySize(*TM.getTargetData()); + OutStreamer.EmitValue(Value, EntrySize, /*addrspace*/0); } @@ -683,48 +893,6 @@ void AsmPrinter::EmitInt64(uint64_t Value) const { OutStreamer.EmitIntValue(Value, 8, 0/*addrspace*/); } - -/// toOctal - Convert the low order bits of X into an octal digit. -/// -static inline char toOctal(int X) { - return (X&7)+'0'; -} - -/// printStringChar - Print a char, escaped if necessary. -/// -static void printStringChar(formatted_raw_ostream &O, unsigned char C) { - if (C == '"') { - O << "\\\""; - } else if (C == '\\') { - O << "\\\\"; - } else if (isprint((unsigned char)C)) { - O << C; - } else { - switch(C) { - case '\b': O << "\\b"; break; - case '\f': O << "\\f"; break; - case '\n': O << "\\n"; break; - case '\r': O << "\\r"; break; - case '\t': O << "\\t"; break; - default: - O << '\\'; - O << toOctal(C >> 6); - O << toOctal(C >> 3); - O << toOctal(C >> 0); - break; - } - } -} - -/// EmitFile - Emit a .file directive. -void AsmPrinter::EmitFile(unsigned Number, StringRef Name) const { - O << "\t.file\t" << Number << " \""; - for (unsigned i = 0, N = Name.size(); i < N; ++i) - printStringChar(O, Name[i]); - O << '\"'; -} - - //===----------------------------------------------------------------------===// // EmitAlignment - Emit an alignment directive to the specified power of @@ -779,15 +947,18 @@ static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) { } switch (CE->getOpcode()) { - case Instruction::ZExt: - case Instruction::SExt: - case Instruction::FPTrunc: - case Instruction::FPExt: - case Instruction::UIToFP: - case Instruction::SIToFP: - case Instruction::FPToUI: - case Instruction::FPToSI: - default: llvm_unreachable("FIXME: Don't support this constant cast expr"); + default: + // If the code isn't optimized, there may be outstanding folding + // opportunities. Attempt to fold the expression using TargetData as a + // last resort before giving up. + if (Constant *C = + ConstantFoldConstantExpression(CE, AP.TM.getTargetData())) + if (C != CE) + return LowerConstant(C, AP); +#ifndef NDEBUG + CE->dump(); +#endif + llvm_unreachable("FIXME: Don't support this constant expr"); case Instruction::GetElementPtr: { const TargetData &TD = *AP.TM.getTargetData(); // Generate a symbolic expression for the byte address @@ -851,8 +1022,14 @@ static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) { return MCBinaryExpr::CreateAnd(OpExpr, MaskExpr, Ctx); } + // The MC library also has a right-shift operator, but it isn't consistently + // signed or unsigned between different targets. case Instruction::Add: case Instruction::Sub: + case Instruction::Mul: + case Instruction::SDiv: + case Instruction::SRem: + case Instruction::Shl: case Instruction::And: case Instruction::Or: case Instruction::Xor: { @@ -862,6 +1039,10 @@ static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) { default: llvm_unreachable("Unknown binary operator constant cast expr"); case Instruction::Add: return MCBinaryExpr::CreateAdd(LHS, RHS, Ctx); case Instruction::Sub: return MCBinaryExpr::CreateSub(LHS, RHS, Ctx); + case Instruction::Mul: return MCBinaryExpr::CreateMul(LHS, RHS, Ctx); + case Instruction::SDiv: return MCBinaryExpr::CreateDiv(LHS, RHS, Ctx); + case Instruction::SRem: return MCBinaryExpr::CreateMod(LHS, RHS, Ctx); + case Instruction::Shl: return MCBinaryExpr::CreateShl(LHS, RHS, Ctx); case Instruction::And: return MCBinaryExpr::CreateAnd(LHS, RHS, Ctx); case Instruction::Or: return MCBinaryExpr::CreateOr (LHS, RHS, Ctx); case Instruction::Xor: return MCBinaryExpr::CreateXor(LHS, RHS, Ctx); @@ -1012,6 +1193,7 @@ static void EmitGlobalConstantLargeInt(const ConstantInt *CI, void AsmPrinter::EmitGlobalConstant(const Constant *CV, unsigned AddrSpace) { if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV)) { uint64_t Size = TM.getTargetData()->getTypeAllocSize(CV->getType()); + if (Size == 0) Size = 1; // An empty "_foo:" followed by a section is undef. return OutStreamer.EmitZeros(Size, AddrSpace); } @@ -1295,7 +1477,7 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { ++OpNo; // Skip over the ID number. if (Modifier[0] == 'l') // labels are target independent - O << *GetMBBSymbol(MI->getOperand(OpNo).getMBB()->getNumber()); + O << *MI->getOperand(OpNo).getMBB()->getSymbol(OutContext); else { AsmPrinter *AP = const_cast<AsmPrinter*>(this); if ((OpFlags & 7) == 4) { @@ -1320,6 +1502,7 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const { } } O << "\n\t" << MAI->getCommentString() << MAI->getInlineAsmEnd(); + OutStreamer.AddBlankLine(); } /// printImplicitDef - This method prints the specified machine instruction @@ -1329,6 +1512,7 @@ void AsmPrinter::printImplicitDef(const MachineInstr *MI) const { O.PadToColumn(MAI->getCommentColumn()); O << MAI->getCommentString() << " implicit-def: " << TRI->getName(MI->getOperand(0).getReg()); + OutStreamer.AddBlankLine(); } void AsmPrinter::printKill(const MachineInstr *MI) const { @@ -1340,12 +1524,14 @@ void AsmPrinter::printKill(const MachineInstr *MI) const { assert(op.isReg() && "KILL instruction must have only register operands"); O << ' ' << TRI->getName(op.getReg()) << (op.isDef() ? "<def>" : "<kill>"); } + OutStreamer.AddBlankLine(); } /// printLabel - This method prints a local label used by debug and /// exception handling tables. -void AsmPrinter::printLabel(const MachineInstr *MI) const { +void AsmPrinter::printLabelInst(const MachineInstr *MI) const { printLabel(MI->getOperand(0).getImm()); + OutStreamer.AddBlankLine(); } void AsmPrinter::printLabel(unsigned Id) const { @@ -1368,14 +1554,12 @@ bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, return true; } -MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BlockAddress *BA, - const char *Suffix) const { - return GetBlockAddressSymbol(BA->getFunction(), BA->getBasicBlock(), Suffix); +MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BlockAddress *BA) const { + return GetBlockAddressSymbol(BA->getFunction(), BA->getBasicBlock()); } MCSymbol *AsmPrinter::GetBlockAddressSymbol(const Function *F, - const BasicBlock *BB, - const char *Suffix) const { + const BasicBlock *BB) const { assert(BB->hasName() && "Address of anonymous basic block not supported yet!"); @@ -1389,19 +1573,12 @@ MCSymbol *AsmPrinter::GetBlockAddressSymbol(const Function *F, SmallString<60> NameResult; Mang->getNameWithPrefix(NameResult, StringRef("BA") + Twine((unsigned)FnName.size()) + - "_" + FnName.str() + "_" + BB->getName() + Suffix, + "_" + FnName.str() + "_" + BB->getName(), Mangler::Private); return OutContext.GetOrCreateSymbol(NameResult.str()); } -MCSymbol *AsmPrinter::GetMBBSymbol(unsigned MBBID) const { - SmallString<60> Name; - raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "BB" - << getFunctionNumber() << '_' << MBBID; - return OutContext.GetOrCreateSymbol(Name.str()); -} - /// GetCPISymbol - Return the symbol for the specified constant pool entry. MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const { SmallString<60> Name; @@ -1412,11 +1589,15 @@ MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const { /// GetJTISymbol - Return the symbol for the specified jump table entry. MCSymbol *AsmPrinter::GetJTISymbol(unsigned JTID, bool isLinkerPrivate) const { - const char *Prefix = isLinkerPrivate ? MAI->getLinkerPrivateGlobalPrefix() : - MAI->getPrivateGlobalPrefix(); + return MF->getJTISymbol(JTID, OutContext, isLinkerPrivate); +} + +/// GetJTSetSymbol - Return the symbol for the specified jump table .set +/// FIXME: privatize to AsmPrinter. +MCSymbol *AsmPrinter::GetJTSetSymbol(unsigned UID, unsigned MBBID) const { SmallString<60> Name; - raw_svector_ostream(Name) << Prefix << "JTI" << getFunctionNumber() << '_' - << JTID; + raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() + << getFunctionNumber() << '_' << UID << "_set_" << MBBID; return OutContext.GetOrCreateSymbol(Name.str()); } @@ -1476,7 +1657,7 @@ static void PrintChildLoopComment(raw_ostream &OS, const MachineLoop *Loop, } } -/// EmitComments - Pretty-print comments for basic blocks. +/// PrintBasicBlockLoopComments - Pretty-print comments for basic blocks. static void PrintBasicBlockLoopComments(const MachineBasicBlock &MBB, const MachineLoopInfo *LI, const AsmPrinter &AP) { @@ -1555,37 +1736,11 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const { PrintBasicBlockLoopComments(*MBB, LI, *this); } - OutStreamer.EmitLabel(GetMBBSymbol(MBB->getNumber())); + OutStreamer.EmitLabel(MBB->getSymbol(OutContext)); } } -/// printPICJumpTableSetLabel - This method prints a set label for the -/// specified MachineBasicBlock for a jumptable entry. -void AsmPrinter::printPICJumpTableSetLabel(unsigned uid, - const MachineBasicBlock *MBB) const { - if (!MAI->getSetDirective()) - return; - - O << MAI->getSetDirective() << ' ' << MAI->getPrivateGlobalPrefix() - << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ',' - << *GetMBBSymbol(MBB->getNumber()) - << '-' << *GetJTISymbol(uid) << '\n'; -} - -void AsmPrinter::printPICJumpTableSetLabel(unsigned uid, unsigned uid2, - const MachineBasicBlock *MBB) const { - if (!MAI->getSetDirective()) - return; - - O << MAI->getSetDirective() << ' ' << MAI->getPrivateGlobalPrefix() - << getFunctionNumber() << '_' << uid << '_' << uid2 - << "_set_" << MBB->getNumber() << ',' - << *GetMBBSymbol(MBB->getNumber()) - << '-' << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << uid << '_' << uid2 << '\n'; -} - -void AsmPrinter::printVisibility(MCSymbol *Sym, unsigned Visibility) const { +void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility) const { MCSymbolAttr Attr = MCSA_Invalid; switch (Visibility) { @@ -1633,86 +1788,3 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) { return 0; } -/// EmitComments - Pretty-print comments for instructions -void AsmPrinter::EmitComments(const MachineInstr &MI) const { - if (!VerboseAsm) - return; - - bool Newline = false; - - if (!MI.getDebugLoc().isUnknown()) { - DILocation DLT = MF->getDILocation(MI.getDebugLoc()); - - // Print source line info. - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' '; - DIScope Scope = DLT.getScope(); - // Omit the directory, because it's likely to be long and uninteresting. - if (!Scope.isNull()) - O << Scope.getFilename(); - else - O << "<unknown>"; - O << ':' << DLT.getLineNumber(); - if (DLT.getColumnNumber() != 0) - O << ':' << DLT.getColumnNumber(); - Newline = true; - } - - // Check for spills and reloads - int FI; - - const MachineFrameInfo *FrameInfo = - MI.getParent()->getParent()->getFrameInfo(); - - // We assume a single instruction only has a spill or reload, not - // both. - const MachineMemOperand *MMO; - if (TM.getInstrInfo()->isLoadFromStackSlotPostFE(&MI, FI)) { - if (FrameInfo->isSpillSlotObjectIndex(FI)) { - MMO = *MI.memoperands_begin(); - if (Newline) O << '\n'; - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' ' << MMO->getSize() << "-byte Reload"; - Newline = true; - } - } - else if (TM.getInstrInfo()->hasLoadFromStackSlot(&MI, MMO, FI)) { - if (FrameInfo->isSpillSlotObjectIndex(FI)) { - if (Newline) O << '\n'; - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' ' - << MMO->getSize() << "-byte Folded Reload"; - Newline = true; - } - } - else if (TM.getInstrInfo()->isStoreToStackSlotPostFE(&MI, FI)) { - if (FrameInfo->isSpillSlotObjectIndex(FI)) { - MMO = *MI.memoperands_begin(); - if (Newline) O << '\n'; - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' ' << MMO->getSize() << "-byte Spill"; - Newline = true; - } - } - else if (TM.getInstrInfo()->hasStoreToStackSlot(&MI, MMO, FI)) { - if (FrameInfo->isSpillSlotObjectIndex(FI)) { - if (Newline) O << '\n'; - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' ' - << MMO->getSize() << "-byte Folded Spill"; - Newline = true; - } - } - - // Check for spill-induced copies - unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; - if (TM.getInstrInfo()->isMoveInstr(MI, SrcReg, DstReg, - SrcSubIdx, DstSubIdx)) { - if (MI.getAsmPrinterFlag(ReloadReuse)) { - if (Newline) O << '\n'; - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << " Reload Reuse"; - } - } -} - diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp index 349e0ac..63360c0 100644 --- a/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/lib/CodeGen/AsmPrinter/DIE.cpp @@ -313,6 +313,7 @@ void DIESectionOffset::EmitValue(DwarfPrinter *D, unsigned Form) const { D->EmitSectionOffset(Label.getTag(), Section.getTag(), Label.getNumber(), Section.getNumber(), IsSmall, IsEH, UseSet); + D->getAsm()->O << '\n'; // FIXME: Necesssary? } /// SizeOf - Determine size of delta value in bytes. diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 513987f..5093dd9 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -26,6 +26,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ValueHandle.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Timer.h" #include "llvm/System/Path.h" @@ -166,7 +167,8 @@ public: class DbgScope { DbgScope *Parent; // Parent to this scope. DIDescriptor Desc; // Debug info descriptor for scope. - MDNode * InlinedAtLocation; // Location at which scope is inlined. + // Location at which this scope is inlined. + AssertingVH<MDNode> InlinedAtLocation; bool AbstractScope; // Abstract Scope unsigned StartLabelID; // Label ID of the beginning of scope. unsigned EndLabelID; // Label ID of the end of scope. @@ -189,7 +191,7 @@ public: void setParent(DbgScope *P) { Parent = P; } DIDescriptor getDesc() const { return Desc; } MDNode *getInlinedAt() const { - return dyn_cast_or_null<MDNode>(InlinedAtLocation); + return InlinedAtLocation; } MDNode *getScopeNode() const { return Desc.getNode(); } unsigned getStartLabelID() const { return StartLabelID; } @@ -616,7 +618,7 @@ void DwarfDebug::addComplexAddress(DbgVariable *&DV, DIE *Die, 1). Add the offset of the forwarding field. - 2). Follow that pointer to get the the real __Block_byref_x_VarName + 2). Follow that pointer to get the real __Block_byref_x_VarName struct to use (the real one may have been copied onto the heap). 3). Add the offset for the field VarName, to find the actual variable. @@ -937,7 +939,16 @@ void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { DIE *ElemDie = NULL; if (Element.getTag() == dwarf::DW_TAG_subprogram) ElemDie = createSubprogramDIE(DISubprogram(Element.getNode())); - else + else if (Element.getTag() == dwarf::DW_TAG_auto_variable) { + DIVariable DV(Element.getNode()); + ElemDie = new DIE(dwarf::DW_TAG_variable); + addString(ElemDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, + DV.getName()); + addType(ElemDie, DV.getType()); + addUInt(ElemDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + addUInt(ElemDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); + addSourceLine(ElemDie, &DV); + } else ElemDie = createMemberDIE(DIDerivedType(Element.getNode())); Buffer.addChild(ElemDie); } @@ -949,6 +960,11 @@ void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { if (RLang) addUInt(&Buffer, dwarf::DW_AT_APPLE_runtime_class, dwarf::DW_FORM_data1, RLang); + + DICompositeType ContainingType = CTy.getContainingType(); + if (!ContainingType.isNull()) + addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, + getOrCreateTypeDIE(DIType(ContainingType.getNode()))); break; } default: @@ -959,7 +975,7 @@ void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { if (!Name.empty()) addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); - if (Tag == dwarf::DW_TAG_enumeration_type || + if (Tag == dwarf::DW_TAG_enumeration_type || Tag == dwarf::DW_TAG_class_type || Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) { // Add size if non-zero (derived types might be zero-sized.) if (Size) @@ -1107,7 +1123,26 @@ DIE *DwarfDebug::createMemberDIE(const DIDerivedType &DT) { // This is not a bitfield. addUInt(MemLocationDie, 0, dwarf::DW_FORM_udata, DT.getOffsetInBits() >> 3); - addBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, MemLocationDie); + if (DT.getTag() == dwarf::DW_TAG_inheritance + && DT.isVirtual()) { + + // For C++, virtual base classes are not at fixed offset. Use following + // expression to extract appropriate offset from vtable. + // BaseAddr = ObAddr + *((*ObAddr) - Offset) + + DIEBlock *VBaseLocationDie = new DIEBlock(); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_dup); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_udata, DT.getOffsetInBits()); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_minus); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); + + addBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, + VBaseLocationDie); + } else + addBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, MemLocationDie); if (DT.isProtected()) addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, @@ -1179,12 +1214,17 @@ DIE *DwarfDebug::createSubprogramDIE(const DISubprogram &SP, bool MakeDecl) { if (SPTag == dwarf::DW_TAG_subroutine_type) for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); - addType(Arg, DIType(Args.getElement(i).getNode())); - addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); // ?? + DIType ATy = DIType(DIType(Args.getElement(i).getNode())); + addType(Arg, ATy); + if (ATy.isArtificial()) + addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); SPDie->addChild(Arg); } } + if (SP.isArtificial()) + addUInt(SPDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + // DW_TAG_inlined_subroutine may refer to this DIE. ModuleCU->insertDIE(SP.getNode(), SPDie); return SPDie; @@ -1289,7 +1329,13 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) { DIE *SPDie = ModuleCU->getDIE(SPNode); assert (SPDie && "Unable to find subprogram DIE!"); DISubprogram SP(SPNode); - if (SP.isDefinition() && !SP.getContext().isCompileUnit()) { + // There is not any need to generate specification DIE for a function + // defined at compile unit level. If a function is defined inside another + // function then gdb prefers the definition at top level and but does not + // expect specification DIE in parent function. So avoid creating + // specification DIE for a function defined inside a function. + if (SP.isDefinition() && !SP.getContext().isCompileUnit() + && !SP.getContext().isSubprogram()) { addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); // Add arguments. DICompositeType SPTy = SP.getType(); @@ -1298,8 +1344,10 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) { if (SPTag == dwarf::DW_TAG_subroutine_type) for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); - addType(Arg, DIType(Args.getElement(i).getNode())); - addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); // ?? + DIType ATy = DIType(DIType(Args.getElement(i).getNode())); + addType(Arg, ATy); + if (ATy.isArtificial()) + addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); SPDie->addChild(Arg); } DIE *SPDeclDie = SPDie; @@ -1308,7 +1356,7 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) { SPDeclDie); ModuleCU->addDie(SPDie); } - + 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, @@ -1471,6 +1519,9 @@ DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) { else addAddress(VariableDie, dwarf::DW_AT_location, Location); } + + if (Tag == dwarf::DW_TAG_formal_parameter && VD.getType().isArtificial()) + addUInt(VariableDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); DV->setDIE(VariableDie); return VariableDie; @@ -1669,6 +1720,7 @@ void DwarfDebug::constructGlobalVariableDIE(MDNode *N) { addObjectLabel(Block, 0, dwarf::DW_FORM_udata, Asm->GetGlobalValueSymbol(DI_GV.getGlobal())); addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block); + addUInt(VariableDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); ModuleCU->addDie(VariableSpecDIE); } else { DIEBlock *Block = new DIEBlock(); @@ -1779,8 +1831,7 @@ void DwarfDebug::beginModule(Module *M, MachineModuleInfo *mmi) { FullPath.appendComponent(getSourceFileName(Id.second)); assert(AppendOk && "Could not append filename to directory!"); AppendOk = false; - Asm->EmitFile(i, FullPath.str()); - Asm->O << '\n'; + Asm->OutStreamer.EmitDwarfFileDirective(i, FullPath.str()); } } @@ -1986,7 +2037,7 @@ void DwarfDebug::createDbgScope(MDNode *Scope, MDNode *InlinedAt) { /// extractScopeInformation - Scan machine instructions in this function /// and collect DbgScopes. Return true, if atleast one scope was found. -bool DwarfDebug::extractScopeInformation(MachineFunction *MF) { +bool DwarfDebug::extractScopeInformation() { // If scope information was extracted using .dbg intrinsics then there is not // any need to extract these information by scanning each instruction. if (!DbgScopeMap.empty()) @@ -2081,7 +2132,7 @@ bool DwarfDebug::extractScopeInformation(MachineFunction *MF) { /// beginFunction - Gather pre-function debug information. Assumes being /// emitted immediately after the function entry point. -void DwarfDebug::beginFunction(MachineFunction *MF) { +void DwarfDebug::beginFunction(const MachineFunction *MF) { this->MF = MF; if (!ShouldEmitDwarfDebug()) return; @@ -2089,14 +2140,11 @@ void DwarfDebug::beginFunction(MachineFunction *MF) { if (TimePassesIsEnabled) DebugTimer->startTimer(); - if (!extractScopeInformation(MF)) + if (!extractScopeInformation()) return; collectVariableInfo(); - // Begin accumulating function debug information. - MMI->BeginFunction(MF); - // Assumes in correct section after the entry point. EmitLabel("func_begin", ++SubprogramCount); @@ -2123,7 +2171,7 @@ void DwarfDebug::beginFunction(MachineFunction *MF) { /// endFunction - Gather and emit post-function debug information. /// -void DwarfDebug::endFunction(MachineFunction *MF) { +void DwarfDebug::endFunction(const MachineFunction *MF) { if (!ShouldEmitDwarfDebug()) return; if (TimePassesIsEnabled) @@ -2366,6 +2414,9 @@ void DwarfDebug::emitDIE(DIE *Die) { unsigned Form = AbbrevData[i].getForm(); assert(Form && "Too many attributes for DIE (check abbreviation)"); + if (Asm->VerboseAsm) + Asm->OutStreamer.AddComment(dwarf::AttributeString(Attr)); + switch (Attr) { case dwarf::DW_AT_sibling: Asm->EmitInt32(Die->getSiblingOffset()); @@ -2380,10 +2431,9 @@ void DwarfDebug::emitDIE(DIE *Die) { default: // Emit an attribute using the defined form. Values[i]->EmitValue(this, Form); + O << "\n"; // REMOVE This once all EmitValue impls emit their own newline. break; } - - EOL(dwarf::AttributeString(Attr)); } // Emit the DIE children if any. @@ -2767,7 +2817,8 @@ void DwarfDebug::emitDebugPubTypes() { EmitLabel("pubtypes_begin", ModuleCU->getID()); - Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF Version"); + if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DWARF Version"); + Asm->EmitInt16(dwarf::DWARF_VERSION); EmitSectionOffset("info_begin", "section_info", ModuleCU->getID(), 0, true, false); @@ -2783,10 +2834,11 @@ void DwarfDebug::emitDebugPubTypes() { const char *Name = GI->getKeyData(); DIE * Entity = GI->second; - Asm->EmitInt32(Entity->getOffset()); EOL("DIE offset"); + if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DIE offset"); + Asm->EmitInt32(Entity->getOffset()); if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("External Name"); - Asm->OutStreamer.EmitBytes(StringRef(Name, strlen(Name)), 0); + Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1), 0); } Asm->EmitInt32(0); EOL("End Mark"); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index e723621..55baa92 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -103,7 +103,7 @@ class DwarfDebug : public DwarfPrinter { /// SmallVector<std::pair<unsigned, unsigned>, 8> SourceIds; - /// Lines - List of of source line correspondence. + /// Lines - List of source line correspondence. std::vector<SrcLineInfo> Lines; /// DIEValues - A list of all the unique values in use. @@ -523,11 +523,11 @@ public: /// beginFunction - Gather pre-function debug information. Assumes being /// emitted immediately after the function entry point. - void beginFunction(MachineFunction *MF); + void beginFunction(const MachineFunction *MF); /// endFunction - Gather and emit post-function debug information. /// - void endFunction(MachineFunction *MF); + void endFunction(const MachineFunction *MF); /// recordSourceLine - Records location information and associates it with a /// label. Returns a unique label ID used to generate a label and provide @@ -550,7 +550,7 @@ public: /// extractScopeInformation - Scan machine instructions in this function /// and collect DbgScopes. Return true, if atleast one scope was found. - bool extractScopeInformation(MachineFunction *MF); + bool extractScopeInformation(); /// collectVariableInfo - Populate DbgScope entries with variables' info. void collectVariableInfo(); diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp index 2ae16c0..c6c59f5 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp @@ -34,6 +34,7 @@ #include "llvm/Support/Timer.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" using namespace llvm; DwarfException::DwarfException(raw_ostream &OS, AsmPrinter *A, @@ -49,26 +50,6 @@ DwarfException::~DwarfException() { delete ExceptionTimer; } -/// SizeOfEncodedValue - Return the size of the encoding in bytes. -unsigned DwarfException::SizeOfEncodedValue(unsigned Encoding) { - if (Encoding == dwarf::DW_EH_PE_omit) - return 0; - - switch (Encoding & 0x07) { - case dwarf::DW_EH_PE_absptr: - return TD->getPointerSize(); - case dwarf::DW_EH_PE_udata2: - return 2; - case dwarf::DW_EH_PE_udata4: - return 4; - case dwarf::DW_EH_PE_udata8: - return 8; - } - - assert(0 && "Invalid encoded value."); - return 0; -} - /// CreateLabelDiff - Emit a label and subtract it from the expression we /// already have. This is equivalent to emitting "foo - .", but we have to emit /// the label for "." directly. @@ -99,7 +80,7 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { TD->getPointerSize() : -TD->getPointerSize(); const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); - + // Begin eh frame section. Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection()); @@ -127,30 +108,16 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { // The personality presence indicates that language specific information will // show up in the eh frame. Find out how we are supposed to lower the // personality function reference: - const MCExpr *PersonalityRef = 0; - bool IsPersonalityIndirect = false, IsPersonalityPCRel = false; - if (PersonalityFn) { - // FIXME: HANDLE STATIC CODEGEN MODEL HERE. - - // In non-static mode, ask the object file how to represent this reference. - PersonalityRef = - TLOF.getSymbolForDwarfGlobalReference(PersonalityFn, Asm->Mang, - Asm->MMI, - IsPersonalityIndirect, - IsPersonalityPCRel); - } - - unsigned PerEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; - if (IsPersonalityIndirect) - PerEncoding |= dwarf::DW_EH_PE_indirect; - unsigned LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; - unsigned FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; + + unsigned LSDAEncoding = TLOF.getLSDAEncoding(); + unsigned FDEEncoding = TLOF.getFDEEncoding(); + unsigned PerEncoding = TLOF.getPersonalityEncoding(); char Augmentation[6] = { 0 }; unsigned AugmentationSize = 0; char *APtr = Augmentation + 1; - if (PersonalityRef) { + if (PersonalityFn) { // There is a personality function. *APtr++ = 'P'; AugmentationSize += 1 + SizeOfEncodedValue(PerEncoding); @@ -180,20 +147,19 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true)); EOL("CIE Return Address Column"); - EmitULEB128(AugmentationSize, "Augmentation Size"); - EmitEncodingByte(PerEncoding, "Personality"); - - // If there is a personality, we need to indicate the function's location. - if (PersonalityRef) { - if (!IsPersonalityPCRel) - PersonalityRef = CreateLabelDiff(PersonalityRef, "personalityref_addr", - Index); - - O << MAI->getData32bitsDirective() << *PersonalityRef; - EOL("Personality"); + if (Augmentation[0]) { + EmitULEB128(AugmentationSize, "Augmentation Size"); - EmitEncodingByte(LSDAEncoding, "LSDA"); - EmitEncodingByte(FDEEncoding, "FDE"); + // If there is a personality, we need to indicate the function's location. + if (PersonalityFn) { + EmitEncodingByte(PerEncoding, "Personality"); + EmitReference(PersonalityFn, PerEncoding); + EOL("Personality"); + } + if (UsesLSDA[Index]) + EmitEncodingByte(LSDAEncoding, "LSDA"); + if (FDEEncoding != dwarf::DW_EH_PE_absptr) + EmitEncodingByte(FDEEncoding, "FDE"); } // Indicate locations of general callee saved registers in frame. @@ -215,8 +181,12 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { "Should not emit 'available externally' functions at all"); const Function *TheFunc = EHFrameInfo.function; + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); - Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getEHFrameSection()); + unsigned LSDAEncoding = TLOF.getLSDAEncoding(); + unsigned FDEEncoding = TLOF.getFDEEncoding(); + + Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection()); // Externally visible entry into the functions eh frame info. If the // corresponding function is static, this should not be externally visible. @@ -254,7 +224,8 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { // EH frame header. EmitDifference("eh_frame_end", EHFrameInfo.Number, - "eh_frame_begin", EHFrameInfo.Number, true); + "eh_frame_begin", EHFrameInfo.Number, + true); EOL("Length of Frame Information Entry"); EmitLabel("eh_frame_begin", EHFrameInfo.Number); @@ -265,33 +236,23 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { EOL("FDE CIE offset"); - EmitReference("eh_func_begin", EHFrameInfo.Number, true, true); + EmitReference("eh_func_begin", EHFrameInfo.Number, FDEEncoding); EOL("FDE initial location"); EmitDifference("eh_func_end", EHFrameInfo.Number, - "eh_func_begin", EHFrameInfo.Number, true); + "eh_func_begin", EHFrameInfo.Number, + SizeOfEncodedValue(FDEEncoding) == 4); EOL("FDE address range"); // If there is a personality and landing pads then point to the language // specific data area in the exception table. if (MMI->getPersonalities()[0] != NULL) { + unsigned Size = SizeOfEncodedValue(LSDAEncoding); - if (Asm->TM.getLSDAEncoding() != DwarfLSDAEncoding::EightByte) { - EmitULEB128(4, "Augmentation size"); - - if (EHFrameInfo.hasLandingPads) - EmitReference("exception", EHFrameInfo.Number, true, true); - else - Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); - } else { - EmitULEB128(TD->getPointerSize(), "Augmentation size"); - - if (EHFrameInfo.hasLandingPads) { - EmitReference("exception", EHFrameInfo.Number, true, false); - } else { - Asm->OutStreamer.EmitIntValue(0, TD->getPointerSize(), - 0/*addrspace*/); - } - } + EmitULEB128(Size, "Augmentation size"); + if (EHFrameInfo.hasLandingPads) + EmitReference("exception", EHFrameInfo.Number, LSDAEncoding); + else + Asm->OutStreamer.EmitIntValue(0, Size/*size*/, 0/*addrspace*/); EOL("Language Specific Data Area"); } else { @@ -406,20 +367,22 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, if (NumShared < TypeIds.size()) { unsigned SizeAction = 0; - ActionEntry *PrevAction = 0; + unsigned PrevAction = (unsigned)-1; if (NumShared) { const unsigned SizePrevIds = PrevLPI->TypeIds.size(); assert(Actions.size()); - PrevAction = &Actions.back(); - SizeAction = MCAsmInfo::getSLEB128Size(PrevAction->NextAction) + - MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); + PrevAction = Actions.size() - 1; + SizeAction = + MCAsmInfo::getSLEB128Size(Actions[PrevAction].NextAction) + + MCAsmInfo::getSLEB128Size(Actions[PrevAction].ValueForTypeID); for (unsigned j = NumShared; j != SizePrevIds; ++j) { + assert(PrevAction != (unsigned)-1 && "PrevAction is invalid!"); SizeAction -= - MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); - SizeAction += -PrevAction->NextAction; - PrevAction = PrevAction->Previous; + MCAsmInfo::getSLEB128Size(Actions[PrevAction].ValueForTypeID); + SizeAction += -Actions[PrevAction].NextAction; + PrevAction = Actions[PrevAction].Previous; } } @@ -436,7 +399,7 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, ActionEntry Action = { ValueForTypeID, NextAction, PrevAction }; Actions.push_back(Action); - PrevAction = &Actions.back(); + PrevAction = Actions.size() - 1; } // Record the first action of the landing pad site. @@ -446,7 +409,7 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, // Information used when created the call-site table. The action record // field of the call site record is the offset of the first associated // action record, relative to the start of the actions table. This value is - // biased by 1 (1 in dicating the start of the actions table), and 0 + // biased by 1 (1 indicating the start of the actions table), and 0 // indicates that there are no actions. FirstActions.push_back(FirstAction); @@ -579,7 +542,16 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, } // Otherwise, create a new call-site. - CallSites.push_back(Site); + if (MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) + CallSites.push_back(Site); + else { + // SjLj EH must maintain the call sites in the order assigned + // to them by the SjLjPrepare pass. + unsigned SiteNo = MMI->getCallSiteBeginLabel(BeginLabel); + if (CallSites.size() < SiteNo) + CallSites.resize(SiteNo); + CallSites[SiteNo - 1] = Site; + } PreviousIsInvoke = true; } else { // Create a gap. @@ -638,8 +610,7 @@ void DwarfException::EmitExceptionTable() { // landing pad site. SmallVector<ActionEntry, 32> Actions; SmallVector<unsigned, 64> FirstActions; - unsigned SizeActions = ComputeActionsTable(LandingPads, Actions, - FirstActions); + unsigned SizeActions=ComputeActionsTable(LandingPads, Actions, FirstActions); // Invokes and nounwind calls have entries in PadMap (due to being bracketed // by try-range labels when lowered). Ordinary calls do not, so appropriate @@ -683,13 +654,13 @@ void DwarfException::EmitExceptionTable() { // Type infos. const MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection(); - unsigned TTypeFormat; + unsigned TTypeEncoding; unsigned TypeFormatSize; if (!HaveTTData) { // For SjLj exceptions, if there is no TypeInfo, then we just explicitly say // that we're omitting that bit. - TTypeFormat = dwarf::DW_EH_PE_omit; + TTypeEncoding = dwarf::DW_EH_PE_omit; TypeFormatSize = SizeOfEncodedValue(dwarf::DW_EH_PE_absptr); } else { // Okay, we have actual filters or typeinfos to emit. As such, we need to @@ -719,14 +690,8 @@ void DwarfException::EmitExceptionTable() { // somewhere. This predicate should be moved to a shared location that is // in target-independent code. // - if (LSDASection->getKind().isWriteable() || - Asm->TM.getRelocationModel() == Reloc::Static) - TTypeFormat = dwarf::DW_EH_PE_absptr; - else - TTypeFormat = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | - dwarf::DW_EH_PE_sdata4; - - TypeFormatSize = SizeOfEncodedValue(TTypeFormat); + TTypeEncoding = Asm->getObjFileLowering().getTTypeEncoding(); + TypeFormatSize = SizeOfEncodedValue(TTypeEncoding); } // Begin the exception table. @@ -752,7 +717,7 @@ void DwarfException::EmitExceptionTable() { // does, instead output it before the table. unsigned SizeTypes = TypeInfos.size() * TypeFormatSize; unsigned TyOffset = sizeof(int8_t) + // Call site format - MCAsmInfo::getULEB128Size(SizeSites) + // Call-site table length + MCAsmInfo::getULEB128Size(SizeSites) + // Call site table length SizeSites + SizeActions + SizeTypes; unsigned TotalSize = sizeof(int8_t) + // LPStart format sizeof(int8_t) + // TType format @@ -777,7 +742,7 @@ void DwarfException::EmitExceptionTable() { // Emit the header. EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); - EmitEncodingByte(TTypeFormat, "@TType"); + EmitEncodingByte(TTypeEncoding, "@TType"); if (HaveTTData) EmitULEB128(TyOffset, "@TType base offset"); @@ -826,7 +791,7 @@ void DwarfException::EmitExceptionTable() { // Emit the landing pad call site table. EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); - EmitULEB128(SizeSites, "Call site table size"); + EmitULEB128(SizeSites, "Call site table length"); for (SmallVectorImpl<CallSiteEntry>::const_iterator I = CallSites.begin(), E = CallSites.end(); I != E; ++I) { @@ -859,13 +824,14 @@ void DwarfException::EmitExceptionTable() { // Offset of the landing pad, counted in 16-byte bundles relative to the // @LPStart address. - if (!S.PadLabel) + if (!S.PadLabel) { + Asm->OutStreamer.AddComment("Landing pad"); Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); - else + } else { EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount, true, true); - - EOL("Landing pad"); + EOL("Landing pad"); + } // Offset of the first associated action record, relative to the start of // the action table. This value is biased by 1 (1 indicates the start of @@ -875,38 +841,43 @@ void DwarfException::EmitExceptionTable() { } // Emit the Action Table. + if (Actions.size() != 0) EOL("-- Action Record Table --"); for (SmallVectorImpl<ActionEntry>::const_iterator I = Actions.begin(), E = Actions.end(); I != E; ++I) { const ActionEntry &Action = *I; + EOL("Action Record:"); // Type Filter // // Used by the runtime to match the type of the thrown exception to the // type of the catch clauses or the types in the exception specification. - EmitSLEB128(Action.ValueForTypeID, "TypeInfo index"); + EmitSLEB128(Action.ValueForTypeID, " TypeInfo index"); // Action Record // // Self-relative signed displacement in bytes of the next action record, // or 0 if there is no next action record. - EmitSLEB128(Action.NextAction, "Next action"); + EmitSLEB128(Action.NextAction, " Next action"); } // Emit the Catch TypeInfos. + if (!TypeInfos.empty()) EOL("-- Catch TypeInfos --"); for (std::vector<GlobalVariable *>::const_reverse_iterator I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) { const GlobalVariable *GV = *I; - PrintRelDirective(); - if (GV) - O << *Asm->GetGlobalValueSymbol(GV); - else + if (GV) { + EmitReference(GV, TTypeEncoding); + EOL("TypeInfo"); + } else { + PrintRelDirective(TTypeEncoding); O << "0x0"; - - EOL("TypeInfo"); + EOL(""); + } } // Emit the Exception Specifications. + if (!FilterIds.empty()) EOL("-- Filter IDs --"); for (std::vector<unsigned>::const_iterator I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { unsigned TypeID = *I; @@ -943,7 +914,7 @@ void DwarfException::EndModule() { /// BeginFunction - Gather pre-function exception information. Assumes it's /// being emitted immediately after the function entry point. -void DwarfException::BeginFunction(MachineFunction *MF) { +void DwarfException::BeginFunction(const MachineFunction *MF) { if (!MMI || !MAI->doesSupportExceptionHandling()) return; if (TimePassesIsEnabled) diff --git a/lib/CodeGen/AsmPrinter/DwarfException.h b/lib/CodeGen/AsmPrinter/DwarfException.h index 3921e91..3db1a00 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.h +++ b/lib/CodeGen/AsmPrinter/DwarfException.h @@ -76,9 +76,6 @@ class DwarfException : public DwarfPrinter { /// ExceptionTimer - Timer for the Dwarf exception writer. Timer *ExceptionTimer; - /// SizeOfEncodedValue - Return the size of the encoding in bytes. - unsigned SizeOfEncodedValue(unsigned Encoding); - /// EmitCIE - Emit a Common Information Entry (CIE). This holds information /// that is shared among many Frame Description Entries. There is at least /// one CIE in every non-empty .debug_frame section. @@ -103,7 +100,7 @@ class DwarfException : public DwarfPrinter { /// exception. If it matches then the exception and type id are passed /// on to the landing pad. Otherwise the next action is looked up. This /// chain is terminated with a next action of zero. If no type id is - /// found the the frame is unwound and handling continues. + /// found the frame is unwound and handling continues. /// 3. Type id table contains references to all the C++ typeinfo for all /// catches in the function. This tables is reversed indexed base 1. @@ -135,7 +132,7 @@ class DwarfException : public DwarfPrinter { struct ActionEntry { int ValueForTypeID; // The value to write - may not be equal to the type id. int NextAction; - struct ActionEntry *Previous; + unsigned Previous; }; /// CallSiteEntry - Structure describing an entry in the call-site table. @@ -197,7 +194,7 @@ public: /// BeginFunction - Gather pre-function exception information. Assumes being /// emitted immediately after the function entry point. - void BeginFunction(MachineFunction *MF); + void BeginFunction(const MachineFunction *MF); /// EndFunction - Gather and emit post-function exception information. void EndFunction(); diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp index d204bba..1299d04 100644 --- a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // Emit general DWARF directives. -// +// //===----------------------------------------------------------------------===// #include "DwarfPrinter.h" @@ -18,13 +18,17 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/SmallString.h" using namespace llvm; DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T, @@ -33,6 +37,26 @@ DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T, RI(Asm->TM.getRegisterInfo()), M(NULL), MF(NULL), MMI(NULL), SubprogramCount(0), Flavor(flavor), SetCounter(1) {} +/// SizeOfEncodedValue - Return the size of the encoding in bytes. +unsigned DwarfPrinter::SizeOfEncodedValue(unsigned Encoding) const { + if (Encoding == dwarf::DW_EH_PE_omit) + return 0; + + switch (Encoding & 0x07) { + case dwarf::DW_EH_PE_absptr: + return TD->getPointerSize(); + case dwarf::DW_EH_PE_udata2: + return 2; + case dwarf::DW_EH_PE_udata4: + return 4; + case dwarf::DW_EH_PE_udata8: + return 8; + } + + assert(0 && "Invalid encoded value."); + return 0; +} + void DwarfPrinter::PrintRelDirective(bool Force32Bit, bool isInSection) const { if (isInSection && MAI->getDwarfSectionOffsetDirective()) O << MAI->getDwarfSectionOffsetDirective(); @@ -42,6 +66,14 @@ void DwarfPrinter::PrintRelDirective(bool Force32Bit, bool isInSection) const { O << MAI->getData64bitsDirective(); } +void DwarfPrinter::PrintRelDirective(unsigned Encoding) const { + unsigned Size = SizeOfEncodedValue(Encoding); + assert((Size == 4 || Size == 8) && "Do not support other types or rels!"); + + O << (Size == 4 ? + MAI->getData32bitsDirective() : MAI->getData64bitsDirective()); +} + /// EOL - Print a newline character to asm stream. If a comment is present /// then it will be printed first. Comments should not contain '\n'. void DwarfPrinter::EOL(const Twine &Comment) const { @@ -195,13 +227,38 @@ void DwarfPrinter::EmitReference(const MCSymbol *Sym, bool IsPCRelative, if (IsPCRelative) O << "-" << MAI->getPCSymbol(); } -/// EmitDifference - Emit the difference between two labels. Some assemblers do -/// not behave with absolute expressions with data directives, so there is an -/// option (needsSet) to use an intermediary set expression. +void DwarfPrinter::EmitReference(const char *Tag, unsigned Number, + unsigned Encoding) const { + SmallString<64> Name; + raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() + << Tag << Number; + + MCSymbol *Sym = Asm->OutContext.GetOrCreateSymbol(Name.str()); + EmitReference(Sym, Encoding); +} + +void DwarfPrinter::EmitReference(const MCSymbol *Sym, unsigned Encoding) const { + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + + PrintRelDirective(Encoding); + O << *TLOF.getSymbolForDwarfReference(Sym, Asm->MMI, Encoding);; +} + +void DwarfPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const { + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + + PrintRelDirective(Encoding); + O << *TLOF.getSymbolForDwarfGlobalReference(GV, Asm->Mang, + Asm->MMI, Encoding);; +} + +/// EmitDifference - Emit the difference between two labels. If this assembler +/// supports .set, we emit a .set of a temporary and then use it in the .word. void DwarfPrinter::EmitDifference(const char *TagHi, unsigned NumberHi, const char *TagLo, unsigned NumberLo, bool IsSmall) { - if (MAI->needsSet()) { + if (MAI->hasSetDirective()) { + // FIXME: switch to OutStreamer.EmitAssignment. O << "\t.set\t"; PrintLabelName("set", SetCounter, Flavor); O << ","; @@ -232,7 +289,8 @@ void DwarfPrinter::EmitSectionOffset(const char* Label, const char* Section, else printAbsolute = MAI->isAbsoluteDebugSectionOffsets(); - if (MAI->needsSet() && useSet) { + if (MAI->hasSetDirective() && useSet) { + // FIXME: switch to OutStreamer.EmitAssignment. O << "\t.set\t"; PrintLabelName("set", SetCounter, Flavor); O << ","; diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.h b/lib/CodeGen/AsmPrinter/DwarfPrinter.h index 86fe2ab..73de398 100644 --- a/lib/CodeGen/AsmPrinter/DwarfPrinter.h +++ b/lib/CodeGen/AsmPrinter/DwarfPrinter.h @@ -28,11 +28,14 @@ class Module; class MCAsmInfo; class TargetData; class TargetRegisterInfo; +class GlobalValue; class MCSymbol; class Twine; class DwarfPrinter { protected: + ~DwarfPrinter() {} + //===-------------------------------------------------------------==---===// // Core attributes used by the DWARF printer. // @@ -56,7 +59,7 @@ protected: Module *M; /// MF - Current machine function. - MachineFunction *MF; + const MachineFunction *MF; /// MMI - Collected machine module information. MachineModuleInfo *MMI; @@ -83,6 +86,10 @@ public: const MCAsmInfo *getMCAsmInfo() const { return MAI; } const TargetData *getTargetData() const { return TD; } + /// SizeOfEncodedValue - Return the size of the encoding in bytes. + unsigned SizeOfEncodedValue(unsigned Encoding) const; + + void PrintRelDirective(unsigned Encoding) const; void PrintRelDirective(bool Force32Bit = false, bool isInSection = false) const; @@ -138,9 +145,11 @@ public: void EmitReference(const MCSymbol *Sym, bool IsPCRelative = false, bool Force32Bit = false) const; - /// EmitDifference - Emit the difference between two labels. Some - /// assemblers do not behave with absolute expressions with data directives, - /// so there is an option (needsSet) to use an intermediary set expression. + void EmitReference(const char *Tag, unsigned Number, unsigned Encoding) const; + void EmitReference(const MCSymbol *Sym, unsigned Encoding) const; + void EmitReference(const GlobalValue *GV, unsigned Encoding) const; + + /// EmitDifference - Emit the difference between two labels. void EmitDifference(const DWLabel &LabelHi, const DWLabel &LabelLo, bool IsSmall = false) { EmitDifference(LabelHi.getTag(), LabelHi.getNumber(), diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp index dd8d88a..08e1bbc 100644 --- a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp @@ -57,14 +57,14 @@ void DwarfWriter::EndModule() { /// BeginFunction - Gather pre-function debug information. Assumes being /// emitted immediately after the function entry point. -void DwarfWriter::BeginFunction(MachineFunction *MF) { +void DwarfWriter::BeginFunction(const MachineFunction *MF) { DE->BeginFunction(MF); DD->beginFunction(MF); } /// EndFunction - Gather and emit post-function debug information. /// -void DwarfWriter::EndFunction(MachineFunction *MF) { +void DwarfWriter::EndFunction(const MachineFunction *MF) { DD->endFunction(MF); DE->EndFunction(); diff --git a/lib/CodeGen/AsmPrinter/Makefile b/lib/CodeGen/AsmPrinter/Makefile index b0071d0..60aa6cb 100644 --- a/lib/CodeGen/AsmPrinter/Makefile +++ b/lib/CodeGen/AsmPrinter/Makefile @@ -9,6 +9,5 @@ LEVEL = ../../.. LIBRARYNAME = LLVMAsmPrinter -CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/CodeGen/BranchFolding.cpp b/lib/CodeGen/BranchFolding.cpp index 92849d3..faf4d95 100644 --- a/lib/CodeGen/BranchFolding.cpp +++ b/lib/CodeGen/BranchFolding.cpp @@ -133,7 +133,7 @@ bool BranchFolder::OptimizeImpDefsBlock(MachineBasicBlock *MBB) { SmallSet<unsigned, 4> ImpDefRegs; MachineBasicBlock::iterator I = MBB->begin(); while (I != MBB->end()) { - if (I->getOpcode() != TargetInstrInfo::IMPLICIT_DEF) + if (!I->isImplicitDef()) break; unsigned Reg = I->getOperand(0).getReg(); ImpDefRegs.insert(Reg); @@ -206,53 +206,56 @@ bool BranchFolder::OptimizeFunction(MachineFunction &MF, // See if any jump tables have become mergable or dead as the code generator // did its thing. MachineJumpTableInfo *JTI = MF.getJumpTableInfo(); + if (JTI == 0) { + delete RS; + return MadeChange; + } + const std::vector<MachineJumpTableEntry> &JTs = JTI->getJumpTables(); - if (!JTs.empty()) { - // Figure out how these jump tables should be merged. - std::vector<unsigned> JTMapping; - JTMapping.reserve(JTs.size()); - - // We always keep the 0th jump table. - JTMapping.push_back(0); - - // Scan the jump tables, seeing if there are any duplicates. Note that this - // is N^2, which should be fixed someday. - for (unsigned i = 1, e = JTs.size(); i != e; ++i) { - if (JTs[i].MBBs.empty()) - JTMapping.push_back(i); - else - JTMapping.push_back(JTI->getJumpTableIndex(JTs[i].MBBs)); - } - - // If a jump table was merge with another one, walk the function rewriting - // references to jump tables to reference the new JT ID's. Keep track of - // whether we see a jump table idx, if not, we can delete the JT. - BitVector JTIsLive(JTs.size()); - for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); - BB != E; ++BB) { - for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end(); - I != E; ++I) - for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op) { - MachineOperand &Op = I->getOperand(op); - if (!Op.isJTI()) continue; - unsigned NewIdx = JTMapping[Op.getIndex()]; - Op.setIndex(NewIdx); - - // Remember that this JT is live. - JTIsLive.set(NewIdx); - } - } + // Figure out how these jump tables should be merged. + std::vector<unsigned> JTMapping; + JTMapping.reserve(JTs.size()); + + // We always keep the 0th jump table. + JTMapping.push_back(0); + + // Scan the jump tables, seeing if there are any duplicates. Note that this + // is N^2, which should be fixed someday. + for (unsigned i = 1, e = JTs.size(); i != e; ++i) { + if (JTs[i].MBBs.empty()) + JTMapping.push_back(i); + else + JTMapping.push_back(JTI->getJumpTableIndex(JTs[i].MBBs)); + } - // Finally, remove dead jump tables. This happens either because the - // indirect jump was unreachable (and thus deleted) or because the jump - // table was merged with some other one. - for (unsigned i = 0, e = JTIsLive.size(); i != e; ++i) - if (!JTIsLive.test(i)) { - JTI->RemoveJumpTable(i); - MadeChange = true; + // If a jump table was merge with another one, walk the function rewriting + // references to jump tables to reference the new JT ID's. Keep track of + // whether we see a jump table idx, if not, we can delete the JT. + BitVector JTIsLive(JTs.size()); + for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); + BB != E; ++BB) { + for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end(); + I != E; ++I) + for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op) { + MachineOperand &Op = I->getOperand(op); + if (!Op.isJTI()) continue; + unsigned NewIdx = JTMapping[Op.getIndex()]; + Op.setIndex(NewIdx); + + // Remember that this JT is live. + JTIsLive.set(NewIdx); } } + // Finally, remove dead jump tables. This happens either because the + // indirect jump was unreachable (and thus deleted) or because the jump + // table was merged with some other one. + for (unsigned i = 0, e = JTIsLive.size(); i != e; ++i) + if (!JTIsLive.test(i)) { + JTI->RemoveJumpTable(i); + MadeChange = true; + } + delete RS; return MadeChange; } @@ -337,7 +340,7 @@ static unsigned ComputeCommonTailLength(MachineBasicBlock *MBB1, // relative order. This is untenable because normal compiler // optimizations (like this one) may reorder and/or merge these // directives. - I1->getOpcode() == TargetInstrInfo::INLINEASM) { + I1->isInlineAsm()) { ++I1; ++I2; break; } @@ -957,7 +960,8 @@ ReoptimizeBlock: } // If MBB was the target of a jump table, update jump tables to go to the // fallthrough instead. - MF.getJumpTableInfo()->ReplaceMBBInJumpTables(MBB, FallThrough); + if (MachineJumpTableInfo *MJTI = MF.getJumpTableInfo()) + MJTI->ReplaceMBBInJumpTables(MBB, FallThrough); MadeChange = true; } return MadeChange; @@ -1191,7 +1195,8 @@ ReoptimizeBlock: } // Change any jumptables to go to the new MBB. - MF.getJumpTableInfo()->ReplaceMBBInJumpTables(MBB, CurTBB); + if (MachineJumpTableInfo *MJTI = MF.getJumpTableInfo()) + MJTI->ReplaceMBBInJumpTables(MBB, CurTBB); if (DidChange) { ++NumBranchOpts; MadeChange = true; diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt index 17072d3..62cf339 100644 --- a/lib/CodeGen/CMakeLists.txt +++ b/lib/CodeGen/CMakeLists.txt @@ -21,7 +21,6 @@ add_llvm_library(LLVMCodeGen LiveStackAnalysis.cpp LiveVariables.cpp LowerSubregs.cpp - MachOWriter.cpp MachineBasicBlock.cpp MachineDominators.cpp MachineFunction.cpp @@ -40,6 +39,7 @@ add_llvm_library(LLVMCodeGen ObjectCodeEmitter.cpp OcamlGC.cpp OptimizeExts.cpp + OptimizePHIs.cpp PHIElimination.cpp Passes.cpp PostRASchedulerList.cpp @@ -67,6 +67,7 @@ add_llvm_library(LLVMCodeGen StrongPHIElimination.cpp TailDuplication.cpp TargetInstrInfoImpl.cpp + TargetLoweringObjectFileImpl.cpp TwoAddressInstructionPass.cpp UnreachableBlockElim.cpp VirtRegMap.cpp diff --git a/lib/CodeGen/CalcSpillWeights.cpp b/lib/CodeGen/CalcSpillWeights.cpp index b8ef219..2bedd04 100644 --- a/lib/CodeGen/CalcSpillWeights.cpp +++ b/lib/CodeGen/CalcSpillWeights.cpp @@ -20,8 +20,8 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" - using namespace llvm; char CalculateSpillWeights::ID = 0; @@ -58,10 +58,7 @@ bool CalculateSpillWeights::runOnMachineFunction(MachineFunction &fn) { for (MachineBasicBlock::const_iterator mii = mbb->begin(), mie = mbb->end(); mii != mie; ++mii) { const MachineInstr *mi = mii; - if (tii->isIdentityCopy(*mi)) - continue; - - if (mi->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) + if (tii->isIdentityCopy(*mi) || mi->isImplicitDef() || mi->isDebugValue()) continue; for (unsigned i = 0, e = mi->getNumOperands(); i != e; ++i) { diff --git a/lib/CodeGen/CodePlacementOpt.cpp b/lib/CodeGen/CodePlacementOpt.cpp index 126700b..a13a310 100644 --- a/lib/CodeGen/CodePlacementOpt.cpp +++ b/lib/CodeGen/CodePlacementOpt.cpp @@ -106,7 +106,7 @@ bool CodePlacementOpt::HasAnalyzableTerminator(MachineBasicBlock *MBB) { // At the time of this writing, there are blocks which AnalyzeBranch // thinks end in single uncoditional branches, yet which have two CFG // successors. Code in this file is not prepared to reason about such things. - if (!MBB->empty() && MBB->back().getOpcode() == TargetInstrInfo::EH_LABEL) + if (!MBB->empty() && MBB->back().isEHLabel()) return false; // Aggressively handle return blocks and similar constructs. @@ -115,7 +115,7 @@ bool CodePlacementOpt::HasAnalyzableTerminator(MachineBasicBlock *MBB) { // Ask the target's AnalyzeBranch if it can handle this block. MachineBasicBlock *TBB = 0, *FBB = 0; SmallVector<MachineOperand, 4> Cond; - // Make the the terminator is understood. + // Make sure the terminator is understood. if (TII->AnalyzeBranch(*MBB, TBB, FBB, Cond)) return false; // Make sure we have the option of reversing the condition. diff --git a/lib/CodeGen/DeadMachineInstructionElim.cpp b/lib/CodeGen/DeadMachineInstructionElim.cpp index 0982eab..a215a19 100644 --- a/lib/CodeGen/DeadMachineInstructionElim.cpp +++ b/lib/CodeGen/DeadMachineInstructionElim.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "codegen-dce" #include "llvm/CodeGen/Passes.h" #include "llvm/Pass.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -19,8 +20,11 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/Statistic.h" using namespace llvm; +STATISTIC(NumDeletes, "Number of dead instructions deleted"); + namespace { class DeadMachineInstructionElim : public MachineFunctionPass { virtual bool runOnMachineFunction(MachineFunction &MF); @@ -51,7 +55,7 @@ FunctionPass *llvm::createDeadMachineInstructionElimPass() { bool DeadMachineInstructionElim::isDead(const MachineInstr *MI) const { // Don't delete instructions with side effects. bool SawStore = false; - if (!MI->isSafeToMove(TII, SawStore, 0)) + if (!MI->isSafeToMove(TII, SawStore, 0) && !MI->isPHI()) return false; // Examine each operand. @@ -60,8 +64,8 @@ bool DeadMachineInstructionElim::isDead(const MachineInstr *MI) const { if (MO.isReg() && MO.isDef()) { unsigned Reg = MO.getReg(); if (TargetRegisterInfo::isPhysicalRegister(Reg) ? - LivePhysRegs[Reg] : !MRI->use_empty(Reg)) { - // This def has a use. Don't delete the instruction! + LivePhysRegs[Reg] : !MRI->use_nodbg_empty(Reg)) { + // This def has a non-debug use. Don't delete the instruction! return false; } } @@ -110,8 +114,31 @@ bool DeadMachineInstructionElim::runOnMachineFunction(MachineFunction &MF) { // If the instruction is dead, delete it! if (isDead(MI)) { DEBUG(dbgs() << "DeadMachineInstructionElim: DELETING: " << *MI); + // It is possible that some DBG_VALUE instructions refer to this + // instruction. Examine each def operand for such references; + // if found, mark the DBG_VALUE as undef (but don't delete it). + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + unsigned Reg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + MachineRegisterInfo::use_iterator nextI; + for (MachineRegisterInfo::use_iterator I = MRI->use_begin(Reg), + E = MRI->use_end(); I!=E; I=nextI) { + nextI = llvm::next(I); // I is invalidated by the setReg + MachineOperand& Use = I.getOperand(); + MachineInstr *UseMI = Use.getParent(); + if (UseMI==MI) + continue; + assert(Use.isDebug()); + UseMI->getOperand(0).setReg(0U); + } + } AnyChanges = true; MI->eraseFromParent(); + ++NumDeletes; MIE = MBB->rend(); // MII is now pointing to the next instruction to process, // so don't increment it. diff --git a/lib/CodeGen/ELFCodeEmitter.cpp b/lib/CodeGen/ELFCodeEmitter.cpp index 11a85a0..8416d3b 100644 --- a/lib/CodeGen/ELFCodeEmitter.cpp +++ b/lib/CodeGen/ELFCodeEmitter.cpp @@ -62,7 +62,8 @@ void ELFCodeEmitter::startFunction(MachineFunction &MF) { // They need to be emitted before the function because in some targets // the later may reference JT or CP entry address. emitConstantPool(MF.getConstantPool()); - emitJumpTables(MF.getJumpTableInfo()); + if (MF.getJumpTableInfo()) + emitJumpTables(MF.getJumpTableInfo()); } /// finishFunction - This callback is invoked after the function is completely @@ -84,7 +85,7 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) { // Patch up Jump Table Section relocations to use the real MBBs offsets // now that the MBB label offsets inside the function are known. - if (!MF.getJumpTableInfo()->isEmpty()) { + if (MF.getJumpTableInfo()) { ELFSection &JTSection = EW.getJumpTableSection(); for (std::vector<MachineRelocation>::iterator MRI = JTRelocations.begin(), MRE = JTRelocations.end(); MRI != MRE; ++MRI) { @@ -172,7 +173,7 @@ void ELFCodeEmitter::emitJumpTables(MachineJumpTableInfo *MJTI) { "PIC codegen not yet handled for elf jump tables!"); const TargetELFWriterInfo *TEW = TM.getELFWriterInfo(); - unsigned EntrySize = MJTI->getEntrySize(); + unsigned EntrySize = 4; //MJTI->getEntrySize(); // Get the ELF Section to emit the jump table ELFSection &JTSection = EW.getJumpTableSection(); diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp index de45e09..0979c04 100644 --- a/lib/CodeGen/ELFWriter.cpp +++ b/lib/CodeGen/ELFWriter.cpp @@ -37,7 +37,6 @@ #include "llvm/PassManager.h" #include "llvm/DerivedTypes.h" #include "llvm/CodeGen/BinaryObject.h" -#include "llvm/CodeGen/FileWriters.h" #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/CodeGen/ObjectCodeEmitter.h" #include "llvm/CodeGen/MachineCodeEmitter.h" @@ -59,15 +58,6 @@ using namespace llvm; char ELFWriter::ID = 0; -/// AddELFWriter - Add the ELF writer to the function pass manager -ObjectCodeEmitter *llvm::AddELFWriter(PassManagerBase &PM, - raw_ostream &O, - TargetMachine &TM) { - ELFWriter *EW = new ELFWriter(O, TM); - PM.add(EW); - return EW->getObjectCodeEmitter(); -} - //===----------------------------------------------------------------------===// // ELFWriter Implementation //===----------------------------------------------------------------------===// diff --git a/lib/CodeGen/ExactHazardRecognizer.cpp b/lib/CodeGen/ExactHazardRecognizer.cpp index 266c74c..61959bb 100644 --- a/lib/CodeGen/ExactHazardRecognizer.cpp +++ b/lib/CodeGen/ExactHazardRecognizer.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This implements a a hazard recognizer using the instructions itineraries +// This implements a hazard recognizer using the instructions itineraries // defined for the current target. // //===----------------------------------------------------------------------===// diff --git a/lib/CodeGen/GCStrategy.cpp b/lib/CodeGen/GCStrategy.cpp index 79b2986..b5006fd 100644 --- a/lib/CodeGen/GCStrategy.cpp +++ b/lib/CodeGen/GCStrategy.cpp @@ -335,7 +335,7 @@ unsigned MachineCodeAnalysis::InsertLabel(MachineBasicBlock &MBB, unsigned Label = MMI->NextLabelID(); BuildMI(MBB, MI, DL, - TII->get(TargetInstrInfo::GC_LABEL)).addImm(Label); + TII->get(TargetOpcode::GC_LABEL)).addImm(Label); return Label; } diff --git a/lib/CodeGen/IntrinsicLowering.cpp b/lib/CodeGen/IntrinsicLowering.cpp index 9997a48..87ab7ef 100644 --- a/lib/CodeGen/IntrinsicLowering.cpp +++ b/lib/CodeGen/IntrinsicLowering.cpp @@ -155,7 +155,7 @@ void IntrinsicLowering::AddPrototypes(Module &M) { /// LowerBSWAP - Emit the code to lower bswap of V before the specified /// instruction IP. static Value *LowerBSWAP(LLVMContext &Context, Value *V, Instruction *IP) { - assert(V->getType()->isInteger() && "Can't bswap a non-integer type!"); + assert(V->getType()->isIntegerTy() && "Can't bswap a non-integer type!"); unsigned BitSize = V->getType()->getPrimitiveSizeInBits(); @@ -251,7 +251,7 @@ static Value *LowerBSWAP(LLVMContext &Context, Value *V, Instruction *IP) { /// LowerCTPOP - Emit the code to lower ctpop of V before the specified /// instruction IP. static Value *LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP) { - assert(V->getType()->isInteger() && "Can't ctpop a non-integer type!"); + assert(V->getType()->isIntegerTy() && "Can't ctpop a non-integer type!"); static const uint64_t MaskValues[6] = { 0x5555555555555555ULL, 0x3333333333333333ULL, diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index 837e184..278de02 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -14,16 +14,20 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/PassManager.h" #include "llvm/Pass.h" +#include "llvm/Analysis/Verifier.h" #include "llvm/Assembly/PrintModulePass.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/Passes.h" -#include "llvm/CodeGen/FileWriters.h" #include "llvm/CodeGen/GCStrategy.h" #include "llvm/CodeGen/MachineFunctionAnalysis.h" #include "llvm/Target/TargetOptions.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FormattedStream.h" @@ -57,14 +61,24 @@ static cl::opt<bool> PrintLSR("print-lsr-output", cl::Hidden, cl::desc("Print LLVM IR produced by the loop-reduce pass")); static cl::opt<bool> PrintISelInput("print-isel-input", cl::Hidden, cl::desc("Print LLVM IR input to isel pass")); -static cl::opt<bool> PrintEmittedAsm("print-emitted-asm", cl::Hidden, - cl::desc("Dump emitter generated instructions as assembly")); static cl::opt<bool> PrintGCInfo("print-gc", cl::Hidden, cl::desc("Dump garbage collector data")); static cl::opt<bool> VerifyMachineCode("verify-machineinstrs", cl::Hidden, cl::desc("Verify generated machine code"), cl::init(getenv("LLVM_VERIFY_MACHINEINSTRS")!=NULL)); +static cl::opt<cl::boolOrDefault> +AsmVerbose("asm-verbose", cl::desc("Add comments to directives."), + cl::init(cl::BOU_UNSET)); + +static bool getVerboseAsm() { + switch (AsmVerbose) { + default: + case cl::BOU_UNSET: return TargetMachine::getAsmVerbosityDefault(); + case cl::BOU_TRUE: return true; + case cl::BOU_FALSE: return false; + } +} // Enable or disable FastISel. Both options are needed, because // FastISel is enabled by default with -fast, and we wish to be @@ -98,139 +112,81 @@ LLVMTargetMachine::setCodeModelForStatic() { setCodeModel(CodeModel::Small); } -FileModel::Model -LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, - formatted_raw_ostream &Out, - CodeGenFileType FileType, - CodeGenOpt::Level OptLevel) { +bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, + formatted_raw_ostream &Out, + CodeGenFileType FileType, + CodeGenOpt::Level OptLevel) { // Add common CodeGen passes. if (addCommonCodeGenPasses(PM, OptLevel)) - return FileModel::Error; + return true; + OwningPtr<MCContext> Context(new MCContext()); + OwningPtr<MCStreamer> AsmStreamer; + + formatted_raw_ostream *LegacyOutput; switch (FileType) { - default: + default: return true; + case CGFT_AssemblyFile: { + const MCAsmInfo &MAI = *getMCAsmInfo(); + MCInstPrinter *InstPrinter = + getTarget().createMCInstPrinter(MAI.getAssemblerDialect(), MAI, Out); + AsmStreamer.reset(createAsmStreamer(*Context, Out, MAI, + getTargetData()->isLittleEndian(), + getVerboseAsm(), InstPrinter, + /*codeemitter*/0)); + // Set the AsmPrinter's "O" to the output file. + LegacyOutput = &Out; break; - case TargetMachine::AssemblyFile: - if (addAssemblyEmitter(PM, OptLevel, getAsmVerbosityDefault(), Out)) - return FileModel::Error; - return FileModel::AsmFile; - case TargetMachine::ObjectFile: - if (!addObjectFileEmitter(PM, OptLevel, Out)) - return FileModel::MachOFile; - else if (getELFWriterInfo()) - return FileModel::ElfFile; } - return FileModel::Error; -} - -bool LLVMTargetMachine::addAssemblyEmitter(PassManagerBase &PM, - CodeGenOpt::Level OptLevel, - bool Verbose, - formatted_raw_ostream &Out) { + case CGFT_ObjectFile: { + // Create the code emitter for the target if it exists. If not, .o file + // emission fails. + MCCodeEmitter *MCE = getTarget().createCodeEmitter(*this, *Context); + if (MCE == 0) + return true; + + AsmStreamer.reset(createMachOStreamer(*Context, Out, MCE)); + + // Any output to the asmprinter's "O" stream is bad and needs to be fixed, + // force it to come out stderr. + // FIXME: this is horrible and leaks, eventually remove the raw_ostream from + // asmprinter. + LegacyOutput = new formatted_raw_ostream(errs()); + break; + } + case CGFT_Null: + // The Null output is intended for use for performance analysis and testing, + // not real users. + AsmStreamer.reset(createNullStreamer(*Context)); + // Any output to the asmprinter's "O" stream is bad and needs to be fixed, + // force it to come out stderr. + // FIXME: this is horrible and leaks, eventually remove the raw_ostream from + // asmprinter. + LegacyOutput = new formatted_raw_ostream(errs()); + break; + } + + // Create the AsmPrinter, which takes ownership of Context and AsmStreamer + // if successful. FunctionPass *Printer = - getTarget().createAsmPrinter(Out, *this, getMCAsmInfo(), Verbose); - if (!Printer) - return true; - - PM.add(Printer); - return false; -} - -bool LLVMTargetMachine::addObjectFileEmitter(PassManagerBase &PM, - CodeGenOpt::Level OptLevel, - formatted_raw_ostream &Out) { - MCCodeEmitter *Emitter = getTarget().createCodeEmitter(*this); - if (!Emitter) + getTarget().createAsmPrinter(*LegacyOutput, *this, *Context, *AsmStreamer, + getMCAsmInfo()); + if (Printer == 0) return true; - PM.add(createMachOWriter(Out, *this, getMCAsmInfo(), Emitter)); - return false; -} - -/// addPassesToEmitFileFinish - If the passes to emit the specified file had to -/// be split up (e.g., to add an object writer pass), this method can be used to -/// finish up adding passes to emit the file, if necessary. -bool LLVMTargetMachine::addPassesToEmitFileFinish(PassManagerBase &PM, - MachineCodeEmitter *MCE, - CodeGenOpt::Level OptLevel) { - // Make sure the code model is set. - setCodeModelForStatic(); + // If successful, createAsmPrinter took ownership of AsmStreamer and Context. + Context.take(); AsmStreamer.take(); - if (MCE) - addSimpleCodeEmitter(PM, OptLevel, *MCE); - if (PrintEmittedAsm) - addAssemblyEmitter(PM, OptLevel, true, ferrs()); - - PM.add(createGCInfoDeleter()); - - return false; // success! -} - -/// addPassesToEmitFileFinish - If the passes to emit the specified file had to -/// be split up (e.g., to add an object writer pass), this method can be used to -/// finish up adding passes to emit the file, if necessary. -bool LLVMTargetMachine::addPassesToEmitFileFinish(PassManagerBase &PM, - JITCodeEmitter *JCE, - CodeGenOpt::Level OptLevel) { - // Make sure the code model is set. - setCodeModelForJIT(); + PM.add(Printer); - if (JCE) - addSimpleCodeEmitter(PM, OptLevel, *JCE); - if (PrintEmittedAsm) - addAssemblyEmitter(PM, OptLevel, true, ferrs()); - - PM.add(createGCInfoDeleter()); - - return false; // success! -} - -/// addPassesToEmitFileFinish - If the passes to emit the specified file had to -/// be split up (e.g., to add an object writer pass), this method can be used to -/// finish up adding passes to emit the file, if necessary. -bool LLVMTargetMachine::addPassesToEmitFileFinish(PassManagerBase &PM, - ObjectCodeEmitter *OCE, - CodeGenOpt::Level OptLevel) { // Make sure the code model is set. setCodeModelForStatic(); - - if (OCE) - addSimpleCodeEmitter(PM, OptLevel, *OCE); - if (PrintEmittedAsm) - addAssemblyEmitter(PM, OptLevel, true, ferrs()); - - PM.add(createGCInfoDeleter()); - - return false; // success! -} - -/// addPassesToEmitMachineCode - Add passes to the specified pass manager to -/// get machine code emitted. This uses a MachineCodeEmitter object to handle -/// actually outputting the machine code and resolving things like the address -/// of functions. This method should returns true if machine code emission is -/// not supported. -/// -bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM, - MachineCodeEmitter &MCE, - CodeGenOpt::Level OptLevel) { - // Make sure the code model is set. - setCodeModelForJIT(); - - // Add common CodeGen passes. - if (addCommonCodeGenPasses(PM, OptLevel)) - return true; - - addCodeEmitter(PM, OptLevel, MCE); - if (PrintEmittedAsm) - addAssemblyEmitter(PM, OptLevel, true, ferrs()); - PM.add(createGCInfoDeleter()); - - return false; // success! + return false; } /// addPassesToEmitMachineCode - Add passes to the specified pass manager to -/// get machine code emitted. This uses a MachineCodeEmitter object to handle +/// get machine code emitted. This uses a JITCodeEmitter object to handle /// actually outputting the machine code and resolving things like the address /// of functions. This method should returns true if machine code emission is /// not supported. @@ -246,9 +202,6 @@ bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM, return true; addCodeEmitter(PM, OptLevel, JCE); - if (PrintEmittedAsm) - addAssemblyEmitter(PM, OptLevel, true, ferrs()); - PM.add(createGCInfoDeleter()); return false; // success! @@ -282,6 +235,9 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, PM.add(createLoopStrengthReducePass(getTargetLowering())); if (PrintLSR) PM.add(createPrintFunctionPass("\n\n*** Code after LSR ***\n", &dbgs())); +#ifndef NDEBUG + PM.add(createVerifierPass()); +#endif } // Turn exception handling constructs into something the code generators can @@ -339,6 +295,16 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, printAndVerify(PM, "After Instruction Selection", /* allowDoubleDefs= */ true); + // Optimize PHIs before DCE: removing dead PHI cycles may make more + // instructions dead. + if (OptLevel != CodeGenOpt::None) + PM.add(createOptimizePHIsPass()); + + // Delete dead machine instructions regardless of optimization level. + PM.add(createDeadMachineInstructionElimPass()); + printAndVerify(PM, "After codegen DCE pass", + /* allowDoubleDefs= */ true); + if (OptLevel != CodeGenOpt::None) { PM.add(createOptimizeExtsPass()); if (!DisableMachineLICM) diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index 8746bf9..f6bf433 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -140,7 +140,7 @@ void LiveIntervals::printInstrs(raw_ostream &OS) const { << ":\t\t# derived from " << mbbi->getName() << "\n"; for (MachineBasicBlock::iterator mii = mbbi->begin(), mie = mbbi->end(); mii != mie; ++mii) { - if (mii->getOpcode()==TargetInstrInfo::DEBUG_VALUE) + if (mii->isDebugValue()) OS << SlotIndex::getEmptyKey() << '\t' << *mii; else OS << getInstructionIndex(mii) << '\t' << *mii; @@ -288,9 +288,7 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb, VNInfo *ValNo; MachineInstr *CopyMI = NULL; unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; - if (mi->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG || - mi->getOpcode() == TargetInstrInfo::INSERT_SUBREG || - mi->getOpcode() == TargetInstrInfo::SUBREG_TO_REG || + if (mi->isExtractSubreg() || mi->isInsertSubreg() || mi->isSubregToReg() || tii_->isMoveInstr(*mi, SrcReg, DstReg, SrcSubReg, DstSubReg)) CopyMI = mi; // Earlyclobbers move back one. @@ -460,9 +458,7 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb, VNInfo *ValNo; MachineInstr *CopyMI = NULL; unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; - if (mi->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG || - mi->getOpcode() == TargetInstrInfo::INSERT_SUBREG || - mi->getOpcode() == TargetInstrInfo::SUBREG_TO_REG || + if (mi->isExtractSubreg() || mi->isInsertSubreg() || mi->isSubregToReg()|| tii_->isMoveInstr(*mi, SrcReg, DstReg, SrcSubReg, DstSubReg)) CopyMI = mi; ValNo = interval.getNextValue(defIndex, CopyMI, true, VNInfoAllocator); @@ -516,6 +512,8 @@ void LiveIntervals::handlePhysicalRegisterDef(MachineBasicBlock *MBB, baseIndex = baseIndex.getNextIndex(); while (++mi != MBB->end()) { + if (mi->isDebugValue()) + continue; if (getInstructionFromIndex(baseIndex) == 0) baseIndex = indexes_->getNextNonNullIndex(baseIndex); @@ -531,8 +529,8 @@ void LiveIntervals::handlePhysicalRegisterDef(MachineBasicBlock *MBB, end = baseIndex.getDefIndex(); } else { // Another instruction redefines the register before it is ever read. - // Then the register is essentially dead at the instruction that defines - // it. Hence its interval is: + // Then the register is essentially dead at the instruction that + // defines it. Hence its interval is: // [defSlot(def), defSlot(def)+1) DEBUG(dbgs() << " dead"); end = start.getStoreIndex(); @@ -577,9 +575,7 @@ void LiveIntervals::handleRegisterDef(MachineBasicBlock *MBB, else if (allocatableRegs_[MO.getReg()]) { MachineInstr *CopyMI = NULL; unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; - if (MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG || - MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG || - MI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG || + if (MI->isExtractSubreg() || MI->isInsertSubreg() || MI->isSubregToReg() || tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg)) CopyMI = MI; handlePhysicalRegisterDef(MBB, MI, MIIdx, MO, @@ -612,8 +608,16 @@ void LiveIntervals::handleLiveInRegister(MachineBasicBlock *MBB, SlotIndex end = baseIndex; bool SeenDefUse = false; - - while (mi != MBB->end()) { + + MachineBasicBlock::iterator E = MBB->end(); + while (mi != E) { + if (mi->isDebugValue()) { + ++mi; + if (mi != E && !mi->isDebugValue()) { + baseIndex = indexes_->getNextNonNullIndex(baseIndex); + } + continue; + } if (mi->killsRegister(interval.reg, tri_)) { DEBUG(dbgs() << " killed"); end = baseIndex.getDefIndex(); @@ -631,7 +635,7 @@ void LiveIntervals::handleLiveInRegister(MachineBasicBlock *MBB, } ++mi; - if (mi != MBB->end()) { + if (mi != E && !mi->isDebugValue()) { baseIndex = indexes_->getNextNonNullIndex(baseIndex); } } @@ -671,6 +675,9 @@ void LiveIntervals::computeIntervals() { for (MachineFunction::iterator MBBI = mf_->begin(), E = mf_->end(); MBBI != E; ++MBBI) { MachineBasicBlock *MBB = MBBI; + if (MBB->empty()) + continue; + // Track the index of the current machine instr. SlotIndex MIIndex = getMBBStartIdx(MBB); DEBUG(dbgs() << MBB->getName() << ":\n"); @@ -693,7 +700,7 @@ void LiveIntervals::computeIntervals() { for (MachineBasicBlock::iterator MI = MBB->begin(), miEnd = MBB->end(); MI != miEnd; ++MI) { DEBUG(dbgs() << MIIndex << "\t" << *MI); - if (MI->getOpcode()==TargetInstrInfo::DEBUG_VALUE) + if (MI->isDebugValue()) continue; // Handle defs. @@ -742,7 +749,7 @@ unsigned LiveIntervals::getVNInfoSourceReg(const VNInfo *VNI) const { if (!VNI->getCopy()) return 0; - if (VNI->getCopy()->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) { + if (VNI->getCopy()->isExtractSubreg()) { // If it's extracting out of a physical register, return the sub-register. unsigned Reg = VNI->getCopy()->getOperand(1).getReg(); if (TargetRegisterInfo::isPhysicalRegister(Reg)) { @@ -756,8 +763,8 @@ unsigned LiveIntervals::getVNInfoSourceReg(const VNInfo *VNI) const { Reg = tri_->getSubReg(Reg, VNI->getCopy()->getOperand(2).getImm()); } return Reg; - } else if (VNI->getCopy()->getOpcode() == TargetInstrInfo::INSERT_SUBREG || - VNI->getCopy()->getOpcode() == TargetInstrInfo::SUBREG_TO_REG) + } else if (VNI->getCopy()->isInsertSubreg() || + VNI->getCopy()->isSubregToReg()) return VNI->getCopy()->getOperand(2).getReg(); unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; @@ -919,7 +926,7 @@ bool LiveIntervals::tryFoldMemoryOperand(MachineInstr* &MI, SmallVector<unsigned, 2> &Ops, bool isSS, int Slot, unsigned Reg) { // If it is an implicit def instruction, just delete it. - if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) { + if (MI->isImplicitDef()) { RemoveMachineInstrFromMaps(MI); vrm.RemoveMachineInstrFromMaps(MI); MI->eraseFromParent(); @@ -1059,7 +1066,7 @@ rewriteInstructionForSpills(const LiveInterval &li, const VNInfo *VNI, // If this is the rematerializable definition MI itself and // all of its uses are rematerialized, simply delete it. if (MI == ReMatOrigDefMI && CanDelete) { - DEBUG(dbgs() << "\t\t\t\tErasing re-materlizable def: " + DEBUG(dbgs() << "\t\t\t\tErasing re-materializable def: " << MI << '\n'); RemoveMachineInstrFromMaps(MI); vrm.RemoveMachineInstrFromMaps(MI); @@ -1302,6 +1309,12 @@ rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit, MachineInstr *MI = &*ri; MachineOperand &O = ri.getOperand(); ++ri; + if (MI->isDebugValue()) { + // Remove debug info for now. + O.setReg(0U); + DEBUG(dbgs() << "Removing debug info due to spill:" << "\t" << *MI); + continue; + } assert(!O.isImplicit() && "Spilling register that's used as implicit use?"); SlotIndex index = getInstructionIndex(MI); if (index < start || index >= end) @@ -1525,7 +1538,7 @@ LiveIntervals::handleSpilledImpDefs(const LiveInterval &li, VirtRegMap &vrm, MachineInstr *MI = &*ri; ++ri; if (O.isDef()) { - assert(MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF && + assert(MI->isImplicitDef() && "Register def was not rewritten?"); RemoveMachineInstrFromMaps(MI); vrm.RemoveMachineInstrFromMaps(MI); @@ -2056,7 +2069,7 @@ bool LiveIntervals::spillPhysRegAroundRegDefsUses(const LiveInterval &li, std::string msg; raw_string_ostream Msg(msg); Msg << "Ran out of registers during register allocation!"; - if (MI->getOpcode() == TargetInstrInfo::INLINEASM) { + if (MI->isInlineAsm()) { Msg << "\nPlease check your inline asm statement for invalid " << "constraints:\n"; MI->print(Msg, tm_); diff --git a/lib/CodeGen/LiveVariables.cpp b/lib/CodeGen/LiveVariables.cpp index b44a220..8a124dc 100644 --- a/lib/CodeGen/LiveVariables.cpp +++ b/lib/CodeGen/LiveVariables.cpp @@ -543,6 +543,8 @@ bool LiveVariables::runOnMachineFunction(MachineFunction &mf) { for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; ++I) { MachineInstr *MI = I; + if (MI->isDebugValue()) + continue; DistanceMap.insert(std::make_pair(MI, Dist++)); // Process all of the operands of the instruction... @@ -550,7 +552,7 @@ bool LiveVariables::runOnMachineFunction(MachineFunction &mf) { // Unless it is a PHI node. In this case, ONLY process the DEF, not any // of the uses. They will be handled in other basic blocks. - if (MI->getOpcode() == TargetInstrInfo::PHI) + if (MI->isPHI()) NumOperandsToProcess = 1; SmallVector<unsigned, 4> UseRegs; @@ -692,7 +694,7 @@ void LiveVariables::analyzePHINodes(const MachineFunction& Fn) { for (MachineFunction::const_iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) for (MachineBasicBlock::const_iterator BBI = I->begin(), BBE = I->end(); - BBI != BBE && BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI) + BBI != BBE && BBI->isPHI(); ++BBI) for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) PHIVarInfo[BBI->getOperand(i + 1).getMBB()->getNumber()] .push_back(BBI->getOperand(i).getReg()); @@ -771,8 +773,7 @@ void LiveVariables::addNewBlock(MachineBasicBlock *BB, // All registers used by PHI nodes in SuccBB must be live through BB. for (MachineBasicBlock::const_iterator BBI = SuccBB->begin(), - BBE = SuccBB->end(); - BBI != BBE && BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI) + BBE = SuccBB->end(); BBI != BBE && BBI->isPHI(); ++BBI) for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) if (BBI->getOperand(i+1).getMBB() == BB) getVarInfo(BBI->getOperand(i).getReg()).AliveBlocks.set(NumNew); diff --git a/lib/CodeGen/LowerSubregs.cpp b/lib/CodeGen/LowerSubregs.cpp index 1121d9b..b4ef648 100644 --- a/lib/CodeGen/LowerSubregs.cpp +++ b/lib/CodeGen/LowerSubregs.cpp @@ -129,7 +129,7 @@ bool LowerSubregsInstructionPass::LowerExtract(MachineInstr *MI) { if (MI->getOperand(1).isKill()) { // We must make sure the super-register gets killed. Replace the // instruction with KILL. - MI->setDesc(TII->get(TargetInstrInfo::KILL)); + MI->setDesc(TII->get(TargetOpcode::KILL)); MI->RemoveOperand(2); // SubIdx DEBUG(dbgs() << "subreg: replace by: " << *MI); return true; @@ -242,7 +242,7 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) { // <undef>, we need to make sure it is alive by inserting a KILL if (MI->getOperand(1).isUndef() && !MI->getOperand(0).isDead()) { MachineInstrBuilder MIB = BuildMI(*MBB, MI, MI->getDebugLoc(), - TII->get(TargetInstrInfo::KILL), DstReg); + TII->get(TargetOpcode::KILL), DstReg); if (MI->getOperand(2).isUndef()) MIB.addReg(InsReg, RegState::Undef); else @@ -260,7 +260,7 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) { // If the source register being inserted is undef, then this becomes a // KILL. BuildMI(*MBB, MI, MI->getDebugLoc(), - TII->get(TargetInstrInfo::KILL), DstSubReg); + TII->get(TargetOpcode::KILL), DstSubReg); else { bool Emitted = TII->copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC0, TRC1); (void)Emitted; @@ -314,11 +314,11 @@ bool LowerSubregsInstructionPass::runOnMachineFunction(MachineFunction &MF) { mi != me;) { MachineBasicBlock::iterator nmi = llvm::next(mi); MachineInstr *MI = mi; - if (MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) { + if (MI->isExtractSubreg()) { MadeChange |= LowerExtract(MI); - } else if (MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG) { + } else if (MI->isInsertSubreg()) { MadeChange |= LowerInsert(MI); - } else if (MI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG) { + } else if (MI->isSubregToReg()) { MadeChange |= LowerSubregToReg(MI); } mi = nmi; diff --git a/lib/CodeGen/MachOWriter.cpp b/lib/CodeGen/MachOWriter.cpp deleted file mode 100644 index e8bbe21..0000000 --- a/lib/CodeGen/MachOWriter.cpp +++ /dev/null @@ -1,125 +0,0 @@ -//===-- MachOWriter.cpp - Target-independent Mach-O Writer code -----------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the target-independent Mach-O writer. This file writes -// out the Mach-O file in the following order: -// -// #1 FatHeader (universal-only) -// #2 FatArch (universal-only, 1 per universal arch) -// Per arch: -// #3 Header -// #4 Load Commands -// #5 Sections -// #6 Relocations -// #7 Symbols -// #8 Strings -// -//===----------------------------------------------------------------------===// - -#include "MachOWriter.h" -#include "llvm/Function.h" -#include "llvm/CodeGen/FileWriters.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCCodeEmitter.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetLowering.h" -#include "llvm/Target/TargetLoweringObjectFile.h" -using namespace llvm; - -namespace llvm { -MachineFunctionPass *createMachOWriter(formatted_raw_ostream &O, - TargetMachine &TM, - const MCAsmInfo *T, - MCCodeEmitter *MCE) { - return new MachOWriter(O, TM, T, MCE); -} -} - -//===----------------------------------------------------------------------===// -// MachOWriter Implementation -//===----------------------------------------------------------------------===// - -char MachOWriter::ID = 0; - -MachOWriter::MachOWriter(formatted_raw_ostream &o, TargetMachine &tm, - const MCAsmInfo *T, MCCodeEmitter *MCE) - : MachineFunctionPass(&ID), O(o), TM(tm), MAI(T), MCCE(MCE), - OutContext(*new MCContext()), - OutStreamer(*createMachOStreamer(OutContext, O, MCCE)) { -} - -MachOWriter::~MachOWriter() { - delete &OutStreamer; - delete &OutContext; - delete MCCE; -} - -bool MachOWriter::doInitialization(Module &M) { - // Initialize TargetLoweringObjectFile. - TM.getTargetLowering()->getObjFileLowering().Initialize(OutContext, TM); - - return false; -} - -/// doFinalization - Now that the module has been completely processed, emit -/// the Mach-O file to 'O'. -bool MachOWriter::doFinalization(Module &M) { - OutStreamer.Finish(); - return false; -} - -bool MachOWriter::runOnMachineFunction(MachineFunction &MF) { - const Function *F = MF.getFunction(); - TargetLoweringObjectFile &TLOF = TM.getTargetLowering()->getObjFileLowering(); - const MCSection *S = TLOF.SectionForGlobal(F, Mang, TM); - OutStreamer.SwitchSection(S); - - for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); - I != E; ++I) { - // Print a label for the basic block. - for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); - II != IE; ++II) { - const MachineInstr *MI = II; - MCInst OutMI; - OutMI.setOpcode(MI->getOpcode()); - - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI->getOperand(i); - MCOperand MCOp; - - switch (MO.getType()) { - default: - MI->dump(); - llvm_unreachable("unknown operand type"); - case MachineOperand::MO_Register: - // Ignore all implicit register operands. - if (MO.isImplicit()) continue; - MCOp = MCOperand::CreateReg(MO.getReg()); - break; - case MachineOperand::MO_Immediate: - MCOp = MCOperand::CreateImm(MO.getImm()); - break; - } - OutMI.addOperand(MCOp); - } - - OutStreamer.EmitInstruction(OutMI); - } - } - - return false; -} diff --git a/lib/CodeGen/MachOWriter.h b/lib/CodeGen/MachOWriter.h deleted file mode 100644 index 2e7e67d..0000000 --- a/lib/CodeGen/MachOWriter.h +++ /dev/null @@ -1,88 +0,0 @@ -//=== MachOWriter.h - Target-independent Mach-O writer support --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the MachOWriter class. -// -//===----------------------------------------------------------------------===// - -#ifndef MACHOWRITER_H -#define MACHOWRITER_H - -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/Target/TargetMachine.h" - -namespace llvm { - class GlobalVariable; - class Mangler; - class MCCodeEmitter; - class MCContext; - class MCStreamer; - - /// MachOWriter - This class implements the common target-independent code for - /// writing Mach-O files. Targets should derive a class from this to - /// parameterize the output format. - /// - class MachOWriter : public MachineFunctionPass { - static char ID; - - protected: - /// Output stream to send the resultant object file to. - /// - formatted_raw_ostream &O; - - /// Target machine description. - /// - TargetMachine &TM; - - /// Target Asm Printer information. - /// - const MCAsmInfo *MAI; - - /// MCCE - The MCCodeEmitter object that we are exposing to emit machine - /// code for functions to the .o file. - MCCodeEmitter *MCCE; - - /// OutContext - This is the context for the output file that we are - /// streaming. This owns all of the global MC-related objects for the - /// generated translation unit. - MCContext &OutContext; - - /// OutStreamer - This is the MCStreamer object for the file we are - /// generating. This contains the transient state for the current - /// translation unit that we are generating (such as the current section - /// etc). - MCStreamer &OutStreamer; - - /// Name-mangler for global names. - /// - Mangler *Mang; - - /// doInitialization - Emit the file header and all of the global variables - /// for the module to the Mach-O file. - bool doInitialization(Module &M); - - /// doFinalization - Now that the module has been completely processed, emit - /// the Mach-O file to 'O'. - bool doFinalization(Module &M); - - bool runOnMachineFunction(MachineFunction &MF); - - public: - explicit MachOWriter(formatted_raw_ostream &O, TargetMachine &TM, - const MCAsmInfo *T, MCCodeEmitter *MCE); - - virtual ~MachOWriter(); - - virtual const char *getPassName() const { - return "Mach-O Writer"; - } - }; -} - -#endif diff --git a/lib/CodeGen/MachineBasicBlock.cpp b/lib/CodeGen/MachineBasicBlock.cpp index 9215bd5..655a0bf 100644 --- a/lib/CodeGen/MachineBasicBlock.cpp +++ b/lib/CodeGen/MachineBasicBlock.cpp @@ -14,15 +14,18 @@ #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/BasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetInstrDesc.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Support/Debug.h" #include "llvm/Support/LeakDetector.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Assembly/Writer.h" #include <algorithm> using namespace llvm; @@ -36,6 +39,18 @@ MachineBasicBlock::~MachineBasicBlock() { LeakDetector::removeGarbageObject(this); } +/// getSymbol - Return the MCSymbol for this basic block. +/// +MCSymbol *MachineBasicBlock::getSymbol(MCContext &Ctx) const { + SmallString<60> Name; + const MachineFunction *MF = getParent(); + raw_svector_ostream(Name) + << MF->getTarget().getMCAsmInfo()->getPrivateGlobalPrefix() << "BB" + << MF->getFunctionNumber() << '_' << getNumber(); + return Ctx.GetOrCreateSymbol(Name.str()); +} + + raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineBasicBlock &MBB) { MBB.print(OS); return OS; @@ -525,7 +540,7 @@ bool MachineBasicBlock::CorrectExtraCFGEdges(MachineBasicBlock *DestA, } /// findDebugLoc - find the next valid DebugLoc starting at MBBI, skipping -/// any DEBUG_VALUE instructions. Return UnknownLoc if there is none. +/// any DBG_VALUE instructions. Return UnknownLoc if there is none. DebugLoc MachineBasicBlock::findDebugLoc(MachineBasicBlock::iterator &MBBI) { DebugLoc DL; @@ -533,8 +548,7 @@ MachineBasicBlock::findDebugLoc(MachineBasicBlock::iterator &MBBI) { if (MBBI != E) { // Skip debug declarations, we don't want a DebugLoc from them. MachineBasicBlock::iterator MBBI2 = MBBI; - while (MBBI2 != E && - MBBI2->getOpcode()==TargetInstrInfo::DEBUG_VALUE) + while (MBBI2 != E && MBBI2->isDebugValue()) MBBI2++; if (MBBI2 != E) DL = MBBI2->getDebugLoc(); diff --git a/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp index 1e3e314..f141c56 100644 --- a/lib/CodeGen/MachineFunction.cpp +++ b/lib/CodeGen/MachineFunction.cpp @@ -16,7 +16,6 @@ #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/MachineFunction.h" @@ -26,12 +25,16 @@ #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" #include "llvm/Analysis/DebugInfo.h" #include "llvm/Support/Debug.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetFrameInfo.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/GraphWriter.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -70,9 +73,9 @@ FunctionPass *llvm::createMachineFunctionPrinterPass(raw_ostream &OS, return new Printer(OS, Banner); } -//===---------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// // MachineFunction implementation -//===---------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// // Out of line virtual method. MachineFunctionInfo::~MachineFunctionInfo() {} @@ -81,8 +84,8 @@ void ilist_traits<MachineBasicBlock>::deleteNode(MachineBasicBlock *MBB) { MBB->getParent()->DeleteMachineBasicBlock(MBB); } -MachineFunction::MachineFunction(Function *F, - const TargetMachine &TM) +MachineFunction::MachineFunction(Function *F, const TargetMachine &TM, + unsigned FunctionNum) : Fn(F), Target(TM) { if (TM.getRegisterInfo()) RegInfo = new (Allocator.Allocate<MachineRegisterInfo>()) @@ -95,16 +98,8 @@ MachineFunction::MachineFunction(Function *F, ConstantPool = new (Allocator.Allocate<MachineConstantPool>()) MachineConstantPool(TM.getTargetData()); Alignment = TM.getTargetLowering()->getFunctionAlignment(F); - - // Set up jump table. - const TargetData &TD = *TM.getTargetData(); - bool IsPic = TM.getRelocationModel() == Reloc::PIC_; - unsigned EntrySize = IsPic ? 4 : TD.getPointerSize(); - unsigned TyAlignment = IsPic ? - TD.getABITypeAlignment(Type::getInt32Ty(F->getContext())) - : TD.getPointerABIAlignment(); - JumpTableInfo = new (Allocator.Allocate<MachineJumpTableInfo>()) - MachineJumpTableInfo(EntrySize, TyAlignment); + FunctionNumber = FunctionNum; + JumpTableInfo = 0; } MachineFunction::~MachineFunction() { @@ -121,9 +116,23 @@ MachineFunction::~MachineFunction() { } FrameInfo->~MachineFrameInfo(); Allocator.Deallocate(FrameInfo); ConstantPool->~MachineConstantPool(); Allocator.Deallocate(ConstantPool); - JumpTableInfo->~MachineJumpTableInfo(); Allocator.Deallocate(JumpTableInfo); + + if (JumpTableInfo) { + JumpTableInfo->~MachineJumpTableInfo(); + Allocator.Deallocate(JumpTableInfo); + } } +/// getOrCreateJumpTableInfo - Get the JumpTableInfo for this function, if it +/// does already exist, allocate one. +MachineJumpTableInfo *MachineFunction:: +getOrCreateJumpTableInfo(unsigned EntryKind) { + if (JumpTableInfo) return JumpTableInfo; + + JumpTableInfo = new (Allocator.Allocate<MachineJumpTableInfo>()) + MachineJumpTableInfo((MachineJumpTableInfo::JTEntryKind)EntryKind); + return JumpTableInfo; +} /// RenumberBlocks - This discards all of the MachineBasicBlock numbers and /// recomputes them. This guarantees that the MBB numbers are sequential, @@ -178,7 +187,7 @@ MachineFunction::CreateMachineInstr(const TargetInstrDesc &TID, } /// CloneMachineInstr - Create a new MachineInstr which is a copy of the -/// 'Orig' instruction, identical in all ways except the the instruction +/// 'Orig' instruction, identical in all ways except the instruction /// has no parent, prev, or next. /// MachineInstr * @@ -311,7 +320,8 @@ void MachineFunction::print(raw_ostream &OS) const { FrameInfo->print(*this, OS); // Print JumpTable Information - JumpTableInfo->print(OS); + if (JumpTableInfo) + JumpTableInfo->print(OS); // Print Constant Pool ConstantPool->print(OS); @@ -435,6 +445,26 @@ DILocation MachineFunction::getDILocation(DebugLoc DL) const { return DILocation(DebugLocInfo.DebugLocations[Idx]); } + +/// getJTISymbol - Return the MCSymbol for the specified non-empty jump table. +/// If isLinkerPrivate is specified, an 'l' label is returned, otherwise a +/// normal 'L' label is returned. +MCSymbol *MachineFunction::getJTISymbol(unsigned JTI, MCContext &Ctx, + bool isLinkerPrivate) const { + assert(JumpTableInfo && "No jump tables"); + + assert(JTI < JumpTableInfo->getJumpTables().size() && "Invalid JTI!"); + const MCAsmInfo &MAI = *getTarget().getMCAsmInfo(); + + const char *Prefix = isLinkerPrivate ? MAI.getLinkerPrivateGlobalPrefix() : + MAI.getPrivateGlobalPrefix(); + SmallString<60> Name; + raw_svector_ostream(Name) + << Prefix << "JTI" << getFunctionNumber() << '_' << JTI; + return Ctx.GetOrCreateSymbol(Name.str()); +} + + //===----------------------------------------------------------------------===// // MachineFrameInfo implementation //===----------------------------------------------------------------------===// @@ -528,6 +558,39 @@ void MachineFrameInfo::dump(const MachineFunction &MF) const { // MachineJumpTableInfo implementation //===----------------------------------------------------------------------===// +/// getEntrySize - Return the size of each entry in the jump table. +unsigned MachineJumpTableInfo::getEntrySize(const TargetData &TD) const { + // The size of a jump table entry is 4 bytes unless the entry is just the + // address of a block, in which case it is the pointer size. + switch (getEntryKind()) { + case MachineJumpTableInfo::EK_BlockAddress: + return TD.getPointerSize(); + case MachineJumpTableInfo::EK_GPRel32BlockAddress: + case MachineJumpTableInfo::EK_LabelDifference32: + case MachineJumpTableInfo::EK_Custom32: + return 4; + } + assert(0 && "Unknown jump table encoding!"); + return ~0; +} + +/// getEntryAlignment - Return the alignment of each entry in the jump table. +unsigned MachineJumpTableInfo::getEntryAlignment(const TargetData &TD) const { + // The alignment of a jump table entry is the alignment of int32 unless the + // entry is just the address of a block, in which case it is the pointer + // alignment. + switch (getEntryKind()) { + case MachineJumpTableInfo::EK_BlockAddress: + return TD.getPointerABIAlignment(); + case MachineJumpTableInfo::EK_GPRel32BlockAddress: + case MachineJumpTableInfo::EK_LabelDifference32: + case MachineJumpTableInfo::EK_Custom32: + return TD.getABIIntegerTypeAlignment(32); + } + assert(0 && "Unknown jump table encoding!"); + return ~0; +} + /// getJumpTableIndex - Create a new jump table entry in the jump table info /// or return an existing one. /// @@ -538,11 +601,11 @@ unsigned MachineJumpTableInfo::getJumpTableIndex( return JumpTables.size()-1; } + /// ReplaceMBBInJumpTables - If Old is the target of any jump tables, update /// the jump tables to branch to New instead. -bool -MachineJumpTableInfo::ReplaceMBBInJumpTables(MachineBasicBlock *Old, - MachineBasicBlock *New) { +bool MachineJumpTableInfo::ReplaceMBBInJumpTables(MachineBasicBlock *Old, + MachineBasicBlock *New) { assert(Old != New && "Not making a change?"); bool MadeChange = false; for (size_t i = 0, e = JumpTables.size(); i != e; ++i) @@ -552,10 +615,9 @@ MachineJumpTableInfo::ReplaceMBBInJumpTables(MachineBasicBlock *Old, /// ReplaceMBBInJumpTable - If Old is a target of the jump tables, update /// the jump table to branch to New instead. -bool -MachineJumpTableInfo::ReplaceMBBInJumpTable(unsigned Idx, - MachineBasicBlock *Old, - MachineBasicBlock *New) { +bool MachineJumpTableInfo::ReplaceMBBInJumpTable(unsigned Idx, + MachineBasicBlock *Old, + MachineBasicBlock *New) { assert(Old != New && "Not making a change?"); bool MadeChange = false; MachineJumpTableEntry &JTE = JumpTables[Idx]; diff --git a/lib/CodeGen/MachineFunctionAnalysis.cpp b/lib/CodeGen/MachineFunctionAnalysis.cpp index f5febc5..8d87e3e 100644 --- a/lib/CodeGen/MachineFunctionAnalysis.cpp +++ b/lib/CodeGen/MachineFunctionAnalysis.cpp @@ -36,7 +36,7 @@ MachineFunctionAnalysis::~MachineFunctionAnalysis() { bool MachineFunctionAnalysis::runOnFunction(Function &F) { assert(!MF && "MachineFunctionAnalysis already initialized!"); - MF = new MachineFunction(&F, TM); + MF = new MachineFunction(&F, TM, NextFnNum++); return false; } diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index ef2fcee..b6d98e8 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -127,7 +127,8 @@ 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 isUndef) { + bool isKill, bool isDead, bool isUndef, + bool isDebug) { // If this operand is already a register operand, use setReg to update the // register's use/def lists. if (isReg()) { @@ -152,6 +153,7 @@ void MachineOperand::ChangeToRegister(unsigned Reg, bool isDef, bool isImp, IsDead = isDead; IsUndef = isUndef; IsEarlyClobber = false; + IsDebug = isDebug; SubReg = 0; } @@ -303,7 +305,7 @@ void MachineOperand::print(raw_ostream &OS, const TargetMachine *TM) const { MachineMemOperand::MachineMemOperand(const Value *v, unsigned int f, int64_t o, uint64_t s, unsigned int a) : Offset(o), Size(s), V(v), - Flags((f & 7) | ((Log2_32(a) + 1) << 3)) { + Flags((f & ((1 << MOMaxBits) - 1)) | ((Log2_32(a) + 1) << MOMaxBits)) { assert(getBaseAlignment() == a && "Alignment is not a power of 2!"); assert((isLoad() || isStore()) && "Not a load/store!"); } @@ -325,7 +327,8 @@ void MachineMemOperand::refineAlignment(const MachineMemOperand *MMO) { if (MMO->getBaseAlignment() >= getBaseAlignment()) { // Update the alignment value. - Flags = (Flags & 7) | ((Log2_32(MMO->getBaseAlignment()) + 1) << 3); + Flags = (Flags & ((1 << MOMaxBits) - 1)) | + ((Log2_32(MMO->getBaseAlignment()) + 1) << MOMaxBits); // Also update the base and offset, because the new alignment may // not be applicable with the old ones. V = MMO->getValue(); @@ -740,20 +743,6 @@ unsigned MachineInstr::getNumExplicitOperands() const { } -/// isLabel - Returns true if the MachineInstr represents a label. -/// -bool MachineInstr::isLabel() const { - return getOpcode() == TargetInstrInfo::DBG_LABEL || - getOpcode() == TargetInstrInfo::EH_LABEL || - getOpcode() == TargetInstrInfo::GC_LABEL; -} - -/// isDebugLabel - Returns true if the MachineInstr represents a debug label. -/// -bool MachineInstr::isDebugLabel() const { - return getOpcode() == TargetInstrInfo::DBG_LABEL; -} - /// findRegisterUseOperandIdx() - Returns the MachineOperand that is a use of /// the specific register or -1 if it is not found. It further tightens /// the search criteria to a use that kills the register if isKill is true. @@ -819,7 +808,7 @@ int MachineInstr::findFirstPredOperandIdx() const { /// first tied use operand index by reference is UseOpIdx is not null. bool MachineInstr:: isRegTiedToUseOperand(unsigned DefOpIdx, unsigned *UseOpIdx) const { - if (getOpcode() == TargetInstrInfo::INLINEASM) { + if (isInlineAsm()) { assert(DefOpIdx >= 2); const MachineOperand &MO = getOperand(DefOpIdx); if (!MO.isReg() || !MO.isDef() || MO.getReg() == 0) @@ -878,7 +867,7 @@ isRegTiedToUseOperand(unsigned DefOpIdx, unsigned *UseOpIdx) const { /// operand index by reference. bool MachineInstr:: isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx) const { - if (getOpcode() == TargetInstrInfo::INLINEASM) { + if (isInlineAsm()) { const MachineOperand &MO = getOperand(UseOpIdx); if (!MO.isReg() || !MO.isUse() || MO.getReg() == 0) return false; @@ -1046,7 +1035,7 @@ bool MachineInstr::hasVolatileMemoryRef() const { /// isInvariantLoad - Return true if this instruction is loading from a /// location whose value is invariant across the function. For example, -/// loading a value from the constant pool or from from the argument area +/// loading a value from the constant pool or from the argument area /// of a function if it does not change. This should only return true of /// *all* loads the instruction does are invariant (if it does multiple loads). bool MachineInstr::isInvariantLoad(AliasAnalysis *AA) const { @@ -1088,7 +1077,7 @@ bool MachineInstr::isInvariantLoad(AliasAnalysis *AA) const { /// merges together the same virtual register, return the register, otherwise /// return 0. unsigned MachineInstr::isConstantValuePHI() const { - if (getOpcode() != TargetInstrInfo::PHI) + if (!isPHI()) return 0; assert(getNumOperands() >= 3 && "It's illegal to have a PHI without source operands"); diff --git a/lib/CodeGen/MachineLICM.cpp b/lib/CodeGen/MachineLICM.cpp index ffcc8ab..92c84f3 100644 --- a/lib/CodeGen/MachineLICM.cpp +++ b/lib/CodeGen/MachineLICM.cpp @@ -336,7 +336,7 @@ static bool HasPHIUses(unsigned Reg, MachineRegisterInfo *RegInfo) { for (MachineRegisterInfo::use_iterator UI = RegInfo->use_begin(Reg), UE = RegInfo->use_end(); UI != UE; ++UI) { MachineInstr *UseMI = &*UI; - if (UseMI->getOpcode() == TargetInstrInfo::PHI) + if (UseMI->isPHI()) return true; } return false; @@ -363,7 +363,7 @@ bool MachineLICM::isLoadFromConstantMemory(MachineInstr *MI) { /// IsProfitableToHoist - Return true if it is potentially profitable to hoist /// the given loop invariant. bool MachineLICM::IsProfitableToHoist(MachineInstr &MI) { - if (MI.getOpcode() == TargetInstrInfo::IMPLICIT_DEF) + if (MI.isImplicitDef()) return false; // FIXME: For now, only hoist re-materilizable instructions. LICM will diff --git a/lib/CodeGen/MachineModuleInfo.cpp b/lib/CodeGen/MachineModuleInfo.cpp index ed5bb5e..5052af7 100644 --- a/lib/CodeGen/MachineModuleInfo.cpp +++ b/lib/CodeGen/MachineModuleInfo.cpp @@ -40,6 +40,7 @@ MachineModuleInfoImpl::~MachineModuleInfoImpl() {} MachineModuleInfo::MachineModuleInfo() : ImmutablePass(&ID) , ObjFileMMI(0) +, CurCallSite(0) , CallsEHReturn(0) , CallsUnwindInit(0) , DbgInfoAvailable(false) { @@ -71,6 +72,7 @@ void MachineModuleInfo::EndFunction() { // Clean up exception info. LandingPads.clear(); + CallSiteMap.clear(); TypeInfos.clear(); FilterIds.clear(); FilterEnds.clear(); diff --git a/lib/CodeGen/MachineModuleInfoImpls.cpp b/lib/CodeGen/MachineModuleInfoImpls.cpp index 7a62929..39d2c75 100644 --- a/lib/CodeGen/MachineModuleInfoImpls.cpp +++ b/lib/CodeGen/MachineModuleInfoImpls.cpp @@ -22,22 +22,23 @@ using namespace llvm; // Out of line virtual method. void MachineModuleInfoMachO::Anchor() {} - +void MachineModuleInfoELF::Anchor() {} static int SortSymbolPair(const void *LHS, const void *RHS) { const MCSymbol *LHSS = - ((const std::pair<const MCSymbol*, const MCSymbol*>*)LHS)->first; + ((const std::pair<MCSymbol*, MCSymbol*>*)LHS)->first; const MCSymbol *RHSS = - ((const std::pair<const MCSymbol*, const MCSymbol*>*)RHS)->first; + ((const std::pair<MCSymbol*, MCSymbol*>*)RHS)->first; return LHSS->getName().compare(RHSS->getName()); } /// GetSortedStubs - Return the entries from a DenseMap in a deterministic /// sorted orer. -MachineModuleInfoMachO::SymbolListTy -MachineModuleInfoMachO::GetSortedStubs(const DenseMap<const MCSymbol*, - const MCSymbol*> &Map) { - MachineModuleInfoMachO::SymbolListTy List(Map.begin(), Map.end()); +MachineModuleInfoImpl::SymbolListTy +MachineModuleInfoImpl::GetSortedStubs(const DenseMap<MCSymbol*, + MCSymbol*> &Map) { + MachineModuleInfoImpl::SymbolListTy List(Map.begin(), Map.end()); + if (!List.empty()) qsort(&List[0], List.size(), sizeof(List[0]), SortSymbolPair); return List; diff --git a/lib/CodeGen/MachineSSAUpdater.cpp b/lib/CodeGen/MachineSSAUpdater.cpp index 467ea5d..2255dc3 100644 --- a/lib/CodeGen/MachineSSAUpdater.cpp +++ b/lib/CodeGen/MachineSSAUpdater.cpp @@ -20,6 +20,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -92,13 +93,13 @@ unsigned LookForIdenticalPHI(MachineBasicBlock *BB, return 0; MachineBasicBlock::iterator I = BB->front(); - if (I->getOpcode() != TargetInstrInfo::PHI) + if (!I->isPHI()) return 0; AvailableValsTy AVals; for (unsigned i = 0, e = PredValues.size(); i != e; ++i) AVals[PredValues[i].first] = PredValues[i].second; - while (I != BB->end() && I->getOpcode() == TargetInstrInfo::PHI) { + while (I != BB->end() && I->isPHI()) { bool Same = true; for (unsigned i = 1, e = I->getNumOperands(); i != e; i += 2) { unsigned SrcReg = I->getOperand(i).getReg(); @@ -155,7 +156,7 @@ unsigned MachineSSAUpdater::GetValueInMiddleOfBlock(MachineBasicBlock *BB) { // If there are no predecessors, just return undef. if (BB->pred_empty()) { // Insert an implicit_def to represent an undef value. - MachineInstr *NewDef = InsertNewDef(TargetInstrInfo::IMPLICIT_DEF, + MachineInstr *NewDef = InsertNewDef(TargetOpcode::IMPLICIT_DEF, BB, BB->getFirstTerminator(), VRC, MRI, TII); return NewDef->getOperand(0).getReg(); @@ -192,7 +193,7 @@ unsigned MachineSSAUpdater::GetValueInMiddleOfBlock(MachineBasicBlock *BB) { // Otherwise, we do need a PHI: insert one now. MachineBasicBlock::iterator Loc = BB->empty() ? BB->end() : BB->front(); - MachineInstr *InsertedPHI = InsertNewDef(TargetInstrInfo::PHI, BB, + MachineInstr *InsertedPHI = InsertNewDef(TargetOpcode::PHI, BB, Loc, VRC, MRI, TII); // Fill in all the predecessors of the PHI. @@ -231,7 +232,7 @@ MachineBasicBlock *findCorrespondingPred(const MachineInstr *MI, void MachineSSAUpdater::RewriteUse(MachineOperand &U) { MachineInstr *UseMI = U.getParent(); unsigned NewVR = 0; - if (UseMI->getOpcode() == TargetInstrInfo::PHI) { + if (UseMI->isPHI()) { MachineBasicBlock *SourceBB = findCorrespondingPred(UseMI, &U); NewVR = GetValueAtEndOfBlockInternal(SourceBB); } else { @@ -277,7 +278,7 @@ unsigned MachineSSAUpdater::GetValueAtEndOfBlockInternal(MachineBasicBlock *BB){ // it. When we get back to the first instance of the recursion we will fill // in the PHI node. MachineBasicBlock::iterator Loc = BB->empty() ? BB->end() : BB->front(); - MachineInstr *NewPHI = InsertNewDef(TargetInstrInfo::PHI, BB, Loc, + MachineInstr *NewPHI = InsertNewDef(TargetOpcode::PHI, BB, Loc, VRC, MRI,TII); unsigned NewVR = NewPHI->getOperand(0).getReg(); InsertRes.first->second = NewVR; @@ -289,7 +290,7 @@ unsigned MachineSSAUpdater::GetValueAtEndOfBlockInternal(MachineBasicBlock *BB){ // be invalidated. if (BB->pred_empty()) { // Insert an implicit_def to represent an undef value. - MachineInstr *NewDef = InsertNewDef(TargetInstrInfo::IMPLICIT_DEF, + MachineInstr *NewDef = InsertNewDef(TargetOpcode::IMPLICIT_DEF, BB, BB->getFirstTerminator(), VRC, MRI, TII); return InsertRes.first->second = NewDef->getOperand(0).getReg(); @@ -358,7 +359,7 @@ unsigned MachineSSAUpdater::GetValueAtEndOfBlockInternal(MachineBasicBlock *BB){ MachineInstr *InsertedPHI; if (InsertedVal == 0) { MachineBasicBlock::iterator Loc = BB->empty() ? BB->end() : BB->front(); - InsertedPHI = InsertNewDef(TargetInstrInfo::PHI, BB, Loc, + InsertedPHI = InsertNewDef(TargetOpcode::PHI, BB, Loc, VRC, MRI, TII); InsertedVal = InsertedPHI->getOperand(0).getReg(); } else { diff --git a/lib/CodeGen/MachineSink.cpp b/lib/CodeGen/MachineSink.cpp index c177e3c..c391576 100644 --- a/lib/CodeGen/MachineSink.cpp +++ b/lib/CodeGen/MachineSink.cpp @@ -77,7 +77,7 @@ bool MachineSinking::AllUsesDominatedByBlock(unsigned Reg, // Determine the block of the use. MachineInstr *UseInst = &*I; MachineBasicBlock *UseBlock = UseInst->getParent(); - if (UseInst->getOpcode() == TargetInstrInfo::PHI) { + if (UseInst->isPHI()) { // PHI nodes use the operand in the predecessor block, not the block with // the PHI. UseBlock = UseInst->getOperand(I.getOperandNo()+1).getMBB(); @@ -269,8 +269,7 @@ bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore) { // Determine where to insert into. Skip phi nodes. MachineBasicBlock::iterator InsertPos = SuccToSinkTo->begin(); - while (InsertPos != SuccToSinkTo->end() && - InsertPos->getOpcode() == TargetInstrInfo::PHI) + while (InsertPos != SuccToSinkTo->end() && InsertPos->isPHI()) ++InsertPos; // Move the instruction. diff --git a/lib/CodeGen/MachineVerifier.cpp b/lib/CodeGen/MachineVerifier.cpp index 584c21b..434a1e8 100644 --- a/lib/CodeGen/MachineVerifier.cpp +++ b/lib/CodeGen/MachineVerifier.cpp @@ -590,7 +590,7 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { // must be live in. PHI instructions are handled separately. if (MInfo.regsKilled.count(Reg)) report("Using a killed virtual register", MO, MONum); - else if (MI->getOpcode() != TargetInstrInfo::PHI) + else if (!MI->isPHI()) MInfo.vregsLiveIn.insert(std::make_pair(Reg, MI)); } } @@ -650,10 +650,8 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { } case MachineOperand::MO_MachineBasicBlock: - if (MI->getOpcode() == TargetInstrInfo::PHI) { - if (!MO->getMBB()->isSuccessor(MI->getParent())) - report("PHI operand is not in the CFG", MO, MONum); - } + if (MI->isPHI() && !MO->getMBB()->isSuccessor(MI->getParent())) + report("PHI operand is not in the CFG", MO, MONum); break; default: @@ -783,7 +781,7 @@ void MachineVerifier::calcRegsRequired() { // calcRegsPassed has been run so BBInfo::isLiveOut is valid. void MachineVerifier::checkPHIOps(const MachineBasicBlock *MBB) { for (MachineBasicBlock::const_iterator BBI = MBB->begin(), BBE = MBB->end(); - BBI != BBE && BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI) { + BBI != BBE && BBI->isPHI(); ++BBI) { DenseSet<const MachineBasicBlock*> seen; for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) { diff --git a/lib/CodeGen/Makefile b/lib/CodeGen/Makefile index 8c0204c..4ab3e3c 100644 --- a/lib/CodeGen/Makefile +++ b/lib/CodeGen/Makefile @@ -11,7 +11,6 @@ LEVEL = ../.. LIBRARYNAME = LLVMCodeGen PARALLEL_DIRS = SelectionDAG AsmPrinter BUILD_ARCHIVE = 1 -CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/CodeGen/OptimizeExts.cpp b/lib/CodeGen/OptimizeExts.cpp index 096f9d4..acb6869 100644 --- a/lib/CodeGen/OptimizeExts.cpp +++ b/lib/CodeGen/OptimizeExts.cpp @@ -110,7 +110,7 @@ bool OptimizeExts::OptimizeInstr(MachineInstr *MI, MachineBasicBlock *MBB, MachineInstr *UseMI = &*UI; if (UseMI == MI) continue; - if (UseMI->getOpcode() == TargetInstrInfo::PHI) { + if (UseMI->isPHI()) { ExtendLife = false; continue; } @@ -150,7 +150,7 @@ bool OptimizeExts::OptimizeInstr(MachineInstr *MI, MachineBasicBlock *MBB, UI = MRI->use_begin(DstReg); for (MachineRegisterInfo::use_iterator UE = MRI->use_end(); UI != UE; ++UI) - if (UI->getOpcode() == TargetInstrInfo::PHI) + if (UI->isPHI()) PHIBBs.insert(UI->getParent()); const TargetRegisterClass *RC = MRI->getRegClass(SrcReg); @@ -162,7 +162,7 @@ bool OptimizeExts::OptimizeInstr(MachineInstr *MI, MachineBasicBlock *MBB, continue; unsigned NewVR = MRI->createVirtualRegister(RC); BuildMI(*UseMBB, UseMI, UseMI->getDebugLoc(), - TII->get(TargetInstrInfo::EXTRACT_SUBREG), NewVR) + TII->get(TargetOpcode::EXTRACT_SUBREG), NewVR) .addReg(DstReg).addImm(SubIdx); UseMO->setReg(NewVR); ++NumReuse; diff --git a/lib/CodeGen/OptimizePHIs.cpp b/lib/CodeGen/OptimizePHIs.cpp new file mode 100644 index 0000000..2717d4d --- /dev/null +++ b/lib/CodeGen/OptimizePHIs.cpp @@ -0,0 +1,189 @@ +//===-- OptimizePHIs.cpp - Optimize machine instruction PHIs --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass optimizes machine instruction PHIs to take advantage of +// opportunities created during DAG legalization. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "phi-opt" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Function.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumPHICycles, "Number of PHI cycles replaced"); +STATISTIC(NumDeadPHICycles, "Number of dead PHI cycles"); + +namespace { + class OptimizePHIs : public MachineFunctionPass { + MachineRegisterInfo *MRI; + const TargetInstrInfo *TII; + + public: + static char ID; // Pass identification + OptimizePHIs() : MachineFunctionPass(&ID) {} + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + private: + typedef SmallPtrSet<MachineInstr*, 16> InstrSet; + typedef SmallPtrSetIterator<MachineInstr*> InstrSetIterator; + + bool IsSingleValuePHICycle(MachineInstr *MI, unsigned &SingleValReg, + InstrSet &PHIsInCycle); + bool IsDeadPHICycle(MachineInstr *MI, InstrSet &PHIsInCycle); + bool OptimizeBB(MachineBasicBlock &MBB); + }; +} + +char OptimizePHIs::ID = 0; +static RegisterPass<OptimizePHIs> +X("opt-phis", "Optimize machine instruction PHIs"); + +FunctionPass *llvm::createOptimizePHIsPass() { return new OptimizePHIs(); } + +bool OptimizePHIs::runOnMachineFunction(MachineFunction &Fn) { + MRI = &Fn.getRegInfo(); + TII = Fn.getTarget().getInstrInfo(); + + // Find dead PHI cycles and PHI cycles that can be replaced by a single + // value. InstCombine does these optimizations, but DAG legalization may + // introduce new opportunities, e.g., when i64 values are split up for + // 32-bit targets. + bool Changed = false; + for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) + Changed |= OptimizeBB(*I); + + return Changed; +} + +/// IsSingleValuePHICycle - Check if MI is a PHI where all the source operands +/// are copies of SingleValReg, possibly via copies through other PHIs. If +/// SingleValReg is zero on entry, it is set to the register with the single +/// non-copy value. PHIsInCycle is a set used to keep track of the PHIs that +/// have been scanned. +bool OptimizePHIs::IsSingleValuePHICycle(MachineInstr *MI, + unsigned &SingleValReg, + InstrSet &PHIsInCycle) { + assert(MI->isPHI() && "IsSingleValuePHICycle expects a PHI instruction"); + unsigned DstReg = MI->getOperand(0).getReg(); + + // See if we already saw this register. + if (!PHIsInCycle.insert(MI)) + return true; + + // Don't scan crazily complex things. + if (PHIsInCycle.size() == 16) + return false; + + // Scan the PHI operands. + for (unsigned i = 1; i != MI->getNumOperands(); i += 2) { + unsigned SrcReg = MI->getOperand(i).getReg(); + if (SrcReg == DstReg) + continue; + MachineInstr *SrcMI = MRI->getVRegDef(SrcReg); + + // Skip over register-to-register moves. + unsigned MvSrcReg, MvDstReg, SrcSubIdx, DstSubIdx; + if (SrcMI && + TII->isMoveInstr(*SrcMI, MvSrcReg, MvDstReg, SrcSubIdx, DstSubIdx) && + SrcSubIdx == 0 && DstSubIdx == 0 && + TargetRegisterInfo::isVirtualRegister(MvSrcReg)) + SrcMI = MRI->getVRegDef(MvSrcReg); + if (!SrcMI) + return false; + + if (SrcMI->isPHI()) { + if (!IsSingleValuePHICycle(SrcMI, SingleValReg, PHIsInCycle)) + return false; + } else { + // Fail if there is more than one non-phi/non-move register. + if (SingleValReg != 0) + return false; + SingleValReg = SrcReg; + } + } + return true; +} + +/// IsDeadPHICycle - Check if the register defined by a PHI is only used by +/// other PHIs in a cycle. +bool OptimizePHIs::IsDeadPHICycle(MachineInstr *MI, InstrSet &PHIsInCycle) { + assert(MI->isPHI() && "IsDeadPHICycle expects a PHI instruction"); + unsigned DstReg = MI->getOperand(0).getReg(); + assert(TargetRegisterInfo::isVirtualRegister(DstReg) && + "PHI destination is not a virtual register"); + + // See if we already saw this register. + if (!PHIsInCycle.insert(MI)) + return true; + + // Don't scan crazily complex things. + if (PHIsInCycle.size() == 16) + return false; + + for (MachineRegisterInfo::use_iterator I = MRI->use_begin(DstReg), + E = MRI->use_end(); I != E; ++I) { + MachineInstr *UseMI = &*I; + if (!UseMI->isPHI() || !IsDeadPHICycle(UseMI, PHIsInCycle)) + return false; + } + + return true; +} + +/// OptimizeBB - Remove dead PHI cycles and PHI cycles that can be replaced by +/// a single value. +bool OptimizePHIs::OptimizeBB(MachineBasicBlock &MBB) { + bool Changed = false; + for (MachineBasicBlock::iterator + MII = MBB.begin(), E = MBB.end(); MII != E; ) { + MachineInstr *MI = &*MII++; + if (!MI->isPHI()) + break; + + // Check for single-value PHI cycles. + unsigned SingleValReg = 0; + InstrSet PHIsInCycle; + if (IsSingleValuePHICycle(MI, SingleValReg, PHIsInCycle) && + SingleValReg != 0) { + MRI->replaceRegWith(MI->getOperand(0).getReg(), SingleValReg); + MI->eraseFromParent(); + ++NumPHICycles; + Changed = true; + continue; + } + + // Check for dead PHI cycles. + PHIsInCycle.clear(); + if (IsDeadPHICycle(MI, PHIsInCycle)) { + for (InstrSetIterator PI = PHIsInCycle.begin(), PE = PHIsInCycle.end(); + PI != PE; ++PI) { + MachineInstr *PhiMI = *PI; + if (&*MII == PhiMI) + ++MII; + PhiMI->eraseFromParent(); + } + ++NumDeadPHICycles; + Changed = true; + } + } + return Changed; +} diff --git a/lib/CodeGen/PBQP/AnnotatedGraph.h b/lib/CodeGen/PBQP/AnnotatedGraph.h deleted file mode 100644 index 738dea0..0000000 --- a/lib/CodeGen/PBQP/AnnotatedGraph.h +++ /dev/null @@ -1,184 +0,0 @@ -//===-- AnnotatedGraph.h - Annotated PBQP Graph -----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Annotated PBQP Graph class. This class is used internally by the PBQP solver -// to cache information to speed up reduction. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_PBQP_ANNOTATEDGRAPH_H -#define LLVM_CODEGEN_PBQP_ANNOTATEDGRAPH_H - -#include "GraphBase.h" - -namespace PBQP { - - -template <typename NodeData, typename EdgeData> class AnnotatedEdge; - -template <typename NodeData, typename EdgeData> -class AnnotatedNode : public NodeBase<AnnotatedNode<NodeData, EdgeData>, - AnnotatedEdge<NodeData, EdgeData> > { -private: - - NodeData nodeData; - -public: - - AnnotatedNode(const Vector &costs, const NodeData &nodeData) : - NodeBase<AnnotatedNode<NodeData, EdgeData>, - AnnotatedEdge<NodeData, EdgeData> >(costs), - nodeData(nodeData) {} - - NodeData& getNodeData() { return nodeData; } - const NodeData& getNodeData() const { return nodeData; } - -}; - -template <typename NodeData, typename EdgeData> -class AnnotatedEdge : public EdgeBase<AnnotatedNode<NodeData, EdgeData>, - AnnotatedEdge<NodeData, EdgeData> > { -private: - - typedef typename GraphBase<AnnotatedNode<NodeData, EdgeData>, - AnnotatedEdge<NodeData, EdgeData> >::NodeIterator - NodeIterator; - - EdgeData edgeData; - -public: - - - AnnotatedEdge(const NodeIterator &node1Itr, const NodeIterator &node2Itr, - const Matrix &costs, const EdgeData &edgeData) : - EdgeBase<AnnotatedNode<NodeData, EdgeData>, - AnnotatedEdge<NodeData, EdgeData> >(node1Itr, node2Itr, costs), - edgeData(edgeData) {} - - EdgeData& getEdgeData() { return edgeData; } - const EdgeData& getEdgeData() const { return edgeData; } - -}; - -template <typename NodeData, typename EdgeData> -class AnnotatedGraph : public GraphBase<AnnotatedNode<NodeData, EdgeData>, - AnnotatedEdge<NodeData, EdgeData> > { -private: - - typedef GraphBase<AnnotatedNode<NodeData, EdgeData>, - AnnotatedEdge<NodeData, EdgeData> > PGraph; - - typedef AnnotatedNode<NodeData, EdgeData> NodeEntry; - typedef AnnotatedEdge<NodeData, EdgeData> EdgeEntry; - - - void copyFrom(const AnnotatedGraph &other) { - if (!other.areNodeIDsValid()) { - other.assignNodeIDs(); - } - std::vector<NodeIterator> newNodeItrs(other.getNumNodes()); - - for (ConstNodeIterator nItr = other.nodesBegin(), nEnd = other.nodesEnd(); - nItr != nEnd; ++nItr) { - newNodeItrs[other.getNodeID(nItr)] = addNode(other.getNodeCosts(nItr)); - } - - for (ConstEdgeIterator eItr = other.edgesBegin(), eEnd = other.edgesEnd(); - eItr != eEnd; ++eItr) { - - unsigned node1ID = other.getNodeID(other.getEdgeNode1(eItr)), - node2ID = other.getNodeID(other.getEdgeNode2(eItr)); - - addEdge(newNodeItrs[node1ID], newNodeItrs[node2ID], - other.getEdgeCosts(eItr), other.getEdgeData(eItr)); - } - - } - -public: - - typedef typename PGraph::NodeIterator NodeIterator; - typedef typename PGraph::ConstNodeIterator ConstNodeIterator; - typedef typename PGraph::EdgeIterator EdgeIterator; - typedef typename PGraph::ConstEdgeIterator ConstEdgeIterator; - - AnnotatedGraph() {} - - AnnotatedGraph(const AnnotatedGraph &other) { - copyFrom(other); - } - - AnnotatedGraph& operator=(const AnnotatedGraph &other) { - PGraph::clear(); - copyFrom(other); - return *this; - } - - NodeIterator addNode(const Vector &costs, const NodeData &data) { - return PGraph::addConstructedNode(NodeEntry(costs, data)); - } - - EdgeIterator addEdge(const NodeIterator &node1Itr, - const NodeIterator &node2Itr, - const Matrix &costs, const EdgeData &data) { - return PGraph::addConstructedEdge(EdgeEntry(node1Itr, node2Itr, - costs, data)); - } - - NodeData& getNodeData(const NodeIterator &nodeItr) { - return PGraph::getNodeEntry(nodeItr).getNodeData(); - } - - const NodeData& getNodeData(const NodeIterator &nodeItr) const { - return PGraph::getNodeEntry(nodeItr).getNodeData(); - } - - EdgeData& getEdgeData(const EdgeIterator &edgeItr) { - return PGraph::getEdgeEntry(edgeItr).getEdgeData(); - } - - const EdgeEntry& getEdgeData(const EdgeIterator &edgeItr) const { - return PGraph::getEdgeEntry(edgeItr).getEdgeData(); - } - - SimpleGraph toSimpleGraph() const { - SimpleGraph g; - - if (!PGraph::areNodeIDsValid()) { - PGraph::assignNodeIDs(); - } - std::vector<SimpleGraph::NodeIterator> newNodeItrs(PGraph::getNumNodes()); - - for (ConstNodeIterator nItr = PGraph::nodesBegin(), - nEnd = PGraph::nodesEnd(); - nItr != nEnd; ++nItr) { - - newNodeItrs[getNodeID(nItr)] = g.addNode(getNodeCosts(nItr)); - } - - for (ConstEdgeIterator - eItr = PGraph::edgesBegin(), eEnd = PGraph::edgesEnd(); - eItr != eEnd; ++eItr) { - - unsigned node1ID = getNodeID(getEdgeNode1(eItr)), - node2ID = getNodeID(getEdgeNode2(eItr)); - - g.addEdge(newNodeItrs[node1ID], newNodeItrs[node2ID], - getEdgeCosts(eItr)); - } - - return g; - } - -}; - - -} - -#endif // LLVM_CODEGEN_PBQP_ANNOTATEDGRAPH_H diff --git a/lib/CodeGen/PBQP/ExhaustiveSolver.h b/lib/CodeGen/PBQP/ExhaustiveSolver.h deleted file mode 100644 index 35ec4f1..0000000 --- a/lib/CodeGen/PBQP/ExhaustiveSolver.h +++ /dev/null @@ -1,110 +0,0 @@ -//===-- ExhaustiveSolver.h - Brute Force PBQP Solver ------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Uses a trivial brute force algorithm to solve a PBQP problem. -// PBQP is NP-HARD - This solver should only be used for debugging small -// problems. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_PBQP_EXHAUSTIVESOLVER_H -#define LLVM_CODEGEN_PBQP_EXHAUSTIVESOLVER_H - -#include "Solver.h" - -namespace PBQP { - -/// A brute force PBQP solver. This solver takes exponential time. It should -/// only be used for debugging purposes. -class ExhaustiveSolverImpl { -private: - - const SimpleGraph &g; - - PBQPNum getSolutionCost(const Solution &solution) const { - PBQPNum cost = 0.0; - - for (SimpleGraph::ConstNodeIterator - nodeItr = g.nodesBegin(), nodeEnd = g.nodesEnd(); - nodeItr != nodeEnd; ++nodeItr) { - - unsigned nodeId = g.getNodeID(nodeItr); - - cost += g.getNodeCosts(nodeItr)[solution.getSelection(nodeId)]; - } - - for (SimpleGraph::ConstEdgeIterator - edgeItr = g.edgesBegin(), edgeEnd = g.edgesEnd(); - edgeItr != edgeEnd; ++edgeItr) { - - SimpleGraph::ConstNodeIterator n1 = g.getEdgeNode1Itr(edgeItr), - n2 = g.getEdgeNode2Itr(edgeItr); - unsigned sol1 = solution.getSelection(g.getNodeID(n1)), - sol2 = solution.getSelection(g.getNodeID(n2)); - - cost += g.getEdgeCosts(edgeItr)[sol1][sol2]; - } - - return cost; - } - -public: - - ExhaustiveSolverImpl(const SimpleGraph &g) : g(g) {} - - Solution solve() const { - Solution current(g.getNumNodes(), true), optimal(current); - - PBQPNum bestCost = std::numeric_limits<PBQPNum>::infinity(); - bool finished = false; - - while (!finished) { - PBQPNum currentCost = getSolutionCost(current); - - if (currentCost < bestCost) { - optimal = current; - bestCost = currentCost; - } - - // assume we're done. - finished = true; - - for (unsigned i = 0; i < g.getNumNodes(); ++i) { - if (current.getSelection(i) == - (g.getNodeCosts(g.getNodeItr(i)).getLength() - 1)) { - current.setSelection(i, 0); - } - else { - current.setSelection(i, current.getSelection(i) + 1); - finished = false; - break; - } - } - - } - - optimal.setSolutionCost(bestCost); - - return optimal; - } - -}; - -class ExhaustiveSolver : public Solver { -public: - ~ExhaustiveSolver() {} - Solution solve(const SimpleGraph &g) const { - ExhaustiveSolverImpl solver(g); - return solver.solve(); - } -}; - -} - -#endif // LLVM_CODGEN_PBQP_EXHAUSTIVESOLVER_HPP diff --git a/lib/CodeGen/PBQP/Graph.h b/lib/CodeGen/PBQP/Graph.h new file mode 100644 index 0000000..b2224cb --- /dev/null +++ b/lib/CodeGen/PBQP/Graph.h @@ -0,0 +1,425 @@ +//===-------------------- Graph.h - PBQP Graph ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// PBQP Graph class. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CODEGEN_PBQP_GRAPH_H +#define LLVM_CODEGEN_PBQP_GRAPH_H + +#include "Math.h" + +#include <list> +#include <vector> +#include <map> + +namespace PBQP { + + /// PBQP Graph class. + /// Instances of this class describe PBQP problems. + class Graph { + private: + + // ----- TYPEDEFS ----- + class NodeEntry; + class EdgeEntry; + + typedef std::list<NodeEntry> NodeList; + typedef std::list<EdgeEntry> EdgeList; + + public: + + typedef NodeList::iterator NodeItr; + typedef NodeList::const_iterator ConstNodeItr; + + typedef EdgeList::iterator EdgeItr; + typedef EdgeList::const_iterator ConstEdgeItr; + + private: + + typedef std::list<EdgeItr> AdjEdgeList; + + public: + + typedef AdjEdgeList::iterator AdjEdgeItr; + + private: + + class NodeEntry { + private: + Vector costs; + AdjEdgeList adjEdges; + unsigned degree; + void *data; + public: + NodeEntry(const Vector &costs) : costs(costs), degree(0) {} + Vector& getCosts() { return costs; } + const Vector& getCosts() const { return costs; } + unsigned getDegree() const { return degree; } + AdjEdgeItr edgesBegin() { return adjEdges.begin(); } + AdjEdgeItr edgesEnd() { return adjEdges.end(); } + AdjEdgeItr addEdge(EdgeItr e) { + ++degree; + return adjEdges.insert(adjEdges.end(), e); + } + void removeEdge(AdjEdgeItr ae) { + --degree; + adjEdges.erase(ae); + } + void setData(void *data) { this->data = data; } + void* getData() { return data; } + }; + + class EdgeEntry { + private: + NodeItr node1, node2; + Matrix costs; + AdjEdgeItr node1AEItr, node2AEItr; + void *data; + public: + EdgeEntry(NodeItr node1, NodeItr node2, const Matrix &costs) + : node1(node1), node2(node2), costs(costs) {} + NodeItr getNode1() const { return node1; } + NodeItr getNode2() const { return node2; } + Matrix& getCosts() { return costs; } + const Matrix& getCosts() const { return costs; } + void setNode1AEItr(AdjEdgeItr ae) { node1AEItr = ae; } + AdjEdgeItr getNode1AEItr() { return node1AEItr; } + void setNode2AEItr(AdjEdgeItr ae) { node2AEItr = ae; } + AdjEdgeItr getNode2AEItr() { return node2AEItr; } + void setData(void *data) { this->data = data; } + void *getData() { return data; } + }; + + // ----- MEMBERS ----- + + NodeList nodes; + unsigned numNodes; + + EdgeList edges; + unsigned numEdges; + + // ----- INTERNAL METHODS ----- + + NodeEntry& getNode(NodeItr nItr) { return *nItr; } + const NodeEntry& getNode(ConstNodeItr nItr) const { return *nItr; } + + EdgeEntry& getEdge(EdgeItr eItr) { return *eItr; } + const EdgeEntry& getEdge(ConstEdgeItr eItr) const { return *eItr; } + + NodeItr addConstructedNode(const NodeEntry &n) { + ++numNodes; + return nodes.insert(nodes.end(), n); + } + + EdgeItr addConstructedEdge(const EdgeEntry &e) { + assert(findEdge(e.getNode1(), e.getNode2()) == edges.end() && + "Attempt to add duplicate edge."); + ++numEdges; + EdgeItr edgeItr = edges.insert(edges.end(), e); + EdgeEntry &ne = getEdge(edgeItr); + NodeEntry &n1 = getNode(ne.getNode1()); + NodeEntry &n2 = getNode(ne.getNode2()); + // Sanity check on matrix dimensions: + assert((n1.getCosts().getLength() == ne.getCosts().getRows()) && + (n2.getCosts().getLength() == ne.getCosts().getCols()) && + "Edge cost dimensions do not match node costs dimensions."); + ne.setNode1AEItr(n1.addEdge(edgeItr)); + ne.setNode2AEItr(n2.addEdge(edgeItr)); + return edgeItr; + } + + inline void copyFrom(const Graph &other); + public: + + /// \brief Construct an empty PBQP graph. + Graph() : numNodes(0), numEdges(0) {} + + /// \brief Copy construct this graph from "other". Note: Does not copy node + /// and edge data, only graph structure and costs. + /// @param other Source graph to copy from. + Graph(const Graph &other) : numNodes(0), numEdges(0) { + copyFrom(other); + } + + /// \brief Make this graph a copy of "other". Note: Does not copy node and + /// edge data, only graph structure and costs. + /// @param other The graph to copy from. + /// @return A reference to this graph. + /// + /// This will clear the current graph, erasing any nodes and edges added, + /// before copying from other. + Graph& operator=(const Graph &other) { + clear(); + copyFrom(other); + return *this; + } + + /// \brief Add a node with the given costs. + /// @param costs Cost vector for the new node. + /// @return Node iterator for the added node. + NodeItr addNode(const Vector &costs) { + return addConstructedNode(NodeEntry(costs)); + } + + /// \brief Add an edge between the given nodes with the given costs. + /// @param n1Itr First node. + /// @param n2Itr Second node. + /// @return Edge iterator for the added edge. + EdgeItr addEdge(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr, + const Matrix &costs) { + assert(getNodeCosts(n1Itr).getLength() == costs.getRows() && + getNodeCosts(n2Itr).getLength() == costs.getCols() && + "Matrix dimensions mismatch."); + return addConstructedEdge(EdgeEntry(n1Itr, n2Itr, costs)); + } + + /// \brief Get the number of nodes in the graph. + /// @return Number of nodes in the graph. + unsigned getNumNodes() const { return numNodes; } + + /// \brief Get the number of edges in the graph. + /// @return Number of edges in the graph. + unsigned getNumEdges() const { return numEdges; } + + /// \brief Get a node's cost vector. + /// @param nItr Node iterator. + /// @return Node cost vector. + Vector& getNodeCosts(NodeItr nItr) { return getNode(nItr).getCosts(); } + + /// \brief Get a node's cost vector (const version). + /// @param nItr Node iterator. + /// @return Node cost vector. + const Vector& getNodeCosts(ConstNodeItr nItr) const { + return getNode(nItr).getCosts(); + } + + /// \brief Set a node's data pointer. + /// @param nItr Node iterator. + /// @param data Pointer to node data. + /// + /// Typically used by a PBQP solver to attach data to aid in solution. + void setNodeData(NodeItr nItr, void *data) { getNode(nItr).setData(data); } + + /// \brief Get the node's data pointer. + /// @param nItr Node iterator. + /// @return Pointer to node data. + void* getNodeData(NodeItr nItr) { return getNode(nItr).getData(); } + + /// \brief Get an edge's cost matrix. + /// @param eItr Edge iterator. + /// @return Edge cost matrix. + Matrix& getEdgeCosts(EdgeItr eItr) { return getEdge(eItr).getCosts(); } + + /// \brief Get an edge's cost matrix (const version). + /// @param eItr Edge iterator. + /// @return Edge cost matrix. + const Matrix& getEdgeCosts(ConstEdgeItr eItr) const { + return getEdge(eItr).getCosts(); + } + + /// \brief Set an edge's data pointer. + /// @param eItr Edge iterator. + /// @param data Pointer to edge data. + /// + /// Typically used by a PBQP solver to attach data to aid in solution. + void setEdgeData(EdgeItr eItr, void *data) { getEdge(eItr).setData(data); } + + /// \brief Get an edge's data pointer. + /// @param eItr Edge iterator. + /// @return Pointer to edge data. + void* getEdgeData(EdgeItr eItr) { return getEdge(eItr).getData(); } + + /// \brief Get a node's degree. + /// @param nItr Node iterator. + /// @return The degree of the node. + unsigned getNodeDegree(NodeItr nItr) const { + return getNode(nItr).getDegree(); + } + + /// \brief Begin iterator for node set. + NodeItr nodesBegin() { return nodes.begin(); } + + /// \brief Begin const iterator for node set. + ConstNodeItr nodesBegin() const { return nodes.begin(); } + + /// \brief End iterator for node set. + NodeItr nodesEnd() { return nodes.end(); } + + /// \brief End const iterator for node set. + ConstNodeItr nodesEnd() const { return nodes.end(); } + + /// \brief Begin iterator for edge set. + EdgeItr edgesBegin() { return edges.begin(); } + + /// \brief End iterator for edge set. + EdgeItr edgesEnd() { return edges.end(); } + + /// \brief Get begin iterator for adjacent edge set. + /// @param nItr Node iterator. + /// @return Begin iterator for the set of edges connected to the given node. + AdjEdgeItr adjEdgesBegin(NodeItr nItr) { + return getNode(nItr).edgesBegin(); + } + + /// \brief Get end iterator for adjacent edge set. + /// @param nItr Node iterator. + /// @return End iterator for the set of edges connected to the given node. + AdjEdgeItr adjEdgesEnd(NodeItr nItr) { + return getNode(nItr).edgesEnd(); + } + + /// \brief Get the first node connected to this edge. + /// @param eItr Edge iterator. + /// @return The first node connected to the given edge. + NodeItr getEdgeNode1(EdgeItr eItr) { + return getEdge(eItr).getNode1(); + } + + /// \brief Get the second node connected to this edge. + /// @param eItr Edge iterator. + /// @return The second node connected to the given edge. + NodeItr getEdgeNode2(EdgeItr eItr) { + return getEdge(eItr).getNode2(); + } + + /// \brief Get the "other" node connected to this edge. + /// @param eItr Edge iterator. + /// @param nItr Node iterator for the "given" node. + /// @return The iterator for the "other" node connected to this edge. + NodeItr getEdgeOtherNode(EdgeItr eItr, NodeItr nItr) { + EdgeEntry &e = getEdge(eItr); + if (e.getNode1() == nItr) { + return e.getNode2(); + } // else + return e.getNode1(); + } + + /// \brief Get the edge connecting two nodes. + /// @param n1Itr First node iterator. + /// @param n2Itr Second node iterator. + /// @return An iterator for edge (n1Itr, n2Itr) if such an edge exists, + /// otherwise returns edgesEnd(). + EdgeItr findEdge(NodeItr n1Itr, NodeItr n2Itr) { + for (AdjEdgeItr aeItr = adjEdgesBegin(n1Itr), aeEnd = adjEdgesEnd(n1Itr); + aeItr != aeEnd; ++aeItr) { + if ((getEdgeNode1(*aeItr) == n2Itr) || + (getEdgeNode2(*aeItr) == n2Itr)) { + return *aeItr; + } + } + return edges.end(); + } + + /// \brief Remove a node from the graph. + /// @param nItr Node iterator. + void removeNode(NodeItr nItr) { + NodeEntry &n = getNode(nItr); + for (AdjEdgeItr itr = n.edgesBegin(), end = n.edgesEnd(); itr != end;) { + EdgeItr eItr = *itr; + ++itr; + removeEdge(eItr); + } + nodes.erase(nItr); + --numNodes; + } + + /// \brief Remove an edge from the graph. + /// @param eItr Edge iterator. + void removeEdge(EdgeItr eItr) { + EdgeEntry &e = getEdge(eItr); + NodeEntry &n1 = getNode(e.getNode1()); + NodeEntry &n2 = getNode(e.getNode2()); + n1.removeEdge(e.getNode1AEItr()); + n2.removeEdge(e.getNode2AEItr()); + edges.erase(eItr); + --numEdges; + } + + /// \brief Remove all nodes and edges from the graph. + void clear() { + nodes.clear(); + edges.clear(); + numNodes = numEdges = 0; + } + + /// \brief Print a representation of this graph in DOT format. + /// @param os Output stream to print on. + template <typename OStream> + void printDot(OStream &os) { + + os << "graph {\n"; + + for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd(); + nodeItr != nodeEnd; ++nodeItr) { + + os << " node" << nodeItr << " [ label=\"" + << nodeItr << ": " << getNodeCosts(nodeItr) << "\" ]\n"; + } + + os << " edge [ len=" << getNumNodes() << " ]\n"; + + for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd(); + edgeItr != edgeEnd; ++edgeItr) { + + os << " node" << getEdgeNode1(edgeItr) + << " -- node" << getEdgeNode2(edgeItr) + << " [ label=\""; + + const Matrix &edgeCosts = getEdgeCosts(edgeItr); + + for (unsigned i = 0; i < edgeCosts.getRows(); ++i) { + os << edgeCosts.getRowAsVector(i) << "\\n"; + } + os << "\" ]\n"; + } + os << "}\n"; + } + + }; + + class NodeItrComparator { + public: + bool operator()(Graph::NodeItr n1, Graph::NodeItr n2) const { + return &*n1 < &*n2; + } + + bool operator()(Graph::ConstNodeItr n1, Graph::ConstNodeItr n2) const { + return &*n1 < &*n2; + } + }; + + class EdgeItrCompartor { + public: + bool operator()(Graph::EdgeItr e1, Graph::EdgeItr e2) const { + return &*e1 < &*e2; + } + + bool operator()(Graph::ConstEdgeItr e1, Graph::ConstEdgeItr e2) const { + return &*e1 < &*e2; + } + }; + + void Graph::copyFrom(const Graph &other) { + std::map<Graph::ConstNodeItr, Graph::NodeItr, + NodeItrComparator> nodeMap; + + for (Graph::ConstNodeItr nItr = other.nodesBegin(), + nEnd = other.nodesEnd(); + nItr != nEnd; ++nItr) { + nodeMap[nItr] = addNode(other.getNodeCosts(nItr)); + } + + } + +} + +#endif // LLVM_CODEGEN_PBQP_GRAPH_HPP diff --git a/lib/CodeGen/PBQP/GraphBase.h b/lib/CodeGen/PBQP/GraphBase.h deleted file mode 100644 index becd98a..0000000 --- a/lib/CodeGen/PBQP/GraphBase.h +++ /dev/null @@ -1,582 +0,0 @@ -//===-- GraphBase.h - Abstract Base PBQP Graph ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Base class for PBQP Graphs. -// -//===----------------------------------------------------------------------===// - - -#ifndef LLVM_CODEGEN_PBQP_GRAPHBASE_H -#define LLVM_CODEGEN_PBQP_GRAPHBASE_H - -#include "PBQPMath.h" - -#include <list> -#include <vector> - -namespace PBQP { - -// UGLY, but I'm not sure there's a good way around this: We need to be able to -// look up a Node's "adjacent edge list" structure type before the Node type is -// fully constructed. We can enable this by pushing the choice of data type -// out into this traits class. -template <typename Graph> -class NodeBaseTraits { - public: - typedef std::list<typename Graph::EdgeIterator> AdjEdgeList; - typedef typename AdjEdgeList::iterator AdjEdgeIterator; - typedef typename AdjEdgeList::const_iterator ConstAdjEdgeIterator; -}; - -/// \brief Base for concrete graph classes. Provides a basic set of graph -/// operations which are useful for PBQP solvers. -template <typename NodeEntry, typename EdgeEntry> -class GraphBase { -private: - - typedef GraphBase<NodeEntry, EdgeEntry> ThisGraphT; - - typedef std::list<NodeEntry> NodeList; - typedef std::list<EdgeEntry> EdgeList; - - NodeList nodeList; - unsigned nodeListSize; - - EdgeList edgeList; - unsigned edgeListSize; - - GraphBase(const ThisGraphT &other) { abort(); } - void operator=(const ThisGraphT &other) { abort(); } - -public: - - /// \brief Iterates over the nodes of a graph. - typedef typename NodeList::iterator NodeIterator; - /// \brief Iterates over the nodes of a const graph. - typedef typename NodeList::const_iterator ConstNodeIterator; - /// \brief Iterates over the edges of a graph. - typedef typename EdgeList::iterator EdgeIterator; - /// \brief Iterates over the edges of a const graph. - typedef typename EdgeList::const_iterator ConstEdgeIterator; - - /// \brief Iterates over the edges attached to a node. - typedef typename NodeBaseTraits<ThisGraphT>::AdjEdgeIterator - AdjEdgeIterator; - - /// \brief Iterates over the edges attached to a node in a const graph. - typedef typename NodeBaseTraits<ThisGraphT>::ConstAdjEdgeIterator - ConstAdjEdgeIterator; - -private: - - typedef std::vector<NodeIterator> IDToNodeMap; - - IDToNodeMap idToNodeMap; - bool nodeIDsValid; - - void invalidateNodeIDs() { - if (nodeIDsValid) { - idToNodeMap.clear(); - nodeIDsValid = false; - } - } - - template <typename ItrT> - bool iteratorInRange(ItrT itr, const ItrT &begin, const ItrT &end) { - for (ItrT t = begin; t != end; ++t) { - if (itr == t) - return true; - } - - return false; - } - -protected: - - GraphBase() : nodeListSize(0), edgeListSize(0), nodeIDsValid(false) {} - - NodeEntry& getNodeEntry(const NodeIterator &nodeItr) { return *nodeItr; } - const NodeEntry& getNodeEntry(const ConstNodeIterator &nodeItr) const { - return *nodeItr; - } - - EdgeEntry& getEdgeEntry(const EdgeIterator &edgeItr) { return *edgeItr; } - const EdgeEntry& getEdgeEntry(const ConstEdgeIterator &edgeItr) const { - return *edgeItr; - } - - NodeIterator addConstructedNode(const NodeEntry &nodeEntry) { - ++nodeListSize; - - invalidateNodeIDs(); - - NodeIterator newNodeItr = nodeList.insert(nodeList.end(), nodeEntry); - - return newNodeItr; - } - - EdgeIterator addConstructedEdge(const EdgeEntry &edgeEntry) { - - assert((findEdge(edgeEntry.getNode1Itr(), edgeEntry.getNode2Itr()) - == edgeList.end()) && "Attempt to add duplicate edge."); - - ++edgeListSize; - - // Add the edge to the graph. - EdgeIterator edgeItr = edgeList.insert(edgeList.end(), edgeEntry); - - // Get a reference to the version in the graph. - EdgeEntry &newEdgeEntry = getEdgeEntry(edgeItr); - - // Node entries: - NodeEntry &node1Entry = getNodeEntry(newEdgeEntry.getNode1Itr()), - &node2Entry = getNodeEntry(newEdgeEntry.getNode2Itr()); - - // Sanity check on matrix dimensions. - assert((node1Entry.getCosts().getLength() == - newEdgeEntry.getCosts().getRows()) && - (node2Entry.getCosts().getLength() == - newEdgeEntry.getCosts().getCols()) && - "Matrix dimensions do not match cost vector dimensions."); - - // Create links between nodes and edges. - newEdgeEntry.setNode1ThisEdgeItr( - node1Entry.addAdjEdge(edgeItr)); - newEdgeEntry.setNode2ThisEdgeItr( - node2Entry.addAdjEdge(edgeItr)); - - return edgeItr; - } - -public: - - /// \brief Returns the number of nodes in this graph. - unsigned getNumNodes() const { return nodeListSize; } - - /// \brief Returns the number of edges in this graph. - unsigned getNumEdges() const { return edgeListSize; } - - /// \brief Return the cost vector for the given node. - Vector& getNodeCosts(const NodeIterator &nodeItr) { - return getNodeEntry(nodeItr).getCosts(); - } - - /// \brief Return the cost vector for the give node. - const Vector& getNodeCosts(const ConstNodeIterator &nodeItr) const { - return getNodeEntry(nodeItr).getCosts(); - } - - /// \brief Return the degree of the given node. - unsigned getNodeDegree(const NodeIterator &nodeItr) const { - return getNodeEntry(nodeItr).getDegree(); - } - - /// \brief Assigns sequential IDs to the nodes, starting at 0, which - /// remain valid until the next addition or removal of a node. - void assignNodeIDs() { - unsigned curID = 0; - idToNodeMap.resize(getNumNodes()); - for (NodeIterator nodeItr = nodesBegin(), nodeEnd = nodesEnd(); - nodeItr != nodeEnd; ++nodeItr, ++curID) { - getNodeEntry(nodeItr).setID(curID); - idToNodeMap[curID] = nodeItr; - } - nodeIDsValid = true; - } - - /// \brief Assigns sequential IDs to the nodes using the ordering of the - /// given vector. - void assignNodeIDs(const std::vector<NodeIterator> &nodeOrdering) { - assert((getNumNodes() == nodeOrdering.size()) && - "Wrong number of nodes in node ordering."); - idToNodeMap = nodeOrdering; - for (unsigned nodeID = 0; nodeID < idToNodeMap.size(); ++nodeID) { - getNodeEntry(idToNodeMap[nodeID]).setID(nodeID); - } - nodeIDsValid = true; - } - - /// \brief Returns true if valid node IDs are assigned, false otherwise. - bool areNodeIDsValid() const { return nodeIDsValid; } - - /// \brief Return the numeric ID of the given node. - /// - /// Calls to this method will result in an assertion failure if there have - /// been any node additions or removals since the last call to - /// assignNodeIDs(). - unsigned getNodeID(const ConstNodeIterator &nodeItr) const { - assert(nodeIDsValid && "Attempt to retrieve invalid ID."); - return getNodeEntry(nodeItr).getID(); - } - - /// \brief Returns the iterator associated with the given node ID. - NodeIterator getNodeItr(unsigned nodeID) { - assert(nodeIDsValid && "Attempt to retrieve iterator with invalid ID."); - return idToNodeMap[nodeID]; - } - - /// \brief Returns the iterator associated with the given node ID. - ConstNodeIterator getNodeItr(unsigned nodeID) const { - assert(nodeIDsValid && "Attempt to retrieve iterator with invalid ID."); - return idToNodeMap[nodeID]; - } - - /// \brief Removes the given node (and all attached edges) from the graph. - void removeNode(const NodeIterator &nodeItr) { - assert(iteratorInRange(nodeItr, nodeList.begin(), nodeList.end()) && - "Iterator does not belong to this graph!"); - - invalidateNodeIDs(); - - NodeEntry &nodeEntry = getNodeEntry(nodeItr); - - // We need to copy this out because it will be destroyed as the edges are - // removed. - typedef std::vector<EdgeIterator> AdjEdgeList; - typedef typename AdjEdgeList::iterator AdjEdgeListItr; - - AdjEdgeList adjEdges; - adjEdges.reserve(nodeEntry.getDegree()); - std::copy(nodeEntry.adjEdgesBegin(), nodeEntry.adjEdgesEnd(), - std::back_inserter(adjEdges)); - - // Iterate over the copied out edges and remove them from the graph. - for (AdjEdgeListItr itr = adjEdges.begin(), end = adjEdges.end(); - itr != end; ++itr) { - removeEdge(*itr); - } - - // Erase the node from the nodelist. - nodeList.erase(nodeItr); - --nodeListSize; - } - - NodeIterator nodesBegin() { return nodeList.begin(); } - ConstNodeIterator nodesBegin() const { return nodeList.begin(); } - NodeIterator nodesEnd() { return nodeList.end(); } - ConstNodeIterator nodesEnd() const { return nodeList.end(); } - - AdjEdgeIterator adjEdgesBegin(const NodeIterator &nodeItr) { - return getNodeEntry(nodeItr).adjEdgesBegin(); - } - - ConstAdjEdgeIterator adjEdgesBegin(const ConstNodeIterator &nodeItr) const { - return getNodeEntry(nodeItr).adjEdgesBegin(); - } - - AdjEdgeIterator adjEdgesEnd(const NodeIterator &nodeItr) { - return getNodeEntry(nodeItr).adjEdgesEnd(); - } - - ConstAdjEdgeIterator adjEdgesEnd(const ConstNodeIterator &nodeItr) const { - getNodeEntry(nodeItr).adjEdgesEnd(); - } - - EdgeIterator findEdge(const NodeIterator &node1Itr, - const NodeIterator &node2Itr) { - - for (AdjEdgeIterator adjEdgeItr = adjEdgesBegin(node1Itr), - adjEdgeEnd = adjEdgesEnd(node1Itr); - adjEdgeItr != adjEdgeEnd; ++adjEdgeItr) { - if ((getEdgeNode1Itr(*adjEdgeItr) == node2Itr) || - (getEdgeNode2Itr(*adjEdgeItr) == node2Itr)) { - return *adjEdgeItr; - } - } - - return edgeList.end(); - } - - ConstEdgeIterator findEdge(const ConstNodeIterator &node1Itr, - const ConstNodeIterator &node2Itr) const { - - for (ConstAdjEdgeIterator adjEdgeItr = adjEdgesBegin(node1Itr), - adjEdgeEnd = adjEdgesEnd(node1Itr); - adjEdgeItr != adjEdgeEnd; ++adjEdgeItr) { - if ((getEdgeNode1Itr(*adjEdgeItr) == node2Itr) || - (getEdgeNode2Itr(*adjEdgeItr) == node2Itr)) { - return *adjEdgeItr; - } - } - - return edgeList.end(); - } - - Matrix& getEdgeCosts(const EdgeIterator &edgeItr) { - return getEdgeEntry(edgeItr).getCosts(); - } - - const Matrix& getEdgeCosts(const ConstEdgeIterator &edgeItr) const { - return getEdgeEntry(edgeItr).getCosts(); - } - - NodeIterator getEdgeNode1Itr(const EdgeIterator &edgeItr) { - return getEdgeEntry(edgeItr).getNode1Itr(); - } - - ConstNodeIterator getEdgeNode1Itr(const ConstEdgeIterator &edgeItr) const { - return getEdgeEntry(edgeItr).getNode1Itr(); - } - - NodeIterator getEdgeNode2Itr(const EdgeIterator &edgeItr) { - return getEdgeEntry(edgeItr).getNode2Itr(); - } - - ConstNodeIterator getEdgeNode2Itr(const ConstEdgeIterator &edgeItr) const { - return getEdgeEntry(edgeItr).getNode2Itr(); - } - - NodeIterator getEdgeOtherNode(const EdgeIterator &edgeItr, - const NodeIterator &nodeItr) { - - EdgeEntry &edgeEntry = getEdgeEntry(edgeItr); - if (nodeItr == edgeEntry.getNode1Itr()) { - return edgeEntry.getNode2Itr(); - } - //else - return edgeEntry.getNode1Itr(); - } - - ConstNodeIterator getEdgeOtherNode(const ConstEdgeIterator &edgeItr, - const ConstNodeIterator &nodeItr) const { - - const EdgeEntry &edgeEntry = getEdgeEntry(edgeItr); - if (nodeItr == edgeEntry.getNode1Itr()) { - return edgeEntry.getNode2Itr(); - } - //else - return edgeEntry.getNode1Itr(); - } - - void removeEdge(const EdgeIterator &edgeItr) { - assert(iteratorInRange(edgeItr, edgeList.begin(), edgeList.end()) && - "Iterator does not belong to this graph!"); - - --edgeListSize; - - // Get the edge entry. - EdgeEntry &edgeEntry = getEdgeEntry(edgeItr); - - // Get the nodes entry. - NodeEntry &node1Entry(getNodeEntry(edgeEntry.getNode1Itr())), - &node2Entry(getNodeEntry(edgeEntry.getNode2Itr())); - - // Disconnect the edge from the nodes. - node1Entry.removeAdjEdge(edgeEntry.getNode1ThisEdgeItr()); - node2Entry.removeAdjEdge(edgeEntry.getNode2ThisEdgeItr()); - - // Remove the edge from the graph. - edgeList.erase(edgeItr); - } - - EdgeIterator edgesBegin() { return edgeList.begin(); } - ConstEdgeIterator edgesBegin() const { return edgeList.begin(); } - EdgeIterator edgesEnd() { return edgeList.end(); } - ConstEdgeIterator edgesEnd() const { return edgeList.end(); } - - void clear() { - nodeList.clear(); - nodeListSize = 0; - edgeList.clear(); - edgeListSize = 0; - idToNodeMap.clear(); - } - - template <typename OStream> - void printDot(OStream &os) const { - - assert(areNodeIDsValid() && - "Cannot print a .dot of a graph unless IDs have been assigned."); - - os << "graph {\n"; - - for (ConstNodeIterator nodeItr = nodesBegin(), nodeEnd = nodesEnd(); - nodeItr != nodeEnd; ++nodeItr) { - - os << " node" << getNodeID(nodeItr) << " [ label=\"" - << getNodeID(nodeItr) << ": " << getNodeCosts(nodeItr) << "\" ]\n"; - } - - os << " edge [ len=" << getNumNodes() << " ]\n"; - - for (ConstEdgeIterator edgeItr = edgesBegin(), edgeEnd = edgesEnd(); - edgeItr != edgeEnd; ++edgeItr) { - - os << " node" << getNodeID(getEdgeNode1Itr(edgeItr)) - << " -- node" << getNodeID(getEdgeNode2Itr(edgeItr)) - << " [ label=\""; - - const Matrix &edgeCosts = getEdgeCosts(edgeItr); - - for (unsigned i = 0; i < edgeCosts.getRows(); ++i) { - os << edgeCosts.getRowAsVector(i) << "\\n"; - } - - os << "\" ]\n"; - } - - os << "}\n"; - } - - template <typename OStream> - void printDot(OStream &os) { - if (!areNodeIDsValid()) { - assignNodeIDs(); - } - - const_cast<const ThisGraphT*>(this)->printDot(os); - } - - template <typename OStream> - void dumpTo(OStream &os) const { - typedef ConstNodeIterator ConstNodeID; - - assert(areNodeIDsValid() && - "Cannot dump a graph unless IDs have been assigned."); - - for (ConstNodeIterator nItr = nodesBegin(), nEnd = nodesEnd(); - nItr != nEnd; ++nItr) { - os << getNodeID(nItr) << "\n"; - } - - unsigned edgeNumber = 1; - for (ConstEdgeIterator eItr = edgesBegin(), eEnd = edgesEnd(); - eItr != eEnd; ++eItr) { - - os << edgeNumber++ << ": { " - << getNodeID(getEdgeNode1Itr(eItr)) << ", " - << getNodeID(getEdgeNode2Itr(eItr)) << " }\n"; - } - - } - - template <typename OStream> - void dumpTo(OStream &os) { - if (!areNodeIDsValid()) { - assignNodeIDs(); - } - - const_cast<const ThisGraphT*>(this)->dumpTo(os); - } - -}; - -/// \brief Provides a base from which to derive nodes for GraphBase. -template <typename NodeImpl, typename EdgeImpl> -class NodeBase { -private: - - typedef GraphBase<NodeImpl, EdgeImpl> GraphBaseT; - typedef NodeBaseTraits<GraphBaseT> ThisNodeBaseTraits; - -public: - typedef typename GraphBaseT::EdgeIterator EdgeIterator; - -private: - typedef typename ThisNodeBaseTraits::AdjEdgeList AdjEdgeList; - - unsigned degree, id; - Vector costs; - AdjEdgeList adjEdges; - - void operator=(const NodeBase& other) { - assert(false && "Can't assign NodeEntrys."); - } - -public: - - typedef typename ThisNodeBaseTraits::AdjEdgeIterator AdjEdgeIterator; - typedef typename ThisNodeBaseTraits::ConstAdjEdgeIterator - ConstAdjEdgeIterator; - - NodeBase(const Vector &costs) : degree(0), costs(costs) { - assert((costs.getLength() > 0) && "Can't have zero-length cost vector."); - } - - Vector& getCosts() { return costs; } - const Vector& getCosts() const { return costs; } - - unsigned getDegree() const { return degree; } - - void setID(unsigned id) { this->id = id; } - unsigned getID() const { return id; } - - AdjEdgeIterator addAdjEdge(const EdgeIterator &edgeItr) { - ++degree; - return adjEdges.insert(adjEdges.end(), edgeItr); - } - - void removeAdjEdge(const AdjEdgeIterator &adjEdgeItr) { - --degree; - adjEdges.erase(adjEdgeItr); - } - - AdjEdgeIterator adjEdgesBegin() { return adjEdges.begin(); } - ConstAdjEdgeIterator adjEdgesBegin() const { return adjEdges.begin(); } - AdjEdgeIterator adjEdgesEnd() { return adjEdges.end(); } - ConstAdjEdgeIterator adjEdgesEnd() const { return adjEdges.end(); } - -}; - -template <typename NodeImpl, typename EdgeImpl> -class EdgeBase { -public: - typedef typename GraphBase<NodeImpl, EdgeImpl>::NodeIterator NodeIterator; - typedef typename GraphBase<NodeImpl, EdgeImpl>::EdgeIterator EdgeIterator; - - typedef typename NodeImpl::AdjEdgeIterator NodeAdjEdgeIterator; - -private: - - NodeIterator node1Itr, node2Itr; - NodeAdjEdgeIterator node1ThisEdgeItr, node2ThisEdgeItr; - Matrix costs; - - void operator=(const EdgeBase &other) { - assert(false && "Can't assign EdgeEntrys."); - } - -public: - - EdgeBase(const NodeIterator &node1Itr, const NodeIterator &node2Itr, - const Matrix &costs) : - node1Itr(node1Itr), node2Itr(node2Itr), costs(costs) { - - assert((costs.getRows() > 0) && (costs.getCols() > 0) && - "Can't have zero-dimensioned cost matrices"); - } - - Matrix& getCosts() { return costs; } - const Matrix& getCosts() const { return costs; } - - const NodeIterator& getNode1Itr() const { return node1Itr; } - const NodeIterator& getNode2Itr() const { return node2Itr; } - - void setNode1ThisEdgeItr(const NodeAdjEdgeIterator &node1ThisEdgeItr) { - this->node1ThisEdgeItr = node1ThisEdgeItr; - } - - const NodeAdjEdgeIterator& getNode1ThisEdgeItr() const { - return node1ThisEdgeItr; - } - - void setNode2ThisEdgeItr(const NodeAdjEdgeIterator &node2ThisEdgeItr) { - this->node2ThisEdgeItr = node2ThisEdgeItr; - } - - const NodeAdjEdgeIterator& getNode2ThisEdgeItr() const { - return node2ThisEdgeItr; - } - -}; - - -} - -#endif // LLVM_CODEGEN_PBQP_GRAPHBASE_HPP diff --git a/lib/CodeGen/PBQP/HeuristicBase.h b/lib/CodeGen/PBQP/HeuristicBase.h new file mode 100644 index 0000000..3bb24e1 --- /dev/null +++ b/lib/CodeGen/PBQP/HeuristicBase.h @@ -0,0 +1,242 @@ +//===-- HeuristcBase.h --- Heuristic base class for PBQP --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQP_HEURISTICBASE_H +#define LLVM_CODEGEN_PBQP_HEURISTICBASE_H + +#include "HeuristicSolver.h" + +namespace PBQP { + + /// \brief Abstract base class for heuristic implementations. + /// + /// This class provides a handy base for heuristic implementations with common + /// solver behaviour implemented for a number of methods. + /// + /// To implement your own heuristic using this class as a base you'll have to + /// implement, as a minimum, the following methods: + /// <ul> + /// <li> void addToHeuristicList(Graph::NodeItr) : Add a node to the + /// heuristic reduction list. + /// <li> void heuristicReduce() : Perform a single heuristic reduction. + /// <li> void preUpdateEdgeCosts(Graph::EdgeItr) : Handle the (imminent) + /// change to the cost matrix on the given edge (by R2). + /// <li> void postUpdateEdgeCostts(Graph::EdgeItr) : Handle the new + /// costs on the given edge. + /// <li> void handleAddEdge(Graph::EdgeItr) : Handle the addition of a new + /// edge into the PBQP graph (by R2). + /// <li> void handleRemoveEdge(Graph::EdgeItr, Graph::NodeItr) : Handle the + /// disconnection of the given edge from the given node. + /// <li> A constructor for your derived class : to pass back a reference to + /// the solver which is using this heuristic. + /// </ul> + /// + /// These methods are implemented in this class for documentation purposes, + /// but will assert if called. + /// + /// Note that this class uses the curiously recursive template idiom to + /// forward calls to the derived class. These methods need not be made + /// virtual, and indeed probably shouldn't for performance reasons. + /// + /// You'll also need to provide NodeData and EdgeData structs in your class. + /// These can be used to attach data relevant to your heuristic to each + /// node/edge in the PBQP graph. + + template <typename HImpl> + class HeuristicBase { + private: + + typedef std::list<Graph::NodeItr> OptimalList; + + HeuristicSolverImpl<HImpl> &s; + Graph &g; + OptimalList optimalList; + + // Return a reference to the derived heuristic. + HImpl& impl() { return static_cast<HImpl&>(*this); } + + // Add the given node to the optimal reductions list. Keep an iterator to + // its location for fast removal. + void addToOptimalReductionList(Graph::NodeItr nItr) { + optimalList.insert(optimalList.end(), nItr); + } + + public: + + /// \brief Construct an instance with a reference to the given solver. + /// @param solver The solver which is using this heuristic instance. + HeuristicBase(HeuristicSolverImpl<HImpl> &solver) + : s(solver), g(s.getGraph()) { } + + /// \brief Get the solver which is using this heuristic instance. + /// @return The solver which is using this heuristic instance. + /// + /// You can use this method to get access to the solver in your derived + /// heuristic implementation. + HeuristicSolverImpl<HImpl>& getSolver() { return s; } + + /// \brief Get the graph representing the problem to be solved. + /// @return The graph representing the problem to be solved. + Graph& getGraph() { return g; } + + /// \brief Tell the solver to simplify the graph before the reduction phase. + /// @return Whether or not the solver should run a simplification phase + /// prior to the main setup and reduction. + /// + /// HeuristicBase returns true from this method as it's a sensible default, + /// however you can over-ride it in your derived class if you want different + /// behaviour. + bool solverRunSimplify() const { return true; } + + /// \brief Decide whether a node should be optimally or heuristically + /// reduced. + /// @return Whether or not the given node should be listed for optimal + /// reduction (via R0, R1 or R2). + /// + /// HeuristicBase returns true for any node with degree less than 3. This is + /// sane and sensible for many situations, but not all. You can over-ride + /// this method in your derived class if you want a different selection + /// criteria. Note however that your criteria for selecting optimal nodes + /// should be <i>at least</i> as strong as this. I.e. Nodes of degree 3 or + /// higher should not be selected under any circumstances. + bool shouldOptimallyReduce(Graph::NodeItr nItr) { + if (g.getNodeDegree(nItr) < 3) + return true; + // else + return false; + } + + /// \brief Add the given node to the list of nodes to be optimally reduced. + /// @return nItr Node iterator to be added. + /// + /// You probably don't want to over-ride this, except perhaps to record + /// statistics before calling this implementation. HeuristicBase relies on + /// its behaviour. + void addToOptimalReduceList(Graph::NodeItr nItr) { + optimalList.push_back(nItr); + } + + /// \brief Initialise the heuristic. + /// + /// HeuristicBase iterates over all nodes in the problem and adds them to + /// the appropriate list using addToOptimalReduceList or + /// addToHeuristicReduceList based on the result of shouldOptimallyReduce. + /// + /// This behaviour should be fine for most situations. + void setup() { + for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); + nItr != nEnd; ++nItr) { + if (impl().shouldOptimallyReduce(nItr)) { + addToOptimalReduceList(nItr); + } else { + impl().addToHeuristicReduceList(nItr); + } + } + } + + /// \brief Optimally reduce one of the nodes in the optimal reduce list. + /// @return True if a reduction takes place, false if the optimal reduce + /// list is empty. + /// + /// Selects a node from the optimal reduce list and removes it, applying + /// R0, R1 or R2 as appropriate based on the selected node's degree. + bool optimalReduce() { + if (optimalList.empty()) + return false; + + Graph::NodeItr nItr = optimalList.front(); + optimalList.pop_front(); + + switch (s.getSolverDegree(nItr)) { + case 0: s.applyR0(nItr); break; + case 1: s.applyR1(nItr); break; + case 2: s.applyR2(nItr); break; + default: assert(false && + "Optimal reductions of degree > 2 nodes is invalid."); + } + + return true; + } + + /// \brief Perform the PBQP reduction process. + /// + /// Reduces the problem to the empty graph by repeated application of the + /// reduction rules R0, R1, R2 and RN. + /// R0, R1 or R2 are always applied if possible before RN is used. + void reduce() { + bool finished = false; + + while (!finished) { + if (!optimalReduce()) + if (!impl().heuristicReduce()) + finished = true; + } + } + + /// \brief Add a node to the heuristic reduce list. + /// @param nItr Node iterator to add to the heuristic reduce list. + void addToHeuristicList(Graph::NodeItr nItr) { + assert(false && "Must be implemented in derived class."); + } + + /// \brief Heuristically reduce one of the nodes in the heuristic + /// reduce list. + /// @return True if a reduction takes place, false if the heuristic reduce + /// list is empty. + void heuristicReduce() { + assert(false && "Must be implemented in derived class."); + } + + /// \brief Prepare a change in the costs on the given edge. + /// @param eItr Edge iterator. + void preUpdateEdgeCosts(Graph::EdgeItr eItr) { + assert(false && "Must be implemented in derived class."); + } + + /// \brief Handle the change in the costs on the given edge. + /// @param eItr Edge iterator. + void postUpdateEdgeCostts(Graph::EdgeItr eItr) { + assert(false && "Must be implemented in derived class."); + } + + /// \brief Handle the addition of a new edge into the PBQP graph. + /// @param eItr Edge iterator for the added edge. + void handleAddEdge(Graph::EdgeItr eItr) { + assert(false && "Must be implemented in derived class."); + } + + /// \brief Handle disconnection of an edge from a node. + /// @param eItr Edge iterator for edge being disconnected. + /// @param nItr Node iterator for the node being disconnected from. + /// + /// Edges are frequently removed due to the removal of a node. This + /// method allows for the effect to be computed only for the remaining + /// node in the graph. + void handleRemoveEdge(Graph::EdgeItr eItr, Graph::NodeItr nItr) { + assert(false && "Must be implemented in derived class."); + } + + /// \brief Clean up any structures used by HeuristicBase. + /// + /// At present this just performs a sanity check: that the optimal reduce + /// list is empty now that reduction has completed. + /// + /// If your derived class has more complex structures which need tearing + /// down you should over-ride this method but include a call back to this + /// implementation. + void cleanup() { + assert(optimalList.empty() && "Nodes left over in optimal reduce list?"); + } + + }; + +} + + +#endif // LLVM_CODEGEN_PBQP_HEURISTICBASE_H diff --git a/lib/CodeGen/PBQP/HeuristicSolver.h b/lib/CodeGen/PBQP/HeuristicSolver.h index f78a58a..c156264 100644 --- a/lib/CodeGen/PBQP/HeuristicSolver.h +++ b/lib/CodeGen/PBQP/HeuristicSolver.h @@ -1,4 +1,4 @@ -//===-- HeuristicSolver.h - Heuristic PBQP Solver ---------------*- C++ -*-===// +//===-- HeuristicSolver.h - Heuristic PBQP Solver --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -9,780 +9,598 @@ // // Heuristic PBQP solver. This solver is able to perform optimal reductions for // nodes of degree 0, 1 or 2. For nodes of degree >2 a plugable heuristic is -// used to to select a node for reduction. +// used to select a node for reduction. // //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H #define LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H -#include "Solver.h" -#include "AnnotatedGraph.h" -#include "llvm/Support/raw_ostream.h" +#include "Graph.h" +#include "Solution.h" +#include <vector> #include <limits> namespace PBQP { -/// \brief Important types for the HeuristicSolverImpl. -/// -/// Declared seperately to allow access to heuristic classes before the solver -/// is fully constructed. -template <typename HeuristicNodeData, typename HeuristicEdgeData> -class HSITypes { -public: - - class NodeData; - class EdgeData; - - typedef AnnotatedGraph<NodeData, EdgeData> SolverGraph; - typedef typename SolverGraph::NodeIterator GraphNodeIterator; - typedef typename SolverGraph::EdgeIterator GraphEdgeIterator; - typedef typename SolverGraph::AdjEdgeIterator GraphAdjEdgeIterator; - - typedef std::list<GraphNodeIterator> NodeList; - typedef typename NodeList::iterator NodeListIterator; - - typedef std::vector<GraphNodeIterator> NodeStack; - typedef typename NodeStack::iterator NodeStackIterator; - - class NodeData { - friend class EdgeData; - + /// \brief Heuristic PBQP solver implementation. + /// + /// This class should usually be created (and destroyed) indirectly via a call + /// to HeuristicSolver<HImpl>::solve(Graph&). + /// See the comments for HeuristicSolver. + /// + /// HeuristicSolverImpl provides the R0, R1 and R2 reduction rules, + /// backpropagation phase, and maintains the internal copy of the graph on + /// which the reduction is carried out (the original being kept to facilitate + /// backpropagation). + template <typename HImpl> + class HeuristicSolverImpl { private: - typedef std::list<GraphEdgeIterator> LinksList; + typedef typename HImpl::NodeData HeuristicNodeData; + typedef typename HImpl::EdgeData HeuristicEdgeData; - unsigned numLinks; - LinksList links, solvedLinks; - NodeListIterator bucketItr; - HeuristicNodeData heuristicData; + typedef std::list<Graph::EdgeItr> SolverEdges; public: - - typedef typename LinksList::iterator AdjLinkIterator; + + /// \brief Iterator type for edges in the solver graph. + typedef SolverEdges::iterator SolverEdgeItr; private: - AdjLinkIterator addLink(const GraphEdgeIterator &edgeItr) { - ++numLinks; - return links.insert(links.end(), edgeItr); - } + class NodeData { + public: + NodeData() : solverDegree(0) {} - void delLink(const AdjLinkIterator &adjLinkItr) { - --numLinks; - links.erase(adjLinkItr); - } + HeuristicNodeData& getHeuristicData() { return hData; } - public: - - NodeData() : numLinks(0) {} - - unsigned getLinkDegree() const { return numLinks; } - - HeuristicNodeData& getHeuristicData() { return heuristicData; } - const HeuristicNodeData& getHeuristicData() const { - return heuristicData; - } + SolverEdgeItr addSolverEdge(Graph::EdgeItr eItr) { + ++solverDegree; + return solverEdges.insert(solverEdges.end(), eItr); + } - void setBucketItr(const NodeListIterator &bucketItr) { - this->bucketItr = bucketItr; - } + void removeSolverEdge(SolverEdgeItr seItr) { + --solverDegree; + solverEdges.erase(seItr); + } - const NodeListIterator& getBucketItr() const { - return bucketItr; - } + SolverEdgeItr solverEdgesBegin() { return solverEdges.begin(); } + SolverEdgeItr solverEdgesEnd() { return solverEdges.end(); } + unsigned getSolverDegree() const { return solverDegree; } + void clearSolverEdges() { + solverDegree = 0; + solverEdges.clear(); + } + + private: + HeuristicNodeData hData; + unsigned solverDegree; + SolverEdges solverEdges; + }; + + class EdgeData { + public: + HeuristicEdgeData& getHeuristicData() { return hData; } + + void setN1SolverEdgeItr(SolverEdgeItr n1SolverEdgeItr) { + this->n1SolverEdgeItr = n1SolverEdgeItr; + } - AdjLinkIterator adjLinksBegin() { - return links.begin(); - } + SolverEdgeItr getN1SolverEdgeItr() { return n1SolverEdgeItr; } - AdjLinkIterator adjLinksEnd() { - return links.end(); - } + void setN2SolverEdgeItr(SolverEdgeItr n2SolverEdgeItr){ + this->n2SolverEdgeItr = n2SolverEdgeItr; + } - void addSolvedLink(const GraphEdgeIterator &solvedLinkItr) { - solvedLinks.push_back(solvedLinkItr); - } + SolverEdgeItr getN2SolverEdgeItr() { return n2SolverEdgeItr; } - AdjLinkIterator solvedLinksBegin() { - return solvedLinks.begin(); - } + private: - AdjLinkIterator solvedLinksEnd() { - return solvedLinks.end(); - } + HeuristicEdgeData hData; + SolverEdgeItr n1SolverEdgeItr, n2SolverEdgeItr; + }; - }; + Graph &g; + HImpl h; + Solution s; + std::vector<Graph::NodeItr> stack; - class EdgeData { - private: + typedef std::list<NodeData> NodeDataList; + NodeDataList nodeDataList; - SolverGraph &g; - GraphNodeIterator node1Itr, node2Itr; - HeuristicEdgeData heuristicData; - typename NodeData::AdjLinkIterator node1ThisEdgeItr, node2ThisEdgeItr; + typedef std::list<EdgeData> EdgeDataList; + EdgeDataList edgeDataList; public: - EdgeData(SolverGraph &g) : g(g) {} - - HeuristicEdgeData& getHeuristicData() { return heuristicData; } - const HeuristicEdgeData& getHeuristicData() const { - return heuristicData; - } - - void setup(const GraphEdgeIterator &thisEdgeItr) { - node1Itr = g.getEdgeNode1Itr(thisEdgeItr); - node2Itr = g.getEdgeNode2Itr(thisEdgeItr); - - node1ThisEdgeItr = g.getNodeData(node1Itr).addLink(thisEdgeItr); - node2ThisEdgeItr = g.getNodeData(node2Itr).addLink(thisEdgeItr); - } - - void unlink() { - g.getNodeData(node1Itr).delLink(node1ThisEdgeItr); - g.getNodeData(node2Itr).delLink(node2ThisEdgeItr); - } - - }; - -}; - -template <typename Heuristic> -class HeuristicSolverImpl { -public: - // Typedefs to make life easier: - typedef HSITypes<typename Heuristic::NodeData, - typename Heuristic::EdgeData> HSIT; - typedef typename HSIT::SolverGraph SolverGraph; - typedef typename HSIT::NodeData NodeData; - typedef typename HSIT::EdgeData EdgeData; - typedef typename HSIT::GraphNodeIterator GraphNodeIterator; - typedef typename HSIT::GraphEdgeIterator GraphEdgeIterator; - typedef typename HSIT::GraphAdjEdgeIterator GraphAdjEdgeIterator; - - typedef typename HSIT::NodeList NodeList; - typedef typename HSIT::NodeListIterator NodeListIterator; - - typedef std::vector<GraphNodeIterator> NodeStack; - typedef typename NodeStack::iterator NodeStackIterator; - - /// \brief Constructor, which performs all the actual solver work. - HeuristicSolverImpl(const SimpleGraph &orig) : - solution(orig.getNumNodes(), true) - { - copyGraph(orig); - simplify(); - setup(); - computeSolution(); - computeSolutionCost(orig); - } - - /// \brief Returns the graph for this solver. - SolverGraph& getGraph() { return g; } - - /// \brief Return the solution found by this solver. - const Solution& getSolution() const { return solution; } - -private: - - /// \brief Add the given node to the appropriate bucket for its link - /// degree. - void addToBucket(const GraphNodeIterator &nodeItr) { - NodeData &nodeData = g.getNodeData(nodeItr); - - switch (nodeData.getLinkDegree()) { - case 0: nodeData.setBucketItr( - r0Bucket.insert(r0Bucket.end(), nodeItr)); - break; - case 1: nodeData.setBucketItr( - r1Bucket.insert(r1Bucket.end(), nodeItr)); - break; - case 2: nodeData.setBucketItr( - r2Bucket.insert(r2Bucket.end(), nodeItr)); - break; - default: heuristic.addToRNBucket(nodeItr); - break; - } - } - - /// \brief Remove the given node from the appropriate bucket for its link - /// degree. - void removeFromBucket(const GraphNodeIterator &nodeItr) { - NodeData &nodeData = g.getNodeData(nodeItr); - - switch (nodeData.getLinkDegree()) { - case 0: r0Bucket.erase(nodeData.getBucketItr()); break; - case 1: r1Bucket.erase(nodeData.getBucketItr()); break; - case 2: r2Bucket.erase(nodeData.getBucketItr()); break; - default: heuristic.removeFromRNBucket(nodeItr); break; - } - } - -public: - - /// \brief Add a link. - void addLink(const GraphEdgeIterator &edgeItr) { - g.getEdgeData(edgeItr).setup(edgeItr); - - if ((g.getNodeData(g.getEdgeNode1Itr(edgeItr)).getLinkDegree() > 2) || - (g.getNodeData(g.getEdgeNode2Itr(edgeItr)).getLinkDegree() > 2)) { - heuristic.handleAddLink(edgeItr); - } - } - - /// \brief Remove link, update info for node. - /// - /// Only updates information for the given node, since usually the other - /// is about to be removed. - void removeLink(const GraphEdgeIterator &edgeItr, - const GraphNodeIterator &nodeItr) { - - if (g.getNodeData(nodeItr).getLinkDegree() > 2) { - heuristic.handleRemoveLink(edgeItr, nodeItr); - } - g.getEdgeData(edgeItr).unlink(); - } - - /// \brief Remove link, update info for both nodes. Useful for R2 only. - void removeLinkR2(const GraphEdgeIterator &edgeItr) { - GraphNodeIterator node1Itr = g.getEdgeNode1Itr(edgeItr); - - if (g.getNodeData(node1Itr).getLinkDegree() > 2) { - heuristic.handleRemoveLink(edgeItr, node1Itr); + /// \brief Construct a heuristic solver implementation to solve the given + /// graph. + /// @param g The graph representing the problem instance to be solved. + HeuristicSolverImpl(Graph &g) : g(g), h(*this) {} + + /// \brief Get the graph being solved by this solver. + /// @return The graph representing the problem instance being solved by this + /// solver. + Graph& getGraph() { return g; } + + /// \brief Get the heuristic data attached to the given node. + /// @param nItr Node iterator. + /// @return The heuristic data attached to the given node. + HeuristicNodeData& getHeuristicNodeData(Graph::NodeItr nItr) { + return getSolverNodeData(nItr).getHeuristicData(); + } + + /// \brief Get the heuristic data attached to the given edge. + /// @param eItr Edge iterator. + /// @return The heuristic data attached to the given node. + HeuristicEdgeData& getHeuristicEdgeData(Graph::EdgeItr eItr) { + return getSolverEdgeData(eItr).getHeuristicData(); + } + + /// \brief Begin iterator for the set of edges adjacent to the given node in + /// the solver graph. + /// @param nItr Node iterator. + /// @return Begin iterator for the set of edges adjacent to the given node + /// in the solver graph. + SolverEdgeItr solverEdgesBegin(Graph::NodeItr nItr) { + return getSolverNodeData(nItr).solverEdgesBegin(); + } + + /// \brief End iterator for the set of edges adjacent to the given node in + /// the solver graph. + /// @param nItr Node iterator. + /// @return End iterator for the set of edges adjacent to the given node in + /// the solver graph. + SolverEdgeItr solverEdgesEnd(Graph::NodeItr nItr) { + return getSolverNodeData(nItr).solverEdgesEnd(); + } + + /// \brief Remove a node from the solver graph. + /// @param eItr Edge iterator for edge to be removed. + /// + /// Does <i>not</i> notify the heuristic of the removal. That should be + /// done manually if necessary. + void removeSolverEdge(Graph::EdgeItr eItr) { + EdgeData &eData = getSolverEdgeData(eItr); + NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eItr)), + &n2Data = getSolverNodeData(g.getEdgeNode2(eItr)); + + n1Data.removeSolverEdge(eData.getN1SolverEdgeItr()); + n2Data.removeSolverEdge(eData.getN2SolverEdgeItr()); + } + + /// \brief Compute a solution to the PBQP problem instance with which this + /// heuristic solver was constructed. + /// @return A solution to the PBQP problem. + /// + /// Performs the full PBQP heuristic solver algorithm, including setup, + /// calls to the heuristic (which will call back to the reduction rules in + /// this class), and cleanup. + Solution computeSolution() { + setup(); + h.setup(); + h.reduce(); + backpropagate(); + h.cleanup(); + cleanup(); + return s; + } + + /// \brief Add to the end of the stack. + /// @param nItr Node iterator to add to the reduction stack. + void pushToStack(Graph::NodeItr nItr) { + getSolverNodeData(nItr).clearSolverEdges(); + stack.push_back(nItr); + } + + /// \brief Returns the solver degree of the given node. + /// @param nItr Node iterator for which degree is requested. + /// @return Node degree in the <i>solver</i> graph (not the original graph). + unsigned getSolverDegree(Graph::NodeItr nItr) { + return getSolverNodeData(nItr).getSolverDegree(); + } + + /// \brief Set the solution of the given node. + /// @param nItr Node iterator to set solution for. + /// @param selection Selection for node. + void setSolution(const Graph::NodeItr &nItr, unsigned selection) { + s.setSelection(nItr, selection); + + for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nItr), + aeEnd = g.adjEdgesEnd(nItr); + aeItr != aeEnd; ++aeItr) { + Graph::EdgeItr eItr(*aeItr); + Graph::NodeItr anItr(g.getEdgeOtherNode(eItr, nItr)); + getSolverNodeData(anItr).addSolverEdge(eItr); + } } - removeLink(edgeItr, g.getEdgeNode2Itr(edgeItr)); - } - - /// \brief Removes all links connected to the given node. - void unlinkNode(const GraphNodeIterator &nodeItr) { - NodeData &nodeData = g.getNodeData(nodeItr); - - typedef std::vector<GraphEdgeIterator> TempEdgeList; - TempEdgeList edgesToUnlink; - edgesToUnlink.reserve(nodeData.getLinkDegree()); + /// \brief Apply rule R0. + /// @param nItr Node iterator for node to apply R0 to. + /// + /// Node will be automatically pushed to the solver stack. + void applyR0(Graph::NodeItr nItr) { + assert(getSolverNodeData(nItr).getSolverDegree() == 0 && + "R0 applied to node with degree != 0."); - // Copy adj edges into a temp vector. We want to destroy them during - // the unlink, and we can't do that while we're iterating over them. - std::copy(nodeData.adjLinksBegin(), nodeData.adjLinksEnd(), - std::back_inserter(edgesToUnlink)); - - for (typename TempEdgeList::iterator - edgeItr = edgesToUnlink.begin(), edgeEnd = edgesToUnlink.end(); - edgeItr != edgeEnd; ++edgeItr) { - - GraphNodeIterator otherNode = g.getEdgeOtherNode(*edgeItr, nodeItr); - - removeFromBucket(otherNode); - removeLink(*edgeItr, otherNode); - addToBucket(otherNode); + // Nothing to do. Just push the node onto the reduction stack. + pushToStack(nItr); } - } - - /// \brief Push the given node onto the stack to be solved with - /// backpropagation. - void pushStack(const GraphNodeIterator &nodeItr) { - stack.push_back(nodeItr); - } - - /// \brief Set the solution of the given node. - void setSolution(const GraphNodeIterator &nodeItr, unsigned solIndex) { - solution.setSelection(g.getNodeID(nodeItr), solIndex); - - for (GraphAdjEdgeIterator adjEdgeItr = g.adjEdgesBegin(nodeItr), - adjEdgeEnd = g.adjEdgesEnd(nodeItr); - adjEdgeItr != adjEdgeEnd; ++adjEdgeItr) { - GraphEdgeIterator edgeItr(*adjEdgeItr); - GraphNodeIterator adjNodeItr(g.getEdgeOtherNode(edgeItr, nodeItr)); - g.getNodeData(adjNodeItr).addSolvedLink(edgeItr); - } - } - -private: - SolverGraph g; - Heuristic heuristic; - Solution solution; + /// \brief Apply rule R1. + /// @param nItr Node iterator for node to apply R1 to. + /// + /// Node will be automatically pushed to the solver stack. + void applyR1(Graph::NodeItr xnItr) { + NodeData &nd = getSolverNodeData(xnItr); + assert(nd.getSolverDegree() == 1 && + "R1 applied to node with degree != 1."); - NodeList r0Bucket, - r1Bucket, - r2Bucket; + Graph::EdgeItr eItr = *nd.solverEdgesBegin(); - NodeStack stack; - - // Copy the SimpleGraph into an annotated graph which we can use for reduction. - void copyGraph(const SimpleGraph &orig) { - - assert((g.getNumEdges() == 0) && (g.getNumNodes() == 0) && - "Graph should be empty prior to solver setup."); - - assert(orig.areNodeIDsValid() && - "Cannot copy from a graph with invalid node IDs."); - - std::vector<GraphNodeIterator> newNodeItrs; - - for (unsigned nodeID = 0; nodeID < orig.getNumNodes(); ++nodeID) { - newNodeItrs.push_back( - g.addNode(orig.getNodeCosts(orig.getNodeItr(nodeID)), NodeData())); + const Matrix &eCosts = g.getEdgeCosts(eItr); + const Vector &xCosts = g.getNodeCosts(xnItr); + + // Duplicate a little to avoid transposing matrices. + if (xnItr == g.getEdgeNode1(eItr)) { + Graph::NodeItr ynItr = g.getEdgeNode2(eItr); + Vector &yCosts = g.getNodeCosts(ynItr); + for (unsigned j = 0; j < yCosts.getLength(); ++j) { + PBQPNum min = eCosts[0][j] + xCosts[0]; + for (unsigned i = 1; i < xCosts.getLength(); ++i) { + PBQPNum c = eCosts[i][j] + xCosts[i]; + if (c < min) + min = c; + } + yCosts[j] += min; + } + h.handleRemoveEdge(eItr, ynItr); + } else { + Graph::NodeItr ynItr = g.getEdgeNode1(eItr); + Vector &yCosts = g.getNodeCosts(ynItr); + for (unsigned i = 0; i < yCosts.getLength(); ++i) { + PBQPNum min = eCosts[i][0] + xCosts[0]; + for (unsigned j = 1; j < xCosts.getLength(); ++j) { + PBQPNum c = eCosts[i][j] + xCosts[j]; + if (c < min) + min = c; + } + yCosts[i] += min; + } + h.handleRemoveEdge(eItr, ynItr); + } + removeSolverEdge(eItr); + assert(nd.getSolverDegree() == 0 && + "Degree 1 with edge removed should be 0."); + pushToStack(xnItr); } - for (SimpleGraph::ConstEdgeIterator - origEdgeItr = orig.edgesBegin(), origEdgeEnd = orig.edgesEnd(); - origEdgeItr != origEdgeEnd; ++origEdgeItr) { - - unsigned id1 = orig.getNodeID(orig.getEdgeNode1Itr(origEdgeItr)), - id2 = orig.getNodeID(orig.getEdgeNode2Itr(origEdgeItr)); + /// \brief Apply rule R2. + /// @param nItr Node iterator for node to apply R2 to. + /// + /// Node will be automatically pushed to the solver stack. + void applyR2(Graph::NodeItr xnItr) { + assert(getSolverNodeData(xnItr).getSolverDegree() == 2 && + "R2 applied to node with degree != 2."); - g.addEdge(newNodeItrs[id1], newNodeItrs[id2], - orig.getEdgeCosts(origEdgeItr), EdgeData(g)); - } + NodeData &nd = getSolverNodeData(xnItr); + const Vector &xCosts = g.getNodeCosts(xnItr); - // Assign IDs to the new nodes using the ordering from the old graph, - // this will lead to nodes in the new graph getting the same ID as the - // corresponding node in the old graph. - g.assignNodeIDs(newNodeItrs); - } + SolverEdgeItr aeItr = nd.solverEdgesBegin(); + Graph::EdgeItr yxeItr = *aeItr, + zxeItr = *(++aeItr); - // Simplify the annotated graph by eliminating independent edges and trivial - // nodes. - void simplify() { - disconnectTrivialNodes(); - eliminateIndependentEdges(); - } + Graph::NodeItr ynItr = g.getEdgeOtherNode(yxeItr, xnItr), + znItr = g.getEdgeOtherNode(zxeItr, xnItr); - // Eliminate trivial nodes. - void disconnectTrivialNodes() { - for (GraphNodeIterator nodeItr = g.nodesBegin(), nodeEnd = g.nodesEnd(); - nodeItr != nodeEnd; ++nodeItr) { + bool flipEdge1 = (g.getEdgeNode1(yxeItr) == xnItr), + flipEdge2 = (g.getEdgeNode1(zxeItr) == xnItr); - if (g.getNodeCosts(nodeItr).getLength() == 1) { + const Matrix *yxeCosts = flipEdge1 ? + new Matrix(g.getEdgeCosts(yxeItr).transpose()) : + &g.getEdgeCosts(yxeItr); - std::vector<GraphEdgeIterator> edgesToRemove; + const Matrix *zxeCosts = flipEdge2 ? + new Matrix(g.getEdgeCosts(zxeItr).transpose()) : + &g.getEdgeCosts(zxeItr); - for (GraphAdjEdgeIterator adjEdgeItr = g.adjEdgesBegin(nodeItr), - adjEdgeEnd = g.adjEdgesEnd(nodeItr); - adjEdgeItr != adjEdgeEnd; ++adjEdgeItr) { + unsigned xLen = xCosts.getLength(), + yLen = yxeCosts->getRows(), + zLen = zxeCosts->getRows(); + + Matrix delta(yLen, zLen); - GraphEdgeIterator edgeItr = *adjEdgeItr; - - if (g.getEdgeNode1Itr(edgeItr) == nodeItr) { - GraphNodeIterator otherNodeItr = g.getEdgeNode2Itr(edgeItr); - g.getNodeCosts(otherNodeItr) += - g.getEdgeCosts(edgeItr).getRowAsVector(0); - } - else { - GraphNodeIterator otherNodeItr = g.getEdgeNode1Itr(edgeItr); - g.getNodeCosts(otherNodeItr) += - g.getEdgeCosts(edgeItr).getColAsVector(0); + for (unsigned i = 0; i < yLen; ++i) { + for (unsigned j = 0; j < zLen; ++j) { + PBQPNum min = (*yxeCosts)[i][0] + (*zxeCosts)[j][0] + xCosts[0]; + for (unsigned k = 1; k < xLen; ++k) { + PBQPNum c = (*yxeCosts)[i][k] + (*zxeCosts)[j][k] + xCosts[k]; + if (c < min) { + min = c; + } } - - edgesToRemove.push_back(edgeItr); + delta[i][j] = min; } + } - while (!edgesToRemove.empty()) { - g.removeEdge(edgesToRemove.back()); - edgesToRemove.pop_back(); + if (flipEdge1) + delete yxeCosts; + + if (flipEdge2) + delete zxeCosts; + + Graph::EdgeItr yzeItr = g.findEdge(ynItr, znItr); + bool addedEdge = false; + + if (yzeItr == g.edgesEnd()) { + yzeItr = g.addEdge(ynItr, znItr, delta); + addedEdge = true; + } else { + Matrix &yzeCosts = g.getEdgeCosts(yzeItr); + h.preUpdateEdgeCosts(yzeItr); + if (ynItr == g.getEdgeNode1(yzeItr)) { + yzeCosts += delta; + } else { + yzeCosts += delta.transpose(); } } - } - } - void eliminateIndependentEdges() { - std::vector<GraphEdgeIterator> edgesToProcess; + bool nullCostEdge = tryNormaliseEdgeMatrix(yzeItr); - for (GraphEdgeIterator edgeItr = g.edgesBegin(), edgeEnd = g.edgesEnd(); - edgeItr != edgeEnd; ++edgeItr) { - edgesToProcess.push_back(edgeItr); - } - - while (!edgesToProcess.empty()) { - tryToEliminateEdge(edgesToProcess.back()); - edgesToProcess.pop_back(); - } - } - - void tryToEliminateEdge(const GraphEdgeIterator &edgeItr) { - if (tryNormaliseEdgeMatrix(edgeItr)) { - g.removeEdge(edgeItr); - } - } - - bool tryNormaliseEdgeMatrix(const GraphEdgeIterator &edgeItr) { - - Matrix &edgeCosts = g.getEdgeCosts(edgeItr); - Vector &uCosts = g.getNodeCosts(g.getEdgeNode1Itr(edgeItr)), - &vCosts = g.getNodeCosts(g.getEdgeNode2Itr(edgeItr)); - - for (unsigned r = 0; r < edgeCosts.getRows(); ++r) { - PBQPNum rowMin = edgeCosts.getRowMin(r); - uCosts[r] += rowMin; - if (rowMin != std::numeric_limits<PBQPNum>::infinity()) { - edgeCosts.subFromRow(r, rowMin); + if (!addedEdge) { + // If we modified the edge costs let the heuristic know. + h.postUpdateEdgeCosts(yzeItr); } - else { - edgeCosts.setRow(r, 0); + + if (nullCostEdge) { + // If this edge ended up null remove it. + if (!addedEdge) { + // We didn't just add it, so we need to notify the heuristic + // and remove it from the solver. + h.handleRemoveEdge(yzeItr, ynItr); + h.handleRemoveEdge(yzeItr, znItr); + removeSolverEdge(yzeItr); + } + g.removeEdge(yzeItr); + } else if (addedEdge) { + // If the edge was added, and non-null, finish setting it up, add it to + // the solver & notify heuristic. + edgeDataList.push_back(EdgeData()); + g.setEdgeData(yzeItr, &edgeDataList.back()); + addSolverEdge(yzeItr); + h.handleAddEdge(yzeItr); } - } - for (unsigned c = 0; c < edgeCosts.getCols(); ++c) { - PBQPNum colMin = edgeCosts.getColMin(c); - vCosts[c] += colMin; - if (colMin != std::numeric_limits<PBQPNum>::infinity()) { - edgeCosts.subFromCol(c, colMin); - } - else { - edgeCosts.setCol(c, 0); - } - } + h.handleRemoveEdge(yxeItr, ynItr); + removeSolverEdge(yxeItr); + h.handleRemoveEdge(zxeItr, znItr); + removeSolverEdge(zxeItr); - return edgeCosts.isZero(); - } + pushToStack(xnItr); + } - void setup() { - setupLinks(); - heuristic.initialise(*this); - setupBuckets(); - } + private: - void setupLinks() { - for (GraphEdgeIterator edgeItr = g.edgesBegin(), edgeEnd = g.edgesEnd(); - edgeItr != edgeEnd; ++edgeItr) { - g.getEdgeData(edgeItr).setup(edgeItr); + NodeData& getSolverNodeData(Graph::NodeItr nItr) { + return *static_cast<NodeData*>(g.getNodeData(nItr)); } - } - void setupBuckets() { - for (GraphNodeIterator nodeItr = g.nodesBegin(), nodeEnd = g.nodesEnd(); - nodeItr != nodeEnd; ++nodeItr) { - addToBucket(nodeItr); - } - } - - void computeSolution() { - assert(g.areNodeIDsValid() && - "Nodes cannot be added/removed during reduction."); - - reduce(); - computeTrivialSolutions(); - backpropagate(); - } - - void printNode(const GraphNodeIterator &nodeItr) { - llvm::errs() << "Node " << g.getNodeID(nodeItr) << " (" << &*nodeItr << "):\n" - << " costs = " << g.getNodeCosts(nodeItr) << "\n" - << " link degree = " << g.getNodeData(nodeItr).getLinkDegree() << "\n" - << " links = [ "; - - for (typename HSIT::NodeData::AdjLinkIterator - aeItr = g.getNodeData(nodeItr).adjLinksBegin(), - aeEnd = g.getNodeData(nodeItr).adjLinksEnd(); - aeItr != aeEnd; ++aeItr) { - llvm::errs() << "(" << g.getNodeID(g.getEdgeNode1Itr(*aeItr)) - << ", " << g.getNodeID(g.getEdgeNode2Itr(*aeItr)) - << ") "; + EdgeData& getSolverEdgeData(Graph::EdgeItr eItr) { + return *static_cast<EdgeData*>(g.getEdgeData(eItr)); } - llvm::errs() << "]\n"; - } - void dumpState() { - llvm::errs() << "\n"; + void addSolverEdge(Graph::EdgeItr eItr) { + EdgeData &eData = getSolverEdgeData(eItr); + NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eItr)), + &n2Data = getSolverNodeData(g.getEdgeNode2(eItr)); - for (GraphNodeIterator nodeItr = g.nodesBegin(), nodeEnd = g.nodesEnd(); - nodeItr != nodeEnd; ++nodeItr) { - printNode(nodeItr); + eData.setN1SolverEdgeItr(n1Data.addSolverEdge(eItr)); + eData.setN2SolverEdgeItr(n2Data.addSolverEdge(eItr)); } - NodeList* buckets[] = { &r0Bucket, &r1Bucket, &r2Bucket }; - - for (unsigned b = 0; b < 3; ++b) { - NodeList &bucket = *buckets[b]; - - llvm::errs() << "Bucket " << b << ": [ "; - - for (NodeListIterator nItr = bucket.begin(), nEnd = bucket.end(); - nItr != nEnd; ++nItr) { - llvm::errs() << g.getNodeID(*nItr) << " "; + void setup() { + if (h.solverRunSimplify()) { + simplify(); } - llvm::errs() << "]\n"; - } + // Create node data objects. + for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); + nItr != nEnd; ++nItr) { + nodeDataList.push_back(NodeData()); + g.setNodeData(nItr, &nodeDataList.back()); + } - llvm::errs() << "Stack: [ "; - for (NodeStackIterator nsItr = stack.begin(), nsEnd = stack.end(); - nsItr != nsEnd; ++nsItr) { - llvm::errs() << g.getNodeID(*nsItr) << " "; + // Create edge data objects. + for (Graph::EdgeItr eItr = g.edgesBegin(), eEnd = g.edgesEnd(); + eItr != eEnd; ++eItr) { + edgeDataList.push_back(EdgeData()); + g.setEdgeData(eItr, &edgeDataList.back()); + addSolverEdge(eItr); + } } - llvm::errs() << "]\n"; - } - - void reduce() { - bool reductionFinished = r1Bucket.empty() && r2Bucket.empty() && - heuristic.rNBucketEmpty(); - while (!reductionFinished) { - - if (!r1Bucket.empty()) { - processR1(); - } - else if (!r2Bucket.empty()) { - processR2(); - } - else if (!heuristic.rNBucketEmpty()) { - solution.setProvedOptimal(false); - solution.incRNReductions(); - heuristic.processRN(); - } - else reductionFinished = true; + void simplify() { + disconnectTrivialNodes(); + eliminateIndependentEdges(); } - - } - void processR1() { + // Eliminate trivial nodes. + void disconnectTrivialNodes() { + unsigned numDisconnected = 0; - // Remove the first node in the R0 bucket: - GraphNodeIterator xNodeItr = r1Bucket.front(); - r1Bucket.pop_front(); + for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); + nItr != nEnd; ++nItr) { - solution.incR1Reductions(); + if (g.getNodeCosts(nItr).getLength() == 1) { - //llvm::errs() << "Applying R1 to " << g.getNodeID(xNodeItr) << "\n"; + std::vector<Graph::EdgeItr> edgesToRemove; - assert((g.getNodeData(xNodeItr).getLinkDegree() == 1) && - "Node in R1 bucket has degree != 1"); + for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nItr), + aeEnd = g.adjEdgesEnd(nItr); + aeItr != aeEnd; ++aeItr) { - GraphEdgeIterator edgeItr = *g.getNodeData(xNodeItr).adjLinksBegin(); + Graph::EdgeItr eItr = *aeItr; - const Matrix &edgeCosts = g.getEdgeCosts(edgeItr); + if (g.getEdgeNode1(eItr) == nItr) { + Graph::NodeItr otherNodeItr = g.getEdgeNode2(eItr); + g.getNodeCosts(otherNodeItr) += + g.getEdgeCosts(eItr).getRowAsVector(0); + } + else { + Graph::NodeItr otherNodeItr = g.getEdgeNode1(eItr); + g.getNodeCosts(otherNodeItr) += + g.getEdgeCosts(eItr).getColAsVector(0); + } - const Vector &xCosts = g.getNodeCosts(xNodeItr); - unsigned xLen = xCosts.getLength(); + edgesToRemove.push_back(eItr); + } - // Duplicate a little code to avoid transposing matrices: - if (xNodeItr == g.getEdgeNode1Itr(edgeItr)) { - GraphNodeIterator yNodeItr = g.getEdgeNode2Itr(edgeItr); - Vector &yCosts = g.getNodeCosts(yNodeItr); - unsigned yLen = yCosts.getLength(); + if (!edgesToRemove.empty()) + ++numDisconnected; - for (unsigned j = 0; j < yLen; ++j) { - PBQPNum min = edgeCosts[0][j] + xCosts[0]; - for (unsigned i = 1; i < xLen; ++i) { - PBQPNum c = edgeCosts[i][j] + xCosts[i]; - if (c < min) - min = c; + while (!edgesToRemove.empty()) { + g.removeEdge(edgesToRemove.back()); + edgesToRemove.pop_back(); + } } - yCosts[j] += min; } } - else { - GraphNodeIterator yNodeItr = g.getEdgeNode1Itr(edgeItr); - Vector &yCosts = g.getNodeCosts(yNodeItr); - unsigned yLen = yCosts.getLength(); - for (unsigned i = 0; i < yLen; ++i) { - PBQPNum min = edgeCosts[i][0] + xCosts[0]; + void eliminateIndependentEdges() { + std::vector<Graph::EdgeItr> edgesToProcess; + unsigned numEliminated = 0; - for (unsigned j = 1; j < xLen; ++j) { - PBQPNum c = edgeCosts[i][j] + xCosts[j]; - if (c < min) - min = c; - } - yCosts[i] += min; + for (Graph::EdgeItr eItr = g.edgesBegin(), eEnd = g.edgesEnd(); + eItr != eEnd; ++eItr) { + edgesToProcess.push_back(eItr); } - } - - unlinkNode(xNodeItr); - pushStack(xNodeItr); - } - - void processR2() { - - GraphNodeIterator xNodeItr = r2Bucket.front(); - r2Bucket.pop_front(); - - solution.incR2Reductions(); - - // Unlink is unsafe here. At some point it may optimistically more a node - // to a lower-degree list when its degree will later rise, or vice versa, - // violating the assumption that node degrees monotonically decrease - // during the reduction phase. Instead we'll bucket shuffle manually. - pushStack(xNodeItr); - - assert((g.getNodeData(xNodeItr).getLinkDegree() == 2) && - "Node in R2 bucket has degree != 2"); - - const Vector &xCosts = g.getNodeCosts(xNodeItr); - typename NodeData::AdjLinkIterator tempItr = - g.getNodeData(xNodeItr).adjLinksBegin(); - - GraphEdgeIterator yxEdgeItr = *tempItr, - zxEdgeItr = *(++tempItr); + while (!edgesToProcess.empty()) { + if (tryToEliminateEdge(edgesToProcess.back())) + ++numEliminated; + edgesToProcess.pop_back(); + } + } - GraphNodeIterator yNodeItr = g.getEdgeOtherNode(yxEdgeItr, xNodeItr), - zNodeItr = g.getEdgeOtherNode(zxEdgeItr, xNodeItr); + bool tryToEliminateEdge(Graph::EdgeItr eItr) { + if (tryNormaliseEdgeMatrix(eItr)) { + g.removeEdge(eItr); + return true; + } + return false; + } - removeFromBucket(yNodeItr); - removeFromBucket(zNodeItr); + bool tryNormaliseEdgeMatrix(Graph::EdgeItr &eItr) { - removeLink(yxEdgeItr, yNodeItr); - removeLink(zxEdgeItr, zNodeItr); + const PBQPNum infinity = std::numeric_limits<PBQPNum>::infinity(); - // Graph some of the costs: - bool flipEdge1 = (g.getEdgeNode1Itr(yxEdgeItr) == xNodeItr), - flipEdge2 = (g.getEdgeNode1Itr(zxEdgeItr) == xNodeItr); + Matrix &edgeCosts = g.getEdgeCosts(eItr); + Vector &uCosts = g.getNodeCosts(g.getEdgeNode1(eItr)), + &vCosts = g.getNodeCosts(g.getEdgeNode2(eItr)); - const Matrix *yxCosts = flipEdge1 ? - new Matrix(g.getEdgeCosts(yxEdgeItr).transpose()) : - &g.getEdgeCosts(yxEdgeItr), - *zxCosts = flipEdge2 ? - new Matrix(g.getEdgeCosts(zxEdgeItr).transpose()) : - &g.getEdgeCosts(zxEdgeItr); + for (unsigned r = 0; r < edgeCosts.getRows(); ++r) { + PBQPNum rowMin = infinity; - unsigned xLen = xCosts.getLength(), - yLen = yxCosts->getRows(), - zLen = zxCosts->getRows(); + for (unsigned c = 0; c < edgeCosts.getCols(); ++c) { + if (vCosts[c] != infinity && edgeCosts[r][c] < rowMin) + rowMin = edgeCosts[r][c]; + } - // Compute delta: - Matrix delta(yLen, zLen); + uCosts[r] += rowMin; - for (unsigned i = 0; i < yLen; ++i) { - for (unsigned j = 0; j < zLen; ++j) { - PBQPNum min = (*yxCosts)[i][0] + (*zxCosts)[j][0] + xCosts[0]; - for (unsigned k = 1; k < xLen; ++k) { - PBQPNum c = (*yxCosts)[i][k] + (*zxCosts)[j][k] + xCosts[k]; - if (c < min) { - min = c; - } + if (rowMin != infinity) { + edgeCosts.subFromRow(r, rowMin); + } + else { + edgeCosts.setRow(r, 0); } - delta[i][j] = min; } - } - - if (flipEdge1) - delete yxCosts; - if (flipEdge2) - delete zxCosts; + for (unsigned c = 0; c < edgeCosts.getCols(); ++c) { + PBQPNum colMin = infinity; - // Deal with the potentially induced yz edge. - GraphEdgeIterator yzEdgeItr = g.findEdge(yNodeItr, zNodeItr); - if (yzEdgeItr == g.edgesEnd()) { - yzEdgeItr = g.addEdge(yNodeItr, zNodeItr, delta, EdgeData(g)); - } - else { - // There was an edge, but we're going to screw with it. Delete the old - // link, update the costs. We'll re-link it later. - removeLinkR2(yzEdgeItr); - g.getEdgeCosts(yzEdgeItr) += - (yNodeItr == g.getEdgeNode1Itr(yzEdgeItr)) ? - delta : delta.transpose(); - } + for (unsigned r = 0; r < edgeCosts.getRows(); ++r) { + if (uCosts[r] != infinity && edgeCosts[r][c] < colMin) + colMin = edgeCosts[r][c]; + } - bool nullCostEdge = tryNormaliseEdgeMatrix(yzEdgeItr); + vCosts[c] += colMin; - // Nulled the edge, remove it entirely. - if (nullCostEdge) { - g.removeEdge(yzEdgeItr); - } - else { - // Edge remains - re-link it. - addLink(yzEdgeItr); - } + if (colMin != infinity) { + edgeCosts.subFromCol(c, colMin); + } + else { + edgeCosts.setCol(c, 0); + } + } - addToBucket(yNodeItr); - addToBucket(zNodeItr); + return edgeCosts.isZero(); } - void computeTrivialSolutions() { - - for (NodeListIterator r0Itr = r0Bucket.begin(), r0End = r0Bucket.end(); - r0Itr != r0End; ++r0Itr) { - GraphNodeIterator nodeItr = *r0Itr; - - solution.incR0Reductions(); - setSolution(nodeItr, g.getNodeCosts(nodeItr).minIndex()); + void backpropagate() { + while (!stack.empty()) { + computeSolution(stack.back()); + stack.pop_back(); + } } - } - - void backpropagate() { - while (!stack.empty()) { - computeSolution(stack.back()); - stack.pop_back(); - } - } + void computeSolution(Graph::NodeItr nItr) { - void computeSolution(const GraphNodeIterator &nodeItr) { + NodeData &nodeData = getSolverNodeData(nItr); - NodeData &nodeData = g.getNodeData(nodeItr); + Vector v(g.getNodeCosts(nItr)); - Vector v(g.getNodeCosts(nodeItr)); + // Solve based on existing solved edges. + for (SolverEdgeItr solvedEdgeItr = nodeData.solverEdgesBegin(), + solvedEdgeEnd = nodeData.solverEdgesEnd(); + solvedEdgeItr != solvedEdgeEnd; ++solvedEdgeItr) { - // Solve based on existing links. - for (typename NodeData::AdjLinkIterator - solvedLinkItr = nodeData.solvedLinksBegin(), - solvedLinkEnd = nodeData.solvedLinksEnd(); - solvedLinkItr != solvedLinkEnd; ++solvedLinkItr) { + Graph::EdgeItr eItr(*solvedEdgeItr); + Matrix &edgeCosts = g.getEdgeCosts(eItr); - GraphEdgeIterator solvedEdgeItr(*solvedLinkItr); - Matrix &edgeCosts = g.getEdgeCosts(solvedEdgeItr); + if (nItr == g.getEdgeNode1(eItr)) { + Graph::NodeItr adjNode(g.getEdgeNode2(eItr)); + unsigned adjSolution = s.getSelection(adjNode); + v += edgeCosts.getColAsVector(adjSolution); + } + else { + Graph::NodeItr adjNode(g.getEdgeNode1(eItr)); + unsigned adjSolution = s.getSelection(adjNode); + v += edgeCosts.getRowAsVector(adjSolution); + } - if (nodeItr == g.getEdgeNode1Itr(solvedEdgeItr)) { - GraphNodeIterator adjNode(g.getEdgeNode2Itr(solvedEdgeItr)); - unsigned adjSolution = - solution.getSelection(g.getNodeID(adjNode)); - v += edgeCosts.getColAsVector(adjSolution); - } - else { - GraphNodeIterator adjNode(g.getEdgeNode1Itr(solvedEdgeItr)); - unsigned adjSolution = - solution.getSelection(g.getNodeID(adjNode)); - v += edgeCosts.getRowAsVector(adjSolution); } + setSolution(nItr, v.minIndex()); } - setSolution(nodeItr, v.minIndex()); - } - - void computeSolutionCost(const SimpleGraph &orig) { - PBQPNum cost = 0.0; - - for (SimpleGraph::ConstNodeIterator - nodeItr = orig.nodesBegin(), nodeEnd = orig.nodesEnd(); - nodeItr != nodeEnd; ++nodeItr) { - - unsigned nodeId = orig.getNodeID(nodeItr); - - cost += orig.getNodeCosts(nodeItr)[solution.getSelection(nodeId)]; + void cleanup() { + h.cleanup(); + nodeDataList.clear(); + edgeDataList.clear(); } + }; - for (SimpleGraph::ConstEdgeIterator - edgeItr = orig.edgesBegin(), edgeEnd = orig.edgesEnd(); - edgeItr != edgeEnd; ++edgeItr) { - - SimpleGraph::ConstNodeIterator n1 = orig.getEdgeNode1Itr(edgeItr), - n2 = orig.getEdgeNode2Itr(edgeItr); - unsigned sol1 = solution.getSelection(orig.getNodeID(n1)), - sol2 = solution.getSelection(orig.getNodeID(n2)); - - cost += orig.getEdgeCosts(edgeItr)[sol1][sol2]; + /// \brief PBQP heuristic solver class. + /// + /// Given a PBQP Graph g representing a PBQP problem, you can find a solution + /// by calling + /// <tt>Solution s = HeuristicSolver<H>::solve(g);</tt> + /// + /// The choice of heuristic for the H parameter will affect both the solver + /// speed and solution quality. The heuristic should be chosen based on the + /// nature of the problem being solved. + /// Currently the only solver included with LLVM is the Briggs heuristic for + /// register allocation. + template <typename HImpl> + class HeuristicSolver { + public: + static Solution solve(Graph &g) { + HeuristicSolverImpl<HImpl> hs(g); + return hs.computeSolution(); } - - solution.setSolutionCost(cost); - } - -}; - -template <typename Heuristic> -class HeuristicSolver : public Solver { -public: - Solution solve(const SimpleGraph &g) const { - HeuristicSolverImpl<Heuristic> solverImpl(g); - return solverImpl.getSolution(); - } -}; + }; } diff --git a/lib/CodeGen/PBQP/Heuristics/Briggs.h b/lib/CodeGen/PBQP/Heuristics/Briggs.h index 1228f65..30d34d9 100644 --- a/lib/CodeGen/PBQP/Heuristics/Briggs.h +++ b/lib/CodeGen/PBQP/Heuristics/Briggs.h @@ -18,365 +18,447 @@ #ifndef LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H #define LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H +#include "llvm/Support/Compiler.h" #include "../HeuristicSolver.h" +#include "../HeuristicBase.h" #include <set> +#include <limits> namespace PBQP { -namespace Heuristics { - -class Briggs { - public: - - class NodeData; - class EdgeData; - - private: - - typedef HeuristicSolverImpl<Briggs> Solver; - typedef HSITypes<NodeData, EdgeData> HSIT; - typedef HSIT::SolverGraph SolverGraph; - typedef HSIT::GraphNodeIterator GraphNodeIterator; - typedef HSIT::GraphEdgeIterator GraphEdgeIterator; - - class LinkDegreeComparator { + namespace Heuristics { + + /// \brief PBQP Heuristic which applies an allocability test based on + /// Briggs. + /// + /// This heuristic assumes that the elements of cost vectors in the PBQP + /// problem represent storage options, with the first being the spill + /// option and subsequent elements representing legal registers for the + /// corresponding node. Edge cost matrices are likewise assumed to represent + /// register constraints. + /// If one or more nodes can be proven allocable by this heuristic (by + /// inspection of their constraint matrices) then the allocable node of + /// highest degree is selected for the next reduction and pushed to the + /// solver stack. If no nodes can be proven allocable then the node with + /// the lowest estimated spill cost is selected and push to the solver stack + /// instead. + /// + /// This implementation is built on top of HeuristicBase. + class Briggs : public HeuristicBase<Briggs> { + private: + + class LinkDegreeComparator { public: - LinkDegreeComparator() : g(0) {} - LinkDegreeComparator(SolverGraph *g) : g(g) {} - - bool operator()(const GraphNodeIterator &node1Itr, - const GraphNodeIterator &node2Itr) const { - assert((g != 0) && "Graph object not set, cannot access node data."); - unsigned n1Degree = g->getNodeData(node1Itr).getLinkDegree(), - n2Degree = g->getNodeData(node2Itr).getLinkDegree(); - if (n1Degree > n2Degree) { + LinkDegreeComparator(HeuristicSolverImpl<Briggs> &s) : s(&s) {} + bool operator()(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr) const { + if (s->getSolverDegree(n1Itr) > s->getSolverDegree(n2Itr)) return true; - } - else if (n1Degree < n2Degree) { + if (s->getSolverDegree(n1Itr) < s->getSolverDegree(n2Itr)) return false; - } - // else they're "equal" by degree, differentiate based on ID. - return g->getNodeID(node1Itr) < g->getNodeID(node2Itr); + return (&*n1Itr < &*n2Itr); } - private: - SolverGraph *g; - }; + HeuristicSolverImpl<Briggs> *s; + }; - class SpillPriorityComparator { + class SpillCostComparator { public: - SpillPriorityComparator() : g(0) {} - SpillPriorityComparator(SolverGraph *g) : g(g) {} - - bool operator()(const GraphNodeIterator &node1Itr, - const GraphNodeIterator &node2Itr) const { - assert((g != 0) && "Graph object not set, cannot access node data."); - PBQPNum cost1 = - g->getNodeCosts(node1Itr)[0] / - g->getNodeData(node1Itr).getLinkDegree(), - cost2 = - g->getNodeCosts(node2Itr)[0] / - g->getNodeData(node2Itr).getLinkDegree(); - - if (cost1 < cost2) { + SpillCostComparator(HeuristicSolverImpl<Briggs> &s) + : s(&s), g(&s.getGraph()) {} + bool operator()(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr) const { + PBQPNum cost1 = g->getNodeCosts(n1Itr)[0] / s->getSolverDegree(n1Itr), + cost2 = g->getNodeCosts(n2Itr)[0] / s->getSolverDegree(n2Itr); + if (cost1 < cost2) return true; - } - else if (cost1 > cost2) { + if (cost1 > cost2) return false; - } - // else they'er "equal" again, differentiate based on address again. - return g->getNodeID(node1Itr) < g->getNodeID(node2Itr); + return (&*n1Itr < &*n2Itr); } private: - SolverGraph *g; - }; - - typedef std::set<GraphNodeIterator, LinkDegreeComparator> - RNAllocableNodeList; - typedef RNAllocableNodeList::iterator RNAllocableNodeListIterator; - - typedef std::set<GraphNodeIterator, SpillPriorityComparator> - RNUnallocableNodeList; - typedef RNUnallocableNodeList::iterator RNUnallocableNodeListIterator; - - public: - - class NodeData { - private: - RNAllocableNodeListIterator rNAllocableNodeListItr; - RNUnallocableNodeListIterator rNUnallocableNodeListItr; - unsigned numRegOptions, numDenied, numSafe; - std::vector<unsigned> unsafeDegrees; - bool allocable; - - void addRemoveLink(SolverGraph &g, const GraphNodeIterator &nodeItr, - const GraphEdgeIterator &edgeItr, bool add) { + HeuristicSolverImpl<Briggs> *s; + Graph *g; + }; - //assume we're adding... - unsigned udTarget = 0, dir = 1; + typedef std::list<Graph::NodeItr> RNAllocableList; + typedef RNAllocableList::iterator RNAllocableListItr; - if (!add) { - udTarget = 1; - dir = ~0; - } + typedef std::list<Graph::NodeItr> RNUnallocableList; + typedef RNUnallocableList::iterator RNUnallocableListItr; - EdgeData &linkEdgeData = g.getEdgeData(edgeItr).getHeuristicData(); + public: - EdgeData::ConstUnsafeIterator edgeUnsafeBegin, edgeUnsafeEnd; + struct NodeData { + typedef std::vector<unsigned> UnsafeDegreesArray; + bool isHeuristic, isAllocable, isInitialized; + unsigned numDenied, numSafe; + UnsafeDegreesArray unsafeDegrees; + RNAllocableListItr rnaItr; + RNUnallocableListItr rnuItr; - if (nodeItr == g.getEdgeNode1Itr(edgeItr)) { - numDenied += (dir * linkEdgeData.getWorstDegree()); - edgeUnsafeBegin = linkEdgeData.unsafeBegin(); - edgeUnsafeEnd = linkEdgeData.unsafeEnd(); - } - else { - numDenied += (dir * linkEdgeData.getReverseWorstDegree()); - edgeUnsafeBegin = linkEdgeData.reverseUnsafeBegin(); - edgeUnsafeEnd = linkEdgeData.reverseUnsafeEnd(); - } + NodeData() + : isHeuristic(false), isAllocable(false), isInitialized(false), + numDenied(0), numSafe(0) { } + }; - assert((unsafeDegrees.size() == - static_cast<unsigned>( - std::distance(edgeUnsafeBegin, edgeUnsafeEnd))) - && "Unsafe array size mismatch."); - - std::vector<unsigned>::iterator unsafeDegreesItr = - unsafeDegrees.begin(); - - for (EdgeData::ConstUnsafeIterator edgeUnsafeItr = edgeUnsafeBegin; - edgeUnsafeItr != edgeUnsafeEnd; - ++edgeUnsafeItr, ++unsafeDegreesItr) { - - if ((*edgeUnsafeItr == 1) && (*unsafeDegreesItr == udTarget)) { - numSafe -= dir; - } - *unsafeDegreesItr += (dir * (*edgeUnsafeItr)); - } - - allocable = (numDenied < numRegOptions) || (numSafe > 0); - } - - public: - - void setup(SolverGraph &g, const GraphNodeIterator &nodeItr) { - - numRegOptions = g.getNodeCosts(nodeItr).getLength() - 1; - - numSafe = numRegOptions; // Optimistic, correct below. - numDenied = 0; // Also optimistic. - unsafeDegrees.resize(numRegOptions, 0); - - HSIT::NodeData &nodeData = g.getNodeData(nodeItr); - - for (HSIT::NodeData::AdjLinkIterator - adjLinkItr = nodeData.adjLinksBegin(), - adjLinkEnd = nodeData.adjLinksEnd(); - adjLinkItr != adjLinkEnd; ++adjLinkItr) { - - addRemoveLink(g, nodeItr, *adjLinkItr, true); - } - } - - bool isAllocable() const { return allocable; } - - void handleAddLink(SolverGraph &g, const GraphNodeIterator &nodeItr, - const GraphEdgeIterator &adjEdge) { - addRemoveLink(g, nodeItr, adjEdge, true); + struct EdgeData { + typedef std::vector<unsigned> UnsafeArray; + unsigned worst, reverseWorst; + UnsafeArray unsafe, reverseUnsafe; + bool isUpToDate; + + EdgeData() : worst(0), reverseWorst(0), isUpToDate(false) {} + }; + + /// \brief Construct an instance of the Briggs heuristic. + /// @param solver A reference to the solver which is using this heuristic. + Briggs(HeuristicSolverImpl<Briggs> &solver) : + HeuristicBase<Briggs>(solver) {} + + /// \brief Determine whether a node should be reduced using optimal + /// reduction. + /// @param nItr Node iterator to be considered. + /// @return True if the given node should be optimally reduced, false + /// otherwise. + /// + /// Selects nodes of degree 0, 1 or 2 for optimal reduction, with one + /// exception. Nodes whose spill cost (element 0 of their cost vector) is + /// infinite are checked for allocability first. Allocable nodes may be + /// optimally reduced, but nodes whose allocability cannot be proven are + /// selected for heuristic reduction instead. + bool shouldOptimallyReduce(Graph::NodeItr nItr) { + if (getSolver().getSolverDegree(nItr) < 3) { + return true; } - - void handleRemoveLink(SolverGraph &g, const GraphNodeIterator &nodeItr, - const GraphEdgeIterator &adjEdge) { - addRemoveLink(g, nodeItr, adjEdge, false); + // else + return false; + } + + /// \brief Add a node to the heuristic reduce list. + /// @param nItr Node iterator to add to the heuristic reduce list. + void addToHeuristicReduceList(Graph::NodeItr nItr) { + NodeData &nd = getHeuristicNodeData(nItr); + initializeNode(nItr); + nd.isHeuristic = true; + if (nd.isAllocable) { + nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nItr); + } else { + nd.rnuItr = rnUnallocableList.insert(rnUnallocableList.end(), nItr); } - - void setRNAllocableNodeListItr( - const RNAllocableNodeListIterator &rNAllocableNodeListItr) { - - this->rNAllocableNodeListItr = rNAllocableNodeListItr; + } + + /// \brief Heuristically reduce one of the nodes in the heuristic + /// reduce list. + /// @return True if a reduction takes place, false if the heuristic reduce + /// list is empty. + /// + /// If the list of allocable nodes is non-empty a node is selected + /// from it and pushed to the stack. Otherwise if the non-allocable list + /// is non-empty a node is selected from it and pushed to the stack. + /// If both lists are empty the method simply returns false with no action + /// taken. + bool heuristicReduce() { + if (!rnAllocableList.empty()) { + RNAllocableListItr rnaItr = + min_element(rnAllocableList.begin(), rnAllocableList.end(), + LinkDegreeComparator(getSolver())); + Graph::NodeItr nItr = *rnaItr; + rnAllocableList.erase(rnaItr); + handleRemoveNode(nItr); + getSolver().pushToStack(nItr); + return true; + } else if (!rnUnallocableList.empty()) { + RNUnallocableListItr rnuItr = + min_element(rnUnallocableList.begin(), rnUnallocableList.end(), + SpillCostComparator(getSolver())); + Graph::NodeItr nItr = *rnuItr; + rnUnallocableList.erase(rnuItr); + handleRemoveNode(nItr); + getSolver().pushToStack(nItr); + return true; } - - RNAllocableNodeListIterator getRNAllocableNodeListItr() const { - return rNAllocableNodeListItr; + // else + return false; + } + + /// \brief Prepare a change in the costs on the given edge. + /// @param eItr Edge iterator. + void preUpdateEdgeCosts(Graph::EdgeItr eItr) { + Graph &g = getGraph(); + Graph::NodeItr n1Itr = g.getEdgeNode1(eItr), + n2Itr = g.getEdgeNode2(eItr); + NodeData &n1 = getHeuristicNodeData(n1Itr), + &n2 = getHeuristicNodeData(n2Itr); + + if (n1.isHeuristic) + subtractEdgeContributions(eItr, getGraph().getEdgeNode1(eItr)); + if (n2.isHeuristic) + subtractEdgeContributions(eItr, getGraph().getEdgeNode2(eItr)); + + EdgeData &ed = getHeuristicEdgeData(eItr); + ed.isUpToDate = false; + } + + /// \brief Handle the change in the costs on the given edge. + /// @param eItr Edge iterator. + void postUpdateEdgeCosts(Graph::EdgeItr eItr) { + // This is effectively the same as adding a new edge now, since + // we've factored out the costs of the old one. + handleAddEdge(eItr); + } + + /// \brief Handle the addition of a new edge into the PBQP graph. + /// @param eItr Edge iterator for the added edge. + /// + /// Updates allocability of any nodes connected by this edge which are + /// being managed by the heuristic. If allocability changes they are + /// moved to the appropriate list. + void handleAddEdge(Graph::EdgeItr eItr) { + Graph &g = getGraph(); + Graph::NodeItr n1Itr = g.getEdgeNode1(eItr), + n2Itr = g.getEdgeNode2(eItr); + NodeData &n1 = getHeuristicNodeData(n1Itr), + &n2 = getHeuristicNodeData(n2Itr); + + // If neither node is managed by the heuristic there's nothing to be + // done. + if (!n1.isHeuristic && !n2.isHeuristic) + return; + + // Ok - we need to update at least one node. + computeEdgeContributions(eItr); + + // Update node 1 if it's managed by the heuristic. + if (n1.isHeuristic) { + bool n1WasAllocable = n1.isAllocable; + addEdgeContributions(eItr, n1Itr); + updateAllocability(n1Itr); + if (n1WasAllocable && !n1.isAllocable) { + rnAllocableList.erase(n1.rnaItr); + n1.rnuItr = + rnUnallocableList.insert(rnUnallocableList.end(), n1Itr); + } } - void setRNUnallocableNodeListItr( - const RNUnallocableNodeListIterator &rNUnallocableNodeListItr) { - - this->rNUnallocableNodeListItr = rNUnallocableNodeListItr; + // Likewise for node 2. + if (n2.isHeuristic) { + bool n2WasAllocable = n2.isAllocable; + addEdgeContributions(eItr, n2Itr); + updateAllocability(n2Itr); + if (n2WasAllocable && !n2.isAllocable) { + rnAllocableList.erase(n2.rnaItr); + n2.rnuItr = + rnUnallocableList.insert(rnUnallocableList.end(), n2Itr); + } } - - RNUnallocableNodeListIterator getRNUnallocableNodeListItr() const { - return rNUnallocableNodeListItr; + } + + /// \brief Handle disconnection of an edge from a node. + /// @param eItr Edge iterator for edge being disconnected. + /// @param nItr Node iterator for the node being disconnected from. + /// + /// Updates allocability of the given node and, if appropriate, moves the + /// node to a new list. + void handleRemoveEdge(Graph::EdgeItr eItr, Graph::NodeItr nItr) { + NodeData &nd = getHeuristicNodeData(nItr); + + // If the node is not managed by the heuristic there's nothing to be + // done. + if (!nd.isHeuristic) + return; + + EdgeData &ed ATTRIBUTE_UNUSED = getHeuristicEdgeData(eItr); + + assert(ed.isUpToDate && "Edge data is not up to date."); + + // Update node. + bool ndWasAllocable = nd.isAllocable; + subtractEdgeContributions(eItr, nItr); + updateAllocability(nItr); + + // If the node has gone optimal... + if (shouldOptimallyReduce(nItr)) { + nd.isHeuristic = false; + addToOptimalReduceList(nItr); + if (ndWasAllocable) { + rnAllocableList.erase(nd.rnaItr); + } else { + rnUnallocableList.erase(nd.rnuItr); + } + } else { + // Node didn't go optimal, but we might have to move it + // from "unallocable" to "allocable". + if (!ndWasAllocable && nd.isAllocable) { + rnUnallocableList.erase(nd.rnuItr); + nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nItr); + } } + } + private: - }; + NodeData& getHeuristicNodeData(Graph::NodeItr nItr) { + return getSolver().getHeuristicNodeData(nItr); + } - class EdgeData { - private: + EdgeData& getHeuristicEdgeData(Graph::EdgeItr eItr) { + return getSolver().getHeuristicEdgeData(eItr); + } - typedef std::vector<unsigned> UnsafeArray; + // Work out what this edge will contribute to the allocability of the + // nodes connected to it. + void computeEdgeContributions(Graph::EdgeItr eItr) { + EdgeData &ed = getHeuristicEdgeData(eItr); - unsigned worstDegree, - reverseWorstDegree; - UnsafeArray unsafe, reverseUnsafe; + if (ed.isUpToDate) + return; // Edge data is already up to date. - public: + Matrix &eCosts = getGraph().getEdgeCosts(eItr); - EdgeData() : worstDegree(0), reverseWorstDegree(0) {} + unsigned numRegs = eCosts.getRows() - 1, + numReverseRegs = eCosts.getCols() - 1; - typedef UnsafeArray::const_iterator ConstUnsafeIterator; + std::vector<unsigned> rowInfCounts(numRegs, 0), + colInfCounts(numReverseRegs, 0); - void setup(SolverGraph &g, const GraphEdgeIterator &edgeItr) { - const Matrix &edgeCosts = g.getEdgeCosts(edgeItr); - unsigned numRegs = edgeCosts.getRows() - 1, - numReverseRegs = edgeCosts.getCols() - 1; + ed.worst = 0; + ed.reverseWorst = 0; + ed.unsafe.clear(); + ed.unsafe.resize(numRegs, 0); + ed.reverseUnsafe.clear(); + ed.reverseUnsafe.resize(numReverseRegs, 0); - unsafe.resize(numRegs, 0); - reverseUnsafe.resize(numReverseRegs, 0); + for (unsigned i = 0; i < numRegs; ++i) { + for (unsigned j = 0; j < numReverseRegs; ++j) { + if (eCosts[i + 1][j + 1] == + std::numeric_limits<PBQPNum>::infinity()) { + ed.unsafe[i] = 1; + ed.reverseUnsafe[j] = 1; + ++rowInfCounts[i]; + ++colInfCounts[j]; - std::vector<unsigned> rowInfCounts(numRegs, 0), - colInfCounts(numReverseRegs, 0); + if (colInfCounts[j] > ed.worst) { + ed.worst = colInfCounts[j]; + } - for (unsigned i = 0; i < numRegs; ++i) { - for (unsigned j = 0; j < numReverseRegs; ++j) { - if (edgeCosts[i + 1][j + 1] == - std::numeric_limits<PBQPNum>::infinity()) { - unsafe[i] = 1; - reverseUnsafe[j] = 1; - ++rowInfCounts[i]; - ++colInfCounts[j]; - - if (colInfCounts[j] > worstDegree) { - worstDegree = colInfCounts[j]; - } - - if (rowInfCounts[i] > reverseWorstDegree) { - reverseWorstDegree = rowInfCounts[i]; - } + if (rowInfCounts[i] > ed.reverseWorst) { + ed.reverseWorst = rowInfCounts[i]; } } } } - unsigned getWorstDegree() const { return worstDegree; } - unsigned getReverseWorstDegree() const { return reverseWorstDegree; } - ConstUnsafeIterator unsafeBegin() const { return unsafe.begin(); } - ConstUnsafeIterator unsafeEnd() const { return unsafe.end(); } - ConstUnsafeIterator reverseUnsafeBegin() const { - return reverseUnsafe.begin(); + ed.isUpToDate = true; + } + + // Add the contributions of the given edge to the given node's + // numDenied and safe members. No action is taken other than to update + // these member values. Once updated these numbers can be used by clients + // to update the node's allocability. + void addEdgeContributions(Graph::EdgeItr eItr, Graph::NodeItr nItr) { + EdgeData &ed = getHeuristicEdgeData(eItr); + + assert(ed.isUpToDate && "Using out-of-date edge numbers."); + + NodeData &nd = getHeuristicNodeData(nItr); + unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; + + bool nIsNode1 = nItr == getGraph().getEdgeNode1(eItr); + EdgeData::UnsafeArray &unsafe = + nIsNode1 ? ed.unsafe : ed.reverseUnsafe; + nd.numDenied += nIsNode1 ? ed.worst : ed.reverseWorst; + + for (unsigned r = 0; r < numRegs; ++r) { + if (unsafe[r]) { + if (nd.unsafeDegrees[r]==0) { + --nd.numSafe; + } + ++nd.unsafeDegrees[r]; + } } - ConstUnsafeIterator reverseUnsafeEnd() const { - return reverseUnsafe.end(); + } + + // Subtract the contributions of the given edge to the given node's + // numDenied and safe members. No action is taken other than to update + // these member values. Once updated these numbers can be used by clients + // to update the node's allocability. + void subtractEdgeContributions(Graph::EdgeItr eItr, Graph::NodeItr nItr) { + EdgeData &ed = getHeuristicEdgeData(eItr); + + assert(ed.isUpToDate && "Using out-of-date edge numbers."); + + NodeData &nd = getHeuristicNodeData(nItr); + unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; + + bool nIsNode1 = nItr == getGraph().getEdgeNode1(eItr); + EdgeData::UnsafeArray &unsafe = + nIsNode1 ? ed.unsafe : ed.reverseUnsafe; + nd.numDenied -= nIsNode1 ? ed.worst : ed.reverseWorst; + + for (unsigned r = 0; r < numRegs; ++r) { + if (unsafe[r]) { + if (nd.unsafeDegrees[r] == 1) { + ++nd.numSafe; + } + --nd.unsafeDegrees[r]; + } } - }; - - void initialise(Solver &solver) { - this->s = &solver; - g = &s->getGraph(); - rNAllocableBucket = RNAllocableNodeList(LinkDegreeComparator(g)); - rNUnallocableBucket = - RNUnallocableNodeList(SpillPriorityComparator(g)); - - for (GraphEdgeIterator - edgeItr = g->edgesBegin(), edgeEnd = g->edgesEnd(); - edgeItr != edgeEnd; ++edgeItr) { - - g->getEdgeData(edgeItr).getHeuristicData().setup(*g, edgeItr); - } - - for (GraphNodeIterator - nodeItr = g->nodesBegin(), nodeEnd = g->nodesEnd(); - nodeItr != nodeEnd; ++nodeItr) { - - g->getNodeData(nodeItr).getHeuristicData().setup(*g, nodeItr); - } - } - - void addToRNBucket(const GraphNodeIterator &nodeItr) { - NodeData &nodeData = g->getNodeData(nodeItr).getHeuristicData(); - - if (nodeData.isAllocable()) { - nodeData.setRNAllocableNodeListItr( - rNAllocableBucket.insert(rNAllocableBucket.begin(), nodeItr)); - } - else { - nodeData.setRNUnallocableNodeListItr( - rNUnallocableBucket.insert(rNUnallocableBucket.begin(), nodeItr)); - } - } + } - void removeFromRNBucket(const GraphNodeIterator &nodeItr) { - NodeData &nodeData = g->getNodeData(nodeItr).getHeuristicData(); - - if (nodeData.isAllocable()) { - rNAllocableBucket.erase(nodeData.getRNAllocableNodeListItr()); - } - else { - rNUnallocableBucket.erase(nodeData.getRNUnallocableNodeListItr()); - } - } + void updateAllocability(Graph::NodeItr nItr) { + NodeData &nd = getHeuristicNodeData(nItr); + unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; + nd.isAllocable = nd.numDenied < numRegs || nd.numSafe > 0; + } - void handleAddLink(const GraphEdgeIterator &edgeItr) { - // We assume that if we got here this edge is attached to at least - // one high degree node. - g->getEdgeData(edgeItr).getHeuristicData().setup(*g, edgeItr); - - GraphNodeIterator n1Itr = g->getEdgeNode1Itr(edgeItr), - n2Itr = g->getEdgeNode2Itr(edgeItr); - - HSIT::NodeData &n1Data = g->getNodeData(n1Itr), - &n2Data = g->getNodeData(n2Itr); - - if (n1Data.getLinkDegree() > 2) { - n1Data.getHeuristicData().handleAddLink(*g, n1Itr, edgeItr); - } - if (n2Data.getLinkDegree() > 2) { - n2Data.getHeuristicData().handleAddLink(*g, n2Itr, edgeItr); - } - } + void initializeNode(Graph::NodeItr nItr) { + NodeData &nd = getHeuristicNodeData(nItr); - void handleRemoveLink(const GraphEdgeIterator &edgeItr, - const GraphNodeIterator &nodeItr) { - NodeData &nodeData = g->getNodeData(nodeItr).getHeuristicData(); - nodeData.handleRemoveLink(*g, nodeItr, edgeItr); - } + if (nd.isInitialized) + return; // Node data is already up to date. - void processRN() { - - if (!rNAllocableBucket.empty()) { - GraphNodeIterator selectedNodeItr = *rNAllocableBucket.begin(); - //std::cerr << "RN safely pushing " << g->getNodeID(selectedNodeItr) << "\n"; - rNAllocableBucket.erase(rNAllocableBucket.begin()); - s->pushStack(selectedNodeItr); - s->unlinkNode(selectedNodeItr); - } - else { - GraphNodeIterator selectedNodeItr = *rNUnallocableBucket.begin(); - //std::cerr << "RN optimistically pushing " << g->getNodeID(selectedNodeItr) << "\n"; - rNUnallocableBucket.erase(rNUnallocableBucket.begin()); - s->pushStack(selectedNodeItr); - s->unlinkNode(selectedNodeItr); - } - - } + unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; - bool rNBucketEmpty() const { - return (rNAllocableBucket.empty() && rNUnallocableBucket.empty()); - } + nd.numDenied = 0; + nd.numSafe = numRegs; + nd.unsafeDegrees.resize(numRegs, 0); -private: + typedef HeuristicSolverImpl<Briggs>::SolverEdgeItr SolverEdgeItr; - Solver *s; - SolverGraph *g; - RNAllocableNodeList rNAllocableBucket; - RNUnallocableNodeList rNUnallocableBucket; -}; + for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(nItr), + aeEnd = getSolver().solverEdgesEnd(nItr); + aeItr != aeEnd; ++aeItr) { + + Graph::EdgeItr eItr = *aeItr; + computeEdgeContributions(eItr); + addEdgeContributions(eItr, nItr); + } + updateAllocability(nItr); + nd.isInitialized = true; + } + + void handleRemoveNode(Graph::NodeItr xnItr) { + typedef HeuristicSolverImpl<Briggs>::SolverEdgeItr SolverEdgeItr; + std::vector<Graph::EdgeItr> edgesToRemove; + for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(xnItr), + aeEnd = getSolver().solverEdgesEnd(xnItr); + aeItr != aeEnd; ++aeItr) { + Graph::NodeItr ynItr = getGraph().getEdgeOtherNode(*aeItr, xnItr); + handleRemoveEdge(*aeItr, ynItr); + edgesToRemove.push_back(*aeItr); + } + while (!edgesToRemove.empty()) { + getSolver().removeSolverEdge(edgesToRemove.back()); + edgesToRemove.pop_back(); + } + } + RNAllocableList rnAllocableList; + RNUnallocableList rnUnallocableList; + }; -} + } } diff --git a/lib/CodeGen/PBQP/PBQPMath.h b/lib/CodeGen/PBQP/Math.h index 20737a2..e7598bf 100644 --- a/lib/CodeGen/PBQP/PBQPMath.h +++ b/lib/CodeGen/PBQP/Math.h @@ -1,4 +1,4 @@ -//===-- PBQPMath.h - PBQP Vector and Matrix classes -------------*- C++ -*-===// +//===------ Math.h - PBQP Vector and Matrix classes -------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_PBQP_PBQPMATH_H -#define LLVM_CODEGEN_PBQP_PBQPMATH_H +#ifndef LLVM_CODEGEN_PBQP_MATH_H +#define LLVM_CODEGEN_PBQP_MATH_H #include <cassert> #include <algorithm> @@ -16,7 +16,7 @@ namespace PBQP { -typedef double PBQPNum; +typedef float PBQPNum; /// \brief PBQP Vector class. class Vector { @@ -285,4 +285,4 @@ OStream& operator<<(OStream &os, const Matrix &m) { } -#endif // LLVM_CODEGEN_PBQP_PBQPMATH_HPP +#endif // LLVM_CODEGEN_PBQP_MATH_H diff --git a/lib/CodeGen/PBQP/SimpleGraph.h b/lib/CodeGen/PBQP/SimpleGraph.h deleted file mode 100644 index 13e63ce..0000000 --- a/lib/CodeGen/PBQP/SimpleGraph.h +++ /dev/null @@ -1,100 +0,0 @@ -//===-- SimpleGraph.h - Simple PBQP Graph -----------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Simple PBQP graph class representing a PBQP problem. Graphs of this type -// can be passed to a PBQPSolver instance to solve the PBQP problem. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_PBQP_SIMPLEGRAPH_H -#define LLVM_CODEGEN_PBQP_SIMPLEGRAPH_H - -#include "GraphBase.h" - -namespace PBQP { - -class SimpleEdge; - -class SimpleNode : public NodeBase<SimpleNode, SimpleEdge> { -public: - SimpleNode(const Vector &costs) : - NodeBase<SimpleNode, SimpleEdge>(costs) {} -}; - -class SimpleEdge : public EdgeBase<SimpleNode, SimpleEdge> { -public: - SimpleEdge(const NodeIterator &node1Itr, const NodeIterator &node2Itr, - const Matrix &costs) : - EdgeBase<SimpleNode, SimpleEdge>(node1Itr, node2Itr, costs) {} -}; - -class SimpleGraph : public GraphBase<SimpleNode, SimpleEdge> { -private: - - typedef GraphBase<SimpleNode, SimpleEdge> PGraph; - - void copyFrom(const SimpleGraph &other) { - assert(other.areNodeIDsValid() && - "Cannot copy from another graph unless IDs have been assigned."); - - std::vector<NodeIterator> newNodeItrs(other.getNumNodes()); - - for (ConstNodeIterator nItr = other.nodesBegin(), nEnd = other.nodesEnd(); - nItr != nEnd; ++nItr) { - newNodeItrs[other.getNodeID(nItr)] = addNode(other.getNodeCosts(nItr)); - } - - for (ConstEdgeIterator eItr = other.edgesBegin(), eEnd = other.edgesEnd(); - eItr != eEnd; ++eItr) { - - unsigned node1ID = other.getNodeID(other.getEdgeNode1Itr(eItr)), - node2ID = other.getNodeID(other.getEdgeNode2Itr(eItr)); - - addEdge(newNodeItrs[node1ID], newNodeItrs[node2ID], - other.getEdgeCosts(eItr)); - } - } - - void copyFrom(SimpleGraph &other) { - if (!other.areNodeIDsValid()) { - other.assignNodeIDs(); - } - copyFrom(const_cast<const SimpleGraph&>(other)); - } - -public: - - SimpleGraph() {} - - - SimpleGraph(const SimpleGraph &other) : PGraph() { - copyFrom(other); - } - - SimpleGraph& operator=(const SimpleGraph &other) { - clear(); - copyFrom(other); - return *this; - } - - NodeIterator addNode(const Vector &costs) { - return PGraph::addConstructedNode(SimpleNode(costs)); - } - - EdgeIterator addEdge(const NodeIterator &node1Itr, - const NodeIterator &node2Itr, - const Matrix &costs) { - return PGraph::addConstructedEdge(SimpleEdge(node1Itr, node2Itr, costs)); - } - -}; - -} - -#endif // LLVM_CODEGEN_PBQP_SIMPLEGRAPH_H diff --git a/lib/CodeGen/PBQP/Solution.h b/lib/CodeGen/PBQP/Solution.h index aee684d..294b537 100644 --- a/lib/CodeGen/PBQP/Solution.h +++ b/lib/CodeGen/PBQP/Solution.h @@ -7,81 +7,51 @@ // //===----------------------------------------------------------------------===// // -// Annotated PBQP Graph class. This class is used internally by the PBQP solver -// to cache information to speed up reduction. +// PBQP Solution class. // //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_PBQP_SOLUTION_H #define LLVM_CODEGEN_PBQP_SOLUTION_H -#include "PBQPMath.h" +#include "Math.h" +#include "Graph.h" -namespace PBQP { - -class Solution { - - friend class SolverImplementation; - -private: - - std::vector<unsigned> selections; - PBQPNum solutionCost; - bool provedOptimal; - unsigned r0Reductions, r1Reductions, - r2Reductions, rNReductions; - -public: - - Solution() : - solutionCost(0.0), provedOptimal(false), - r0Reductions(0), r1Reductions(0), r2Reductions(0), rNReductions(0) {} - - Solution(unsigned length, bool assumeOptimal) : - selections(length), solutionCost(0.0), provedOptimal(assumeOptimal), - r0Reductions(0), r1Reductions(0), r2Reductions(0), rNReductions(0) {} - - void setProvedOptimal(bool provedOptimal) { - this->provedOptimal = provedOptimal; - } - - void setSelection(unsigned nodeID, unsigned selection) { - selections[nodeID] = selection; - } +#include <map> - void setSolutionCost(PBQPNum solutionCost) { - this->solutionCost = solutionCost; - } - - void incR0Reductions() { ++r0Reductions; } - void incR1Reductions() { ++r1Reductions; } - void incR2Reductions() { ++r2Reductions; } - void incRNReductions() { ++rNReductions; } - - unsigned numNodes() const { return selections.size(); } - - unsigned getSelection(unsigned nodeID) const { - return selections[nodeID]; - } - - PBQPNum getCost() const { return solutionCost; } - - bool isProvedOptimal() const { return provedOptimal; } - - unsigned getR0Reductions() const { return r0Reductions; } - unsigned getR1Reductions() const { return r1Reductions; } - unsigned getR2Reductions() const { return r2Reductions; } - unsigned getRNReductions() const { return rNReductions; } - - bool operator==(const Solution &other) const { - return (selections == other.selections); - } - - bool operator!=(const Solution &other) const { - return !(*this == other); - } +namespace PBQP { -}; + /// \brief Represents a solution to a PBQP problem. + /// + /// To get the selection for each node in the problem use the getSelection method. + class Solution { + private: + typedef std::map<Graph::NodeItr, unsigned, NodeItrComparator> SelectionsMap; + SelectionsMap selections; + + public: + + /// \brief Number of nodes for which selections have been made. + /// @return Number of nodes for which selections have been made. + unsigned numNodes() const { return selections.size(); } + + /// \brief Set the selection for a given node. + /// @param nItr Node iterator. + /// @param selection Selection for nItr. + void setSelection(Graph::NodeItr nItr, unsigned selection) { + selections[nItr] = selection; + } + + /// \brief Get a node's selection. + /// @param nItr Node iterator. + /// @return The selection for nItr; + unsigned getSelection(Graph::NodeItr nItr) const { + SelectionsMap::const_iterator sItr = selections.find(nItr); + assert(sItr != selections.end() && "No selection for node."); + return sItr->second; + } + + }; } diff --git a/lib/CodeGen/PBQP/Solver.h b/lib/CodeGen/PBQP/Solver.h deleted file mode 100644 index a445de8..0000000 --- a/lib/CodeGen/PBQP/Solver.h +++ /dev/null @@ -1,31 +0,0 @@ -//===-- Solver.h ------- PBQP solver interface ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - - -#ifndef LLVM_CODEGEN_PBQP_SOLVER_H -#define LLVM_CODEGEN_PBQP_SOLVER_H - -#include "SimpleGraph.h" -#include "Solution.h" - -namespace PBQP { - -/// \brief Interface for solver classes. -class Solver { -public: - - virtual ~Solver() = 0; - virtual Solution solve(const SimpleGraph &orig) const = 0; -}; - -Solver::~Solver() {} - -} - -#endif // LLVM_CODEGEN_PBQP_SOLVER_H diff --git a/lib/CodeGen/PHIElimination.cpp b/lib/CodeGen/PHIElimination.cpp index 365df30..b740c68 100644 --- a/lib/CodeGen/PHIElimination.cpp +++ b/lib/CodeGen/PHIElimination.cpp @@ -21,6 +21,7 @@ #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" #include "llvm/Function.h" #include "llvm/Target/TargetMachine.h" #include "llvm/ADT/SmallPtrSet.h" @@ -95,14 +96,14 @@ bool llvm::PHIElimination::runOnMachineFunction(MachineFunction &Fn) { /// bool llvm::PHIElimination::EliminatePHINodes(MachineFunction &MF, MachineBasicBlock &MBB) { - if (MBB.empty() || MBB.front().getOpcode() != TargetInstrInfo::PHI) + if (MBB.empty() || !MBB.front().isPHI()) return false; // Quick exit for basic blocks without PHIs. // Get an iterator to the first instruction after the last PHI node (this may // also be the end of the basic block). MachineBasicBlock::iterator AfterPHIsIt = SkipPHIsAndLabels(MBB, MBB.begin()); - while (MBB.front().getOpcode() == TargetInstrInfo::PHI) + while (MBB.front().isPHI()) LowerAtomicPHINode(MBB, AfterPHIsIt); return true; @@ -115,7 +116,7 @@ static bool isSourceDefinedByImplicitDef(const MachineInstr *MPhi, for (unsigned i = 1; i != MPhi->getNumOperands(); i += 2) { unsigned SrcReg = MPhi->getOperand(i).getReg(); const MachineInstr *DefMI = MRI->getVRegDef(SrcReg); - if (!DefMI || DefMI->getOpcode() != TargetInstrInfo::IMPLICIT_DEF) + if (!DefMI || !DefMI->isImplicitDef()) return false; } return true; @@ -197,7 +198,7 @@ void llvm::PHIElimination::LowerAtomicPHINode( // If all sources of a PHI node are implicit_def, just emit an // implicit_def instead of a copy. BuildMI(MBB, AfterPHIsIt, MPhi->getDebugLoc(), - TII->get(TargetInstrInfo::IMPLICIT_DEF), DestReg); + TII->get(TargetOpcode::IMPLICIT_DEF), DestReg); else { // Can we reuse an earlier PHI node? This only happens for critical edges, // typically those created by tail duplication. @@ -281,7 +282,7 @@ void llvm::PHIElimination::LowerAtomicPHINode( // If source is defined by an implicit def, there is no need to insert a // copy. MachineInstr *DefMI = MRI->getVRegDef(SrcReg); - if (DefMI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) { + if (DefMI->isImplicitDef()) { ImpDefs.insert(DefMI); continue; } @@ -375,7 +376,7 @@ void llvm::PHIElimination::analyzePHINodes(const MachineFunction& Fn) { for (MachineFunction::const_iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) for (MachineBasicBlock::const_iterator BBI = I->begin(), BBE = I->end(); - BBI != BBE && BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI) + BBI != BBE && BBI->isPHI(); ++BBI) for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) ++VRegPHIUseCount[BBVRegPair(BBI->getOperand(i+1).getMBB()->getNumber(), BBI->getOperand(i).getReg())]; @@ -384,12 +385,11 @@ void llvm::PHIElimination::analyzePHINodes(const MachineFunction& Fn) { bool llvm::PHIElimination::SplitPHIEdges(MachineFunction &MF, MachineBasicBlock &MBB, LiveVariables &LV) { - if (MBB.empty() || MBB.front().getOpcode() != TargetInstrInfo::PHI || - MBB.isLandingPad()) + if (MBB.empty() || !MBB.front().isPHI() || MBB.isLandingPad()) return false; // Quick exit for basic blocks without PHIs. for (MachineBasicBlock::const_iterator BBI = MBB.begin(), BBE = MBB.end(); - BBI != BBE && BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI) { + BBI != BBE && BBI->isPHI(); ++BBI) { for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) { unsigned Reg = BBI->getOperand(i).getReg(); MachineBasicBlock *PreMBB = BBI->getOperand(i+1).getMBB(); @@ -438,7 +438,7 @@ MachineBasicBlock *PHIElimination::SplitCriticalEdge(MachineBasicBlock *A, // Fix PHI nodes in B so they refer to NMBB instead of A for (MachineBasicBlock::iterator i = B->begin(), e = B->end(); - i != e && i->getOpcode() == TargetInstrInfo::PHI; ++i) + i != e && i->isPHI(); ++i) for (unsigned ni = 1, ne = i->getNumOperands(); ni != ne; ni += 2) if (i->getOperand(ni+1).getMBB() == A) i->getOperand(ni+1).setMBB(NMBB); diff --git a/lib/CodeGen/PHIElimination.h b/lib/CodeGen/PHIElimination.h index 1bcc9dc..f3ab9e2 100644 --- a/lib/CodeGen/PHIElimination.h +++ b/lib/CodeGen/PHIElimination.h @@ -14,10 +14,11 @@ #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" namespace llvm { - + class LiveVariables; + /// Lower PHI instructions to copies. class PHIElimination : public MachineFunctionPass { MachineRegisterInfo *MRI; // Machine register information @@ -108,13 +109,29 @@ namespace llvm { // SkipPHIsAndLabels - Copies need to be inserted after phi nodes and // also after any exception handling labels: in landing pads execution // starts at the label, so any copies placed before it won't be executed! + // We also deal with DBG_VALUEs, which are a bit tricky: + // PHI + // DBG_VALUE + // LABEL + // Here the DBG_VALUE needs to be skipped, and if it refers to a PHI it + // needs to be annulled or, better, moved to follow the label, as well. + // PHI + // DBG_VALUE + // no label + // Here it is not a good idea to skip the DBG_VALUE. + // FIXME: For now we skip and annul all DBG_VALUEs, maximally simple and + // maximally stupid. MachineBasicBlock::iterator SkipPHIsAndLabels(MachineBasicBlock &MBB, MachineBasicBlock::iterator I) { // Rather than assuming that EH labels come before other kinds of labels, // just skip all labels. - while (I != MBB.end() && - (I->getOpcode() == TargetInstrInfo::PHI || I->isLabel())) + while (I != MBB.end() && + (I->isPHI() || I->isLabel() || I->isDebugValue())) { + if (I->isDebugValue() && I->getNumOperands()==3 && + I->getOperand(0).isReg()) + I->getOperand(0).setReg(0U); ++I; + } return I; } diff --git a/lib/CodeGen/PreAllocSplitting.cpp b/lib/CodeGen/PreAllocSplitting.cpp index 8cbc8c2..70e91aa 100644 --- a/lib/CodeGen/PreAllocSplitting.cpp +++ b/lib/CodeGen/PreAllocSplitting.cpp @@ -686,8 +686,7 @@ void PreAllocSplitting::ReconstructLiveInterval(LiveInterval* LI) { SlotIndex DefIdx = LIs->getInstructionIndex(&*DI); DefIdx = DefIdx.getDefIndex(); - assert(DI->getOpcode() != TargetInstrInfo::PHI && - "PHI instr in code during pre-alloc splitting."); + assert(!DI->isPHI() && "PHI instr in code during pre-alloc splitting."); VNInfo* NewVN = LI->getNextValue(DefIdx, 0, true, Alloc); // If the def is a move, set the copy field. diff --git a/lib/CodeGen/ProcessImplicitDefs.cpp b/lib/CodeGen/ProcessImplicitDefs.cpp index a00f450..d7179b3 100644 --- a/lib/CodeGen/ProcessImplicitDefs.cpp +++ b/lib/CodeGen/ProcessImplicitDefs.cpp @@ -49,9 +49,9 @@ bool ProcessImplicitDefs::CanTurnIntoImplicitDef(MachineInstr *MI, Reg == SrcReg) return true; - if (OpIdx == 2 && MI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG) + if (OpIdx == 2 && MI->isSubregToReg()) return true; - if (OpIdx == 1 && MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) + if (OpIdx == 1 && MI->isExtractSubreg()) return true; return false; } @@ -88,7 +88,7 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) { I != E; ) { MachineInstr *MI = &*I; ++I; - if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) { + if (MI->isImplicitDef()) { unsigned Reg = MI->getOperand(0).getReg(); ImpDefRegs.insert(Reg); if (TargetRegisterInfo::isPhysicalRegister(Reg)) { @@ -99,7 +99,7 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) { continue; } - if (MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG) { + if (MI->isInsertSubreg()) { MachineOperand &MO = MI->getOperand(2); if (ImpDefRegs.count(MO.getReg())) { // %reg1032<def> = INSERT_SUBREG %reg1032, undef, 2 @@ -127,7 +127,7 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) { // Use is a copy, just turn it into an implicit_def. if (CanTurnIntoImplicitDef(MI, Reg, i, tii_)) { bool isKill = MO.isKill(); - MI->setDesc(tii_->get(TargetInstrInfo::IMPLICIT_DEF)); + MI->setDesc(tii_->get(TargetOpcode::IMPLICIT_DEF)); for (int j = MI->getNumOperands() - 1, ee = 0; j > ee; --j) MI->RemoveOperand(j); if (isKill) { @@ -187,7 +187,7 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) { for (MachineRegisterInfo::def_iterator DI = mri_->def_begin(Reg), DE = mri_->def_end(); DI != DE; ++DI) { MachineInstr *DeadImpDef = &*DI; - if (DeadImpDef->getOpcode() != TargetInstrInfo::IMPLICIT_DEF) { + if (!DeadImpDef->isImplicitDef()) { Skip = true; break; } @@ -205,10 +205,9 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) { // Process each use instruction once. for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(Reg), UE = mri_->use_end(); UI != UE; ++UI) { - MachineInstr *RMI = &*UI; - MachineBasicBlock *RMBB = RMI->getParent(); - if (RMBB == MBB) + if (UI.getOperand().isUndef()) continue; + MachineInstr *RMI = &*UI; if (ModInsts.insert(RMI)) RUses.push_back(RMI); } @@ -220,7 +219,7 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) { unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; if (tii_->isMoveInstr(*RMI, SrcReg, DstReg, SrcSubReg, DstSubReg) && Reg == SrcReg) { - RMI->setDesc(tii_->get(TargetInstrInfo::IMPLICIT_DEF)); + RMI->setDesc(tii_->get(TargetOpcode::IMPLICIT_DEF)); bool isKill = false; SmallVector<unsigned, 4> Ops; @@ -264,8 +263,8 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) { } } RUses.clear(); + ModInsts.clear(); } - ModInsts.clear(); ImpDefRegs.clear(); ImpDefMIs.clear(); } diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp index 709d46a..040259e 100644 --- a/lib/CodeGen/PrologEpilogInserter.cpp +++ b/lib/CodeGen/PrologEpilogInserter.cpp @@ -161,7 +161,7 @@ void PEI::calculateCallsInformation(MachineFunction &Fn) { if (Size > MaxCallFrameSize) MaxCallFrameSize = Size; HasCalls = true; FrameSDOps.push_back(I); - } else if (I->getOpcode() == TargetInstrInfo::INLINEASM) { + } else if (I->isInlineAsm()) { // An InlineAsm might be a call; assume it is to get the stack frame // aligned correctly for calls. HasCalls = true; @@ -476,8 +476,6 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { // Loop over all of the stack objects, assigning sequential addresses... MachineFrameInfo *FFI = Fn.getFrameInfo(); - unsigned MaxAlign = 1; - // Start at the beginning of the local area. // The Offset is the distance from the stack top in the direction // of stack growth -- so it's always nonnegative. @@ -517,9 +515,6 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { Offset += FFI->getObjectSize(i); unsigned Align = FFI->getObjectAlignment(i); - // If the alignment of this object is greater than that of the stack, - // then increase the stack alignment to match. - MaxAlign = std::max(MaxAlign, Align); // Adjust to alignment boundary Offset = (Offset+Align-1)/Align*Align; @@ -529,9 +524,6 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { int MaxCSFI = MaxCSFrameIndex, MinCSFI = MinCSFrameIndex; for (int i = MaxCSFI; i >= MinCSFI ; --i) { unsigned Align = FFI->getObjectAlignment(i); - // If the alignment of this object is greater than that of the stack, - // then increase the stack alignment to match. - MaxAlign = std::max(MaxAlign, Align); // Adjust to alignment boundary Offset = (Offset+Align-1)/Align*Align; @@ -540,6 +532,8 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { } } + unsigned MaxAlign = FFI->getMaxAlignment(); + // Make sure the special register scavenging spill slot is closest to the // frame pointer if a frame pointer is required. const TargetRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo(); @@ -605,11 +599,6 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { // Update frame info to pretend that this is part of the stack... FFI->setStackSize(Offset - LocalAreaOffset); - - // Remember the required stack alignment in case targets need it to perform - // dynamic stack alignment. - if (MaxAlign > FFI->getMaxAlignment()) - FFI->setMaxAlignment(MaxAlign); } diff --git a/lib/CodeGen/RegAllocLocal.cpp b/lib/CodeGen/RegAllocLocal.cpp index cbb5826..04303cf 100644 --- a/lib/CodeGen/RegAllocLocal.cpp +++ b/lib/CodeGen/RegAllocLocal.cpp @@ -490,9 +490,12 @@ MachineInstr *RALocal::reloadVirtReg(MachineBasicBlock &MBB, MachineInstr *MI, // If the virtual register is already available, just update the instruction // and return. if (unsigned PR = getVirt2PhysRegMapSlot(VirtReg)) { - MarkPhysRegRecentlyUsed(PR); // Already have this value available! MI->getOperand(OpNum).setReg(PR); // Assign the input register - getVirtRegLastUse(VirtReg) = std::make_pair(MI, OpNum); + if (!MI->isDebugValue()) { + // Do not do these for DBG_VALUE as they can affect codegen. + MarkPhysRegRecentlyUsed(PR); // Already have this value available! + getVirtRegLastUse(VirtReg) = std::make_pair(MI, OpNum); + } return MI; } @@ -531,7 +534,7 @@ MachineInstr *RALocal::reloadVirtReg(MachineBasicBlock &MBB, MachineInstr *MI, std::string msg; raw_string_ostream Msg(msg); Msg << "Ran out of registers during register allocation!"; - if (MI->getOpcode() == TargetInstrInfo::INLINEASM) { + if (MI->isInlineAsm()) { Msg << "\nPlease check your inline asm statement for invalid " << "constraints:\n"; MI->print(Msg, TM); @@ -544,7 +547,7 @@ MachineInstr *RALocal::reloadVirtReg(MachineBasicBlock &MBB, MachineInstr *MI, std::string msg; raw_string_ostream Msg(msg); Msg << "Ran out of registers during register allocation!"; - if (MI->getOpcode() == TargetInstrInfo::INLINEASM) { + if (MI->isInlineAsm()) { Msg << "\nPlease check your inline asm statement for invalid " << "constraints:\n"; MI->print(Msg, TM); @@ -609,6 +612,8 @@ void RALocal::ComputeLocalLiveness(MachineBasicBlock& MBB) { DenseMap<unsigned, std::pair<MachineInstr*, unsigned> > LastUseDef; for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I) { + if (I->isDebugValue()) + continue; for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { MachineOperand& MO = I->getOperand(i); // Uses don't trigger any flags, but we need to save @@ -691,7 +696,13 @@ void RALocal::ComputeLocalLiveness(MachineBasicBlock& MBB) { bool usedOutsideBlock = isPhysReg ? false : UsedInMultipleBlocks.test(MO.getReg() - TargetRegisterInfo::FirstVirtualRegister); - if (!isPhysReg && !usedOutsideBlock) + if (!isPhysReg && !usedOutsideBlock) { + // DBG_VALUE complicates this: if the only refs of a register outside + // this block are DBG_VALUE, we can't keep the reg live just for that, + // as it will cause the reg to be spilled at the end of this block when + // it wouldn't have been otherwise. Nullify the DBG_VALUEs when that + // happens. + bool UsedByDebugValueOnly = false; for (MachineRegisterInfo::reg_iterator UI = MRI.reg_begin(MO.getReg()), UE = MRI.reg_end(); UI != UE; ++UI) // Two cases: @@ -699,12 +710,26 @@ void RALocal::ComputeLocalLiveness(MachineBasicBlock& MBB) { // - used in the same block before it is defined (loop) if (UI->getParent() != &MBB || (MO.isDef() && UI.getOperand().isUse() && precedes(&*UI, MI))) { + if (UI->isDebugValue()) { + UsedByDebugValueOnly = true; + continue; + } + // A non-DBG_VALUE use means we can leave DBG_VALUE uses alone. UsedInMultipleBlocks.set(MO.getReg() - TargetRegisterInfo::FirstVirtualRegister); usedOutsideBlock = true; + UsedByDebugValueOnly = false; break; } - + if (UsedByDebugValueOnly) + for (MachineRegisterInfo::reg_iterator UI = MRI.reg_begin(MO.getReg()), + UE = MRI.reg_end(); UI != UE; ++UI) + if (UI->isDebugValue() && + (UI->getParent() != &MBB || + (MO.isDef() && precedes(&*UI, MI)))) + UI.getOperand().setReg(0U); + } + // Physical registers and those that are not live-out of the block // are killed/dead at their last use/def within this block. if (isPhysReg || !usedOutsideBlock) { @@ -764,8 +789,11 @@ void RALocal::AllocateBasicBlock(MachineBasicBlock &MBB) { // Determine whether this is a copy instruction. The cases where the // source or destination are phys regs are handled specially. unsigned SrcCopyReg, DstCopyReg, SrcCopySubReg, DstCopySubReg; + unsigned SrcCopyPhysReg = 0U; bool isCopy = TII->isMoveInstr(*MI, SrcCopyReg, DstCopyReg, SrcCopySubReg, DstCopySubReg); + if (isCopy && TargetRegisterInfo::isVirtualRegister(SrcCopyReg)) + SrcCopyPhysReg = getVirt2PhysRegMapSlot(SrcCopyReg); // Loop over the implicit uses, making sure that they are at the head of the // use order list, so they don't get reallocated. @@ -793,7 +821,7 @@ void RALocal::AllocateBasicBlock(MachineBasicBlock &MBB) { // have in them, then mark them unallocatable. // If any virtual regs are earlyclobber, allocate them now (before // freeing inputs that are killed). - if (MI->getOpcode()==TargetInstrInfo::INLINEASM) { + if (MI->isInlineAsm()) { for (unsigned i = 0; i != MI->getNumOperands(); ++i) { MachineOperand& MO = MI->getOperand(i); if (MO.isReg() && MO.isDef() && MO.isEarlyClobber() && @@ -838,6 +866,18 @@ void RALocal::AllocateBasicBlock(MachineBasicBlock &MBB) { } } + // If a DBG_VALUE says something is located in a spilled register, + // change the DBG_VALUE to be undef, which prevents the register + // from being reloaded here. Doing that would change the generated + // code, unless another use immediately follows this instruction. + if (MI->isDebugValue() && + MI->getNumOperands()==3 && MI->getOperand(0).isReg()) { + unsigned VirtReg = MI->getOperand(0).getReg(); + if (VirtReg && TargetRegisterInfo::isVirtualRegister(VirtReg) && + !getVirt2PhysRegMapSlot(VirtReg)) + MI->getOperand(0).setReg(0U); + } + // Get the used operands into registers. This has the potential to spill // incoming values if we are out of registers. Note that we completely // ignore physical register uses here. We assume that if an explicit @@ -965,13 +1005,26 @@ void RALocal::AllocateBasicBlock(MachineBasicBlock &MBB) { // If DestVirtReg already has a value, use it. if (!(DestPhysReg = getVirt2PhysRegMapSlot(DestVirtReg))) { + // If this is a copy try to reuse the input as the output; + // that will make the copy go away. // If this is a copy, the source reg is a phys reg, and // that reg is available, use that phys reg for DestPhysReg. + // If this is a copy, the source reg is a virtual reg, and + // the phys reg that was assigned to that virtual reg is now + // available, use that phys reg for DestPhysReg. (If it's now + // available that means this was the last use of the source.) if (isCopy && TargetRegisterInfo::isPhysicalRegister(SrcCopyReg) && isPhysRegAvailable(SrcCopyReg)) { DestPhysReg = SrcCopyReg; assignVirtToPhysReg(DestVirtReg, DestPhysReg); + } else if (isCopy && + TargetRegisterInfo::isVirtualRegister(SrcCopyReg) && + SrcCopyPhysReg && isPhysRegAvailable(SrcCopyPhysReg) && + MF->getRegInfo().getRegClass(DestVirtReg)-> + contains(SrcCopyPhysReg)) { + DestPhysReg = SrcCopyPhysReg; + assignVirtToPhysReg(DestVirtReg, DestPhysReg); } else DestPhysReg = getReg(MBB, MI, DestVirtReg); } diff --git a/lib/CodeGen/RegAllocPBQP.cpp b/lib/CodeGen/RegAllocPBQP.cpp index fc59653..2701faf 100644 --- a/lib/CodeGen/RegAllocPBQP.cpp +++ b/lib/CodeGen/RegAllocPBQP.cpp @@ -32,7 +32,7 @@ #define DEBUG_TYPE "regalloc" #include "PBQP/HeuristicSolver.h" -#include "PBQP/SimpleGraph.h" +#include "PBQP/Graph.h" #include "PBQP/Heuristics/Briggs.h" #include "VirtRegMap.h" #include "VirtRegRewriter.h" @@ -58,12 +58,12 @@ using namespace llvm; static RegisterRegAlloc registerPBQPRepAlloc("pbqp", "PBQP register allocator.", - llvm::createPBQPRegisterAllocator); + llvm::createPBQPRegisterAllocator); static cl::opt<bool> pbqpCoalescing("pbqp-coalescing", - cl::desc("Attempt coalescing during PBQP register allocation."), - cl::init(false), cl::Hidden); + cl::desc("Attempt coalescing during PBQP register allocation."), + cl::init(false), cl::Hidden); namespace { @@ -114,6 +114,8 @@ namespace { typedef std::set<LiveInterval*> LiveIntervalSet; + typedef std::vector<PBQP::Graph::NodeItr> NodeVector; + MachineFunction *mf; const TargetMachine *tm; const TargetRegisterInfo *tri; @@ -130,6 +132,7 @@ namespace { AllowedSetMap allowedSets; LiveIntervalSet vregIntervalsToAlloc, emptyVRegIntervals; + NodeVector problemNodes; /// Builds a PBQP cost vector. @@ -174,7 +177,7 @@ namespace { /// allocation problem for this function. /// /// @return a PBQP solver object for the register allocation problem. - PBQP::SimpleGraph constructPBQPProblem(); + PBQP::Graph constructPBQPProblem(); /// \brief Adds a stack interval if the given live interval has been /// spilled. Used to support stack slot coloring. @@ -408,16 +411,16 @@ PBQPRegAlloc::CoalesceMap PBQPRegAlloc::findCoalesces() { // We also need any physical regs to be allocable, coalescing with // a non-allocable register is invalid. if (srcRegIsPhysical) { - if (std::find(srcRegClass->allocation_order_begin(*mf), - srcRegClass->allocation_order_end(*mf), srcReg) == - srcRegClass->allocation_order_end(*mf)) + if (std::find(dstRegClass->allocation_order_begin(*mf), + dstRegClass->allocation_order_end(*mf), srcReg) == + dstRegClass->allocation_order_end(*mf)) continue; } if (dstRegIsPhysical) { - if (std::find(dstRegClass->allocation_order_begin(*mf), - dstRegClass->allocation_order_end(*mf), dstReg) == - dstRegClass->allocation_order_end(*mf)) + if (std::find(srcRegClass->allocation_order_begin(*mf), + srcRegClass->allocation_order_end(*mf), dstReg) == + srcRegClass->allocation_order_end(*mf)) continue; } @@ -439,6 +442,12 @@ PBQPRegAlloc::CoalesceMap PBQPRegAlloc::findCoalesces() { vniItr = srcLI->vni_begin(), vniEnd = srcLI->vni_end(); vniItr != vniEnd; ++vniItr) { + // If we find a poorly defined def we err on the side of caution. + if (!(*vniItr)->def.isValid()) { + badDef = true; + break; + } + // If we find a def that kills the coalescing opportunity then // record it and break from the loop. if (dstLI->liveAt((*vniItr)->def)) { @@ -460,6 +469,11 @@ PBQPRegAlloc::CoalesceMap PBQPRegAlloc::findCoalesces() { if ((*vniItr)->getCopy() == instr) continue; + if (!(*vniItr)->def.isValid()) { + badDef = true; + break; + } + if (srcLI->liveAt((*vniItr)->def)) { badDef = true; break; @@ -510,11 +524,10 @@ void PBQPRegAlloc::findVRegIntervalsToAlloc() { } } -PBQP::SimpleGraph PBQPRegAlloc::constructPBQPProblem() { +PBQP::Graph PBQPRegAlloc::constructPBQPProblem() { typedef std::vector<const LiveInterval*> LIVector; typedef std::vector<unsigned> RegVector; - typedef std::vector<PBQP::SimpleGraph::NodeIterator> NodeVector; // This will store the physical intervals for easy reference. LIVector physIntervals; @@ -553,8 +566,8 @@ PBQP::SimpleGraph PBQPRegAlloc::constructPBQPProblem() { } // Construct a PBQP solver for this problem - PBQP::SimpleGraph problem; - NodeVector problemNodes(vregIntervalsToAlloc.size()); + PBQP::Graph problem; + problemNodes.resize(vregIntervalsToAlloc.size()); // Resize allowedSets container appropriately. allowedSets.resize(vregIntervalsToAlloc.size()); @@ -657,12 +670,7 @@ PBQP::SimpleGraph PBQPRegAlloc::constructPBQPProblem() { } } - problem.assignNodeIDs(); - assert(problem.getNumNodes() == allowedSets.size()); - for (unsigned i = 0; i < allowedSets.size(); ++i) { - assert(problem.getNodeItr(i) == problemNodes[i]); - } /* std::cerr << "Allocating for " << problem.getNumNodes() << " nodes, " << problem.getNumEdges() << " edges.\n"; @@ -696,10 +704,6 @@ void PBQPRegAlloc::addStackInterval(const LiveInterval *spilled, bool PBQPRegAlloc::mapPBQPToRegAlloc(const PBQP::Solution &solution) { - // Assert that this is a valid solution to the regalloc problem. - assert(solution.getCost() != std::numeric_limits<PBQP::PBQPNum>::infinity() && - "Invalid (infinite cost) solution for PBQP problem."); - // Set to true if we have any spills bool anotherRoundNeeded = false; @@ -709,7 +713,7 @@ bool PBQPRegAlloc::mapPBQPToRegAlloc(const PBQP::Solution &solution) { // Iterate over the nodes mapping the PBQP solution to a register assignment. for (unsigned node = 0; node < node2LI.size(); ++node) { unsigned virtReg = node2LI[node]->reg, - allocSelection = solution.getSelection(node); + allocSelection = solution.getSelection(problemNodes[node]); // If the PBQP solution is non-zero it's a physical register... @@ -849,7 +853,7 @@ bool PBQPRegAlloc::runOnMachineFunction(MachineFunction &MF) { vrm = &getAnalysis<VirtRegMap>(); - DEBUG(dbgs() << "PBQP2 Register Allocating for " << mf->getFunction()->getName() << "\n"); + DEBUG(dbgs() << "PBQP Register Allocating for " << mf->getFunction()->getName() << "\n"); // Allocator main loop: // @@ -876,10 +880,9 @@ bool PBQPRegAlloc::runOnMachineFunction(MachineFunction &MF) { while (!pbqpAllocComplete) { DEBUG(dbgs() << " PBQP Regalloc round " << round << ":\n"); - PBQP::SimpleGraph problem = constructPBQPProblem(); - PBQP::HeuristicSolver<PBQP::Heuristics::Briggs> solver; - problem.assignNodeIDs(); - PBQP::Solution solution = solver.solve(problem); + PBQP::Graph problem = constructPBQPProblem(); + PBQP::Solution solution = + PBQP::HeuristicSolver<PBQP::Heuristics::Briggs>::solve(problem); pbqpAllocComplete = mapPBQPToRegAlloc(solution); @@ -895,6 +898,7 @@ bool PBQPRegAlloc::runOnMachineFunction(MachineFunction &MF) { li2Node.clear(); node2LI.clear(); allowedSets.clear(); + problemNodes.clear(); DEBUG(dbgs() << "Post alloc VirtRegMap:\n" << *vrm << "\n"); diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 8883064..7da7848 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -1881,7 +1881,8 @@ SDValue DAGCombiner::visitAND(SDNode *N) { LN0->getChain(), LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), MemVT, - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); AddToWorkList(N); CombineTo(N0.getNode(), ExtLoad, ExtLoad.getValue(1)); return SDValue(N, 0); // Return N so it doesn't get rechecked! @@ -1903,7 +1904,8 @@ SDValue DAGCombiner::visitAND(SDNode *N) { LN0->getChain(), LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), MemVT, - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); AddToWorkList(N); CombineTo(N0.getNode(), ExtLoad, ExtLoad.getValue(1)); return SDValue(N, 0); // Return N so it doesn't get rechecked! @@ -1935,7 +1937,8 @@ SDValue DAGCombiner::visitAND(SDNode *N) { DAG.getExtLoad(ISD::ZEXTLOAD, LN0->getDebugLoc(), LoadResultTy, LN0->getChain(), LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), - ExtVT, LN0->isVolatile(), LN0->getAlignment()); + ExtVT, LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); AddToWorkList(N); CombineTo(LN0, NewLoad, NewLoad.getValue(1)); return SDValue(N, 0); // Return N so it doesn't get rechecked! @@ -1970,7 +1973,8 @@ SDValue DAGCombiner::visitAND(SDNode *N) { DAG.getExtLoad(ISD::ZEXTLOAD, LN0->getDebugLoc(), LoadResultTy, LN0->getChain(), NewPtr, LN0->getSrcValue(), LN0->getSrcValueOffset(), - ExtVT, LN0->isVolatile(), Alignment); + ExtVT, LN0->isVolatile(), LN0->isNonTemporal(), + Alignment); AddToWorkList(N); CombineTo(LN0, Load, Load.getValue(1)); return SDValue(N, 0); // Return N so it doesn't get rechecked! @@ -2640,7 +2644,7 @@ SDValue DAGCombiner::visitSRA(SDNode *N) { // If the shift is not a no-op (in which case this should be just a sign // extend already), the truncated to type is legal, sign_extend is legal - // on that type, and the the truncate to that type is both legal and free, + // on that type, and the truncate to that type is both legal and free, // perform the transform. if ((ShiftAmt > 0) && TLI.isOperationLegalOrCustom(ISD::SIGN_EXTEND, TruncVT) && @@ -3143,7 +3147,8 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) { LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), N0.getValueType(), - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); CombineTo(N, ExtLoad); SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), N0.getValueType(), ExtLoad); @@ -3185,7 +3190,8 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) { LN0->getChain(), LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), MemVT, - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); CombineTo(N, ExtLoad); CombineTo(N0.getNode(), DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), @@ -3220,6 +3226,14 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) { NegOne, DAG.getConstant(0, VT), cast<CondCodeSDNode>(N0.getOperand(2))->get(), true); if (SCC.getNode()) return SCC; + if (!LegalOperations || + TLI.isOperationLegal(ISD::SETCC, TLI.getSetCCResultType(VT))) + return DAG.getNode(ISD::SELECT, N->getDebugLoc(), VT, + DAG.getSetCC(N->getDebugLoc(), + TLI.getSetCCResultType(VT), + N0.getOperand(0), N0.getOperand(1), + cast<CondCodeSDNode>(N0.getOperand(2))->get()), + NegOne, DAG.getConstant(0, VT)); } @@ -3307,7 +3321,8 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), N0.getValueType(), - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); CombineTo(N, ExtLoad); SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), N0.getValueType(), ExtLoad); @@ -3349,7 +3364,8 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { LN0->getChain(), LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), MemVT, - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); CombineTo(N, ExtLoad); CombineTo(N0.getNode(), DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), N0.getValueType(), @@ -3463,7 +3479,8 @@ SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) { LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), N0.getValueType(), - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); CombineTo(N, ExtLoad); SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), N0.getValueType(), ExtLoad); @@ -3505,7 +3522,8 @@ SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) { VT, LN0->getChain(), LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), MemVT, - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); CombineTo(N, ExtLoad); CombineTo(N0.getNode(), DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), @@ -3628,10 +3646,11 @@ SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) { SDValue Load = (ExtType == ISD::NON_EXTLOAD) ? DAG.getLoad(VT, N0.getDebugLoc(), LN0->getChain(), NewPtr, LN0->getSrcValue(), LN0->getSrcValueOffset() + PtrOff, - LN0->isVolatile(), NewAlign) + LN0->isVolatile(), LN0->isNonTemporal(), NewAlign) : DAG.getExtLoad(ExtType, N0.getDebugLoc(), VT, LN0->getChain(), NewPtr, LN0->getSrcValue(), LN0->getSrcValueOffset() + PtrOff, - ExtVT, LN0->isVolatile(), NewAlign); + ExtVT, LN0->isVolatile(), LN0->isNonTemporal(), + NewAlign); // Replace the old load's chain with the new load's chain. WorkListRemover DeadNodes(*this); @@ -3718,7 +3737,8 @@ SDValue DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *N) { LN0->getChain(), LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), EVT, - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); CombineTo(N, ExtLoad); CombineTo(N0.getNode(), ExtLoad, ExtLoad.getValue(1)); return SDValue(N, 0); // Return N so it doesn't get rechecked! @@ -3734,7 +3754,8 @@ SDValue DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *N) { LN0->getChain(), LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), EVT, - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); CombineTo(N, ExtLoad); CombineTo(N0.getNode(), ExtLoad, ExtLoad.getValue(1)); return SDValue(N, 0); // Return N so it doesn't get rechecked! @@ -3818,7 +3839,7 @@ SDValue DAGCombiner::CombineConsecutiveLoads(SDNode *N, EVT VT) { (!LegalOperations || TLI.isOperationLegal(ISD::LOAD, VT))) return DAG.getLoad(VT, N->getDebugLoc(), LD1->getChain(), LD1->getBasePtr(), LD1->getSrcValue(), - LD1->getSrcValueOffset(), false, Align); + LD1->getSrcValueOffset(), false, false, Align); } return SDValue(); @@ -3888,7 +3909,8 @@ SDValue DAGCombiner::visitBIT_CONVERT(SDNode *N) { SDValue Load = DAG.getLoad(VT, N->getDebugLoc(), LN0->getChain(), LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), - LN0->isVolatile(), OrigAlign); + LN0->isVolatile(), LN0->isNonTemporal(), + OrigAlign); AddToWorkList(N); CombineTo(N0.getNode(), DAG.getNode(ISD::BIT_CONVERT, N0.getDebugLoc(), @@ -4484,7 +4506,8 @@ SDValue DAGCombiner::visitFP_EXTEND(SDNode *N) { LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), N0.getValueType(), - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); CombineTo(N, ExtLoad); CombineTo(N0.getNode(), DAG.getNode(ISD::FP_ROUND, N0.getDebugLoc(), @@ -4952,7 +4975,7 @@ SDValue DAGCombiner::visitLOAD(SDNode *N) { LD->getValueType(0), Chain, Ptr, LD->getSrcValue(), LD->getSrcValueOffset(), LD->getMemoryVT(), - LD->isVolatile(), Align); + LD->isVolatile(), LD->isNonTemporal(), Align); } } @@ -5034,7 +5057,8 @@ SDValue DAGCombiner::visitLOAD(SDNode *N) { ReplLoad = DAG.getLoad(N->getValueType(0), LD->getDebugLoc(), BetterChain, Ptr, LD->getSrcValue(), LD->getSrcValueOffset(), - LD->isVolatile(), LD->getAlignment()); + LD->isVolatile(), LD->isNonTemporal(), + LD->getAlignment()); } else { ReplLoad = DAG.getExtLoad(LD->getExtensionType(), LD->getDebugLoc(), LD->getValueType(0), @@ -5042,6 +5066,7 @@ SDValue DAGCombiner::visitLOAD(SDNode *N) { LD->getSrcValueOffset(), LD->getMemoryVT(), LD->isVolatile(), + LD->isNonTemporal(), LD->getAlignment()); } @@ -5141,13 +5166,14 @@ SDValue DAGCombiner::ReduceLoadOpStoreWidth(SDNode *N) { SDValue NewLD = DAG.getLoad(NewVT, N0.getDebugLoc(), LD->getChain(), NewPtr, LD->getSrcValue(), LD->getSrcValueOffset(), - LD->isVolatile(), NewAlign); + LD->isVolatile(), LD->isNonTemporal(), + NewAlign); SDValue NewVal = DAG.getNode(Opc, Value.getDebugLoc(), NewVT, NewLD, DAG.getConstant(NewImm, NewVT)); SDValue NewST = DAG.getStore(Chain, N->getDebugLoc(), NewVal, NewPtr, ST->getSrcValue(), ST->getSrcValueOffset(), - false, NewAlign); + false, false, NewAlign); AddToWorkList(NewPtr.getNode()); AddToWorkList(NewLD.getNode()); @@ -5176,7 +5202,7 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { return DAG.getTruncStore(Chain, N->getDebugLoc(), Value, Ptr, ST->getSrcValue(), ST->getSrcValueOffset(), ST->getMemoryVT(), - ST->isVolatile(), Align); + ST->isVolatile(), ST->isNonTemporal(), Align); } } @@ -5193,7 +5219,8 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { TLI.isOperationLegalOrCustom(ISD::STORE, SVT))) return DAG.getStore(Chain, N->getDebugLoc(), Value.getOperand(0), Ptr, ST->getSrcValue(), - ST->getSrcValueOffset(), ST->isVolatile(), OrigAlign); + ST->getSrcValueOffset(), ST->isVolatile(), + ST->isNonTemporal(), OrigAlign); } // Turn 'store float 1.0, Ptr' -> 'store int 0x12345678, Ptr' @@ -5219,7 +5246,7 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { return DAG.getStore(Chain, N->getDebugLoc(), Tmp, Ptr, ST->getSrcValue(), ST->getSrcValueOffset(), ST->isVolatile(), - ST->getAlignment()); + ST->isNonTemporal(), ST->getAlignment()); } break; case MVT::f64: @@ -5231,7 +5258,7 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { return DAG.getStore(Chain, N->getDebugLoc(), Tmp, Ptr, ST->getSrcValue(), ST->getSrcValueOffset(), ST->isVolatile(), - ST->getAlignment()); + ST->isNonTemporal(), ST->getAlignment()); } else if (!ST->isVolatile() && TLI.isOperationLegalOrCustom(ISD::STORE, MVT::i32)) { // Many FP stores are not made apparent until after legalize, e.g. for @@ -5245,18 +5272,21 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { int SVOffset = ST->getSrcValueOffset(); unsigned Alignment = ST->getAlignment(); bool isVolatile = ST->isVolatile(); + bool isNonTemporal = ST->isNonTemporal(); SDValue St0 = DAG.getStore(Chain, ST->getDebugLoc(), Lo, Ptr, ST->getSrcValue(), ST->getSrcValueOffset(), - isVolatile, ST->getAlignment()); + isVolatile, isNonTemporal, + ST->getAlignment()); Ptr = DAG.getNode(ISD::ADD, N->getDebugLoc(), Ptr.getValueType(), Ptr, DAG.getConstant(4, Ptr.getValueType())); SVOffset += 4; Alignment = MinAlign(Alignment, 4U); SDValue St1 = DAG.getStore(Chain, ST->getDebugLoc(), Hi, Ptr, ST->getSrcValue(), - SVOffset, isVolatile, Alignment); + SVOffset, isVolatile, isNonTemporal, + Alignment); return DAG.getNode(ISD::TokenFactor, N->getDebugLoc(), MVT::Other, St0, St1); } @@ -5278,12 +5308,13 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { if (ST->isTruncatingStore()) { ReplStore = DAG.getTruncStore(BetterChain, N->getDebugLoc(), Value, Ptr, ST->getSrcValue(),ST->getSrcValueOffset(), - ST->getMemoryVT(), - ST->isVolatile(), ST->getAlignment()); + ST->getMemoryVT(), ST->isVolatile(), + ST->isNonTemporal(), ST->getAlignment()); } else { ReplStore = DAG.getStore(BetterChain, N->getDebugLoc(), Value, Ptr, ST->getSrcValue(), ST->getSrcValueOffset(), - ST->isVolatile(), ST->getAlignment()); + ST->isVolatile(), ST->isNonTemporal(), + ST->getAlignment()); } // Create token to keep both nodes around. @@ -5317,7 +5348,8 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { return DAG.getTruncStore(Chain, N->getDebugLoc(), Shorter, Ptr, ST->getSrcValue(), ST->getSrcValueOffset(), ST->getMemoryVT(), - ST->isVolatile(), ST->getAlignment()); + ST->isVolatile(), ST->isNonTemporal(), + ST->getAlignment()); // Otherwise, see if we can simplify the operation with // SimplifyDemandedBits, which only works if the value has a single use. @@ -5350,7 +5382,8 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { return DAG.getTruncStore(Chain, N->getDebugLoc(), Value.getOperand(0), Ptr, ST->getSrcValue(), ST->getSrcValueOffset(), ST->getMemoryVT(), - ST->isVolatile(), ST->getAlignment()); + ST->isVolatile(), ST->isNonTemporal(), + ST->getAlignment()); } return ReduceLoadOpStoreWidth(N); @@ -5395,12 +5428,16 @@ SDValue DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *N) { SDValue InVec = N->getOperand(0); if (InVec.getOpcode() == ISD::SCALAR_TO_VECTOR) { - // If the operand is wider than the vector element type then it is implicitly - // truncated. Make that explicit here. + // Check if the result type doesn't match the inserted element type. A + // SCALAR_TO_VECTOR may truncate the inserted element and the + // EXTRACT_VECTOR_ELT may widen the extracted vector. EVT EltVT = InVec.getValueType().getVectorElementType(); SDValue InOp = InVec.getOperand(0); - if (InOp.getValueType() != EltVT) - return DAG.getNode(ISD::TRUNCATE, InVec.getDebugLoc(), EltVT, InOp); + EVT NVT = N->getValueType(0); + if (InOp.getValueType() != NVT) { + assert(InOp.getValueType().isInteger() && NVT.isInteger()); + return DAG.getSExtOrTrunc(InOp, InVec.getDebugLoc(), NVT); + } return InOp; } @@ -5491,7 +5528,7 @@ SDValue DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *N) { return DAG.getLoad(LVT, N->getDebugLoc(), LN0->getChain(), NewPtr, LN0->getSrcValue(), LN0->getSrcValueOffset(), - LN0->isVolatile(), Align); + LN0->isVolatile(), LN0->isNonTemporal(), Align); } return SDValue(); @@ -5871,6 +5908,7 @@ bool DAGCombiner::SimplifySelectOps(SDNode *TheSelect, SDValue LHS, LLD->getChain(), Addr, 0, 0, LLD->isVolatile(), + LLD->isNonTemporal(), LLD->getAlignment()); } else { Load = DAG.getExtLoad(LLD->getExtensionType(), @@ -5879,6 +5917,7 @@ bool DAGCombiner::SimplifySelectOps(SDNode *TheSelect, SDValue LHS, LLD->getChain(), Addr, 0, 0, LLD->getMemoryVT(), LLD->isVolatile(), + LLD->isNonTemporal(), LLD->getAlignment()); } @@ -5986,7 +6025,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, CstOffset); return DAG.getLoad(TV->getValueType(0), DL, DAG.getEntryNode(), CPIdx, PseudoSourceValue::getConstantPool(), 0, false, - Alignment); + false, Alignment); } } diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index 09fd657..35ef5b7 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -121,7 +121,7 @@ unsigned FastISel::getRegForValue(Value *V) { Reg = LocalValueMap[CE]; } else if (isa<UndefValue>(V)) { Reg = createResultReg(TLI.getRegClassFor(VT)); - BuildMI(MBB, DL, TII.get(TargetInstrInfo::IMPLICIT_DEF), Reg); + BuildMI(MBB, DL, TII.get(TargetOpcode::IMPLICIT_DEF), Reg); } // If target-independent code couldn't handle the value, give target-specific @@ -332,6 +332,8 @@ bool FastISel::SelectCall(User *I) { return true; Value *Address = DI->getAddress(); + if (!Address) + return true; AllocaInst *AI = dyn_cast<AllocaInst>(Address); // Don't handle byval struct arguments or VLAs, for example. if (!AI) break; @@ -343,6 +345,9 @@ bool FastISel::SelectCall(User *I) { if (MDNode *Dbg = DI->getMetadata("dbg")) MMI->setVariableDbgInfo(DI->getVariable(), FI, Dbg); } + // Building the map above is target independent. Generating DBG_VALUE + // inline is target dependent; do this now. + (void)TargetSelectInstruction(cast<Instruction>(I)); return true; } case Intrinsic::eh_exception: { @@ -966,7 +971,7 @@ unsigned FastISel::FastEmitInst_extractsubreg(MVT RetVT, const TargetRegisterClass* RC = MRI.getRegClass(Op0); unsigned ResultReg = createResultReg(TLI.getRegClassFor(RetVT)); - const TargetInstrDesc &II = TII.get(TargetInstrInfo::EXTRACT_SUBREG); + const TargetInstrDesc &II = TII.get(TargetOpcode::EXTRACT_SUBREG); if (II.getNumDefs() >= 1) BuildMI(MBB, DL, II, ResultReg).addReg(Op0).addImm(Idx); diff --git a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index dc7d82d..50f4c32 100644 --- a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -227,7 +227,7 @@ void FunctionLoweringInfo::set(Function &fn, MachineFunction &mf, unsigned NumRegisters = TLI.getNumRegisters(Fn->getContext(), VT); const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); for (unsigned i = 0; i != NumRegisters; ++i) - BuildMI(MBB, DL, TII->get(TargetInstrInfo::PHI), PHIReg + i); + BuildMI(MBB, DL, TII->get(TargetOpcode::PHI), PHIReg + i); PHIReg += NumRegisters; } } diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp index 9c50936..02fe85d 100644 --- a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -178,7 +178,7 @@ void InstrEmitter::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI, const TargetInstrDesc &II, bool IsClone, bool IsCloned, DenseMap<SDValue, unsigned> &VRBaseMap) { - assert(Node->getMachineOpcode() != TargetInstrInfo::IMPLICIT_DEF && + assert(Node->getMachineOpcode() != TargetOpcode::IMPLICIT_DEF && "IMPLICIT_DEF should have been handled as a special case elsewhere!"); for (unsigned i = 0; i < II.getNumDefs(); ++i) { @@ -236,7 +236,7 @@ void InstrEmitter::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI, unsigned InstrEmitter::getVR(SDValue Op, DenseMap<SDValue, unsigned> &VRBaseMap) { if (Op.isMachineOpcode() && - Op.getMachineOpcode() == TargetInstrInfo::IMPLICIT_DEF) { + Op.getMachineOpcode() == TargetOpcode::IMPLICIT_DEF) { // Add an IMPLICIT_DEF instruction before every use. unsigned VReg = getDstOfOnlyCopyToRegUse(Op.getNode(), Op.getResNo()); // IMPLICIT_DEF can produce any type of result so its TargetInstrDesc @@ -246,7 +246,7 @@ unsigned InstrEmitter::getVR(SDValue Op, VReg = MRI->createVirtualRegister(RC); } BuildMI(MBB, Op.getDebugLoc(), - TII->get(TargetInstrInfo::IMPLICIT_DEF), VReg); + TII->get(TargetOpcode::IMPLICIT_DEF), VReg); return VReg; } @@ -396,12 +396,12 @@ void InstrEmitter::EmitSubregNode(SDNode *Node, } } - if (Opc == TargetInstrInfo::EXTRACT_SUBREG) { + if (Opc == TargetOpcode::EXTRACT_SUBREG) { unsigned SubIdx = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue(); // Create the extract_subreg machine instruction. MachineInstr *MI = BuildMI(*MF, Node->getDebugLoc(), - TII->get(TargetInstrInfo::EXTRACT_SUBREG)); + TII->get(TargetOpcode::EXTRACT_SUBREG)); // Figure out the register class to create for the destreg. unsigned VReg = getVR(Node->getOperand(0), VRBaseMap); @@ -424,8 +424,8 @@ void InstrEmitter::EmitSubregNode(SDNode *Node, AddOperand(MI, Node->getOperand(0), 0, 0, VRBaseMap); MI->addOperand(MachineOperand::CreateImm(SubIdx)); MBB->insert(InsertPos, MI); - } else if (Opc == TargetInstrInfo::INSERT_SUBREG || - Opc == TargetInstrInfo::SUBREG_TO_REG) { + } else if (Opc == TargetOpcode::INSERT_SUBREG || + Opc == TargetOpcode::SUBREG_TO_REG) { SDValue N0 = Node->getOperand(0); SDValue N1 = Node->getOperand(1); SDValue N2 = Node->getOperand(2); @@ -452,7 +452,7 @@ void InstrEmitter::EmitSubregNode(SDNode *Node, // If creating a subreg_to_reg, then the first input operand // is an implicit value immediate, otherwise it's a register - if (Opc == TargetInstrInfo::SUBREG_TO_REG) { + if (Opc == TargetOpcode::SUBREG_TO_REG) { const ConstantSDNode *SD = cast<ConstantSDNode>(N0); MI->addOperand(MachineOperand::CreateImm(SD->getZExtValue())); } else @@ -507,20 +507,20 @@ void InstrEmitter::EmitNode(SDNode *Node, bool IsClone, bool IsCloned, unsigned Opc = Node->getMachineOpcode(); // Handle subreg insert/extract specially - if (Opc == TargetInstrInfo::EXTRACT_SUBREG || - Opc == TargetInstrInfo::INSERT_SUBREG || - Opc == TargetInstrInfo::SUBREG_TO_REG) { + if (Opc == TargetOpcode::EXTRACT_SUBREG || + Opc == TargetOpcode::INSERT_SUBREG || + Opc == TargetOpcode::SUBREG_TO_REG) { EmitSubregNode(Node, VRBaseMap); return; } // Handle COPY_TO_REGCLASS specially. - if (Opc == TargetInstrInfo::COPY_TO_REGCLASS) { + if (Opc == TargetOpcode::COPY_TO_REGCLASS) { EmitCopyToRegClassNode(Node, VRBaseMap); return; } - if (Opc == TargetInstrInfo::IMPLICIT_DEF) + if (Opc == TargetOpcode::IMPLICIT_DEF) // We want a unique VR for each IMPLICIT_DEF use. return; @@ -640,7 +640,7 @@ void InstrEmitter::EmitNode(SDNode *Node, bool IsClone, bool IsCloned, // Create the inline asm machine instruction. MachineInstr *MI = BuildMI(*MF, Node->getDebugLoc(), - TII->get(TargetInstrInfo::INLINEASM)); + TII->get(TargetOpcode::INLINEASM)); // Add the asm string as an external symbol operand. const char *AsmStr = diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 5e3f58a..e9321da 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -377,9 +377,10 @@ static SDValue ExpandConstantFP(ConstantFPSDNode *CFP, bool UseCP, return DAG.getExtLoad(ISD::EXTLOAD, dl, OrigVT, DAG.getEntryNode(), CPIdx, PseudoSourceValue::getConstantPool(), - 0, VT, false, Alignment); + 0, VT, false, false, Alignment); return DAG.getLoad(OrigVT, dl, DAG.getEntryNode(), CPIdx, - PseudoSourceValue::getConstantPool(), 0, false, Alignment); + PseudoSourceValue::getConstantPool(), 0, false, false, + Alignment); } /// ExpandUnalignedStore - Expands an unaligned store to 2 half-size stores. @@ -402,7 +403,8 @@ SDValue ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG, // FIXME: Does not handle truncating floating point stores! SDValue Result = DAG.getNode(ISD::BIT_CONVERT, dl, intVT, Val); return DAG.getStore(Chain, dl, Result, Ptr, ST->getSrcValue(), - SVOffset, ST->isVolatile(), Alignment); + SVOffset, ST->isVolatile(), ST->isNonTemporal(), + Alignment); } else { // Do a (aligned) store to a stack slot, then copy from the stack slot // to the final destination using (unaligned) integer loads and stores. @@ -418,7 +420,8 @@ SDValue ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG, // Perform the original store, only redirected to the stack slot. SDValue Store = DAG.getTruncStore(Chain, dl, - Val, StackPtr, NULL, 0, StoredVT); + Val, StackPtr, NULL, 0, StoredVT, + false, false, 0); SDValue Increment = DAG.getConstant(RegBytes, TLI.getPointerTy()); SmallVector<SDValue, 8> Stores; unsigned Offset = 0; @@ -426,11 +429,12 @@ SDValue ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG, // Do all but one copies using the full register width. for (unsigned i = 1; i < NumRegs; i++) { // Load one integer register's worth from the stack slot. - SDValue Load = DAG.getLoad(RegVT, dl, Store, StackPtr, NULL, 0); + SDValue Load = DAG.getLoad(RegVT, dl, Store, StackPtr, NULL, 0, + false, false, 0); // Store it to the final location. Remember the store. Stores.push_back(DAG.getStore(Load.getValue(1), dl, Load, Ptr, ST->getSrcValue(), SVOffset + Offset, - ST->isVolatile(), + ST->isVolatile(), ST->isNonTemporal(), MinAlign(ST->getAlignment(), Offset))); // Increment the pointers. Offset += RegBytes; @@ -446,11 +450,12 @@ SDValue ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG, // Load from the stack slot. SDValue Load = DAG.getExtLoad(ISD::EXTLOAD, dl, RegVT, Store, StackPtr, - NULL, 0, MemVT); + NULL, 0, MemVT, false, false, 0); Stores.push_back(DAG.getTruncStore(Load.getValue(1), dl, Load, Ptr, ST->getSrcValue(), SVOffset + Offset, MemVT, ST->isVolatile(), + ST->isNonTemporal(), MinAlign(ST->getAlignment(), Offset))); // The order of the stores doesn't matter - say it with a TokenFactor. return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &Stores[0], @@ -474,13 +479,14 @@ SDValue ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG, SDValue Store1, Store2; Store1 = DAG.getTruncStore(Chain, dl, TLI.isLittleEndian()?Lo:Hi, Ptr, ST->getSrcValue(), SVOffset, NewStoredVT, - ST->isVolatile(), Alignment); + ST->isVolatile(), ST->isNonTemporal(), Alignment); Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, DAG.getConstant(IncrementSize, TLI.getPointerTy())); Alignment = MinAlign(Alignment, IncrementSize); Store2 = DAG.getTruncStore(Chain, dl, TLI.isLittleEndian()?Hi:Lo, Ptr, ST->getSrcValue(), SVOffset + IncrementSize, - NewStoredVT, ST->isVolatile(), Alignment); + NewStoredVT, ST->isVolatile(), ST->isNonTemporal(), + Alignment); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Store1, Store2); } @@ -502,7 +508,7 @@ SDValue ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG, // then bitconvert to floating point or vector. SDValue newLoad = DAG.getLoad(intVT, dl, Chain, Ptr, LD->getSrcValue(), SVOffset, LD->isVolatile(), - LD->getAlignment()); + LD->isNonTemporal(), LD->getAlignment()); SDValue Result = DAG.getNode(ISD::BIT_CONVERT, dl, LoadedVT, newLoad); if (VT.isFloatingPoint() && LoadedVT != VT) Result = DAG.getNode(ISD::FP_EXTEND, dl, VT, Result); @@ -530,10 +536,11 @@ SDValue ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG, // Load one integer register's worth from the original location. SDValue Load = DAG.getLoad(RegVT, dl, Chain, Ptr, LD->getSrcValue(), SVOffset + Offset, LD->isVolatile(), + LD->isNonTemporal(), MinAlign(LD->getAlignment(), Offset)); // Follow the load with a store to the stack slot. Remember the store. Stores.push_back(DAG.getStore(Load.getValue(1), dl, Load, StackPtr, - NULL, 0)); + NULL, 0, false, false, 0)); // Increment the pointers. Offset += RegBytes; Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, Increment); @@ -546,12 +553,13 @@ SDValue ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG, SDValue Load = DAG.getExtLoad(ISD::EXTLOAD, dl, RegVT, Chain, Ptr, LD->getSrcValue(), SVOffset + Offset, MemVT, LD->isVolatile(), + LD->isNonTemporal(), MinAlign(LD->getAlignment(), Offset)); // Follow the load with a store to the stack slot. Remember the store. // On big-endian machines this requires a truncating store to ensure // that the bits end up in the right place. Stores.push_back(DAG.getTruncStore(Load.getValue(1), dl, Load, StackPtr, - NULL, 0, MemVT)); + NULL, 0, MemVT, false, false, 0)); // The order of the stores doesn't matter - say it with a TokenFactor. SDValue TF = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &Stores[0], @@ -559,7 +567,7 @@ SDValue ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG, // Finally, perform the original load only redirected to the stack slot. Load = DAG.getExtLoad(LD->getExtensionType(), dl, VT, TF, StackBase, - NULL, 0, LoadedVT); + NULL, 0, LoadedVT, false, false, 0); // Callers expect a MERGE_VALUES node. SDValue Ops[] = { Load, TF }; @@ -588,20 +596,22 @@ SDValue ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG, SDValue Lo, Hi; if (TLI.isLittleEndian()) { Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, VT, Chain, Ptr, LD->getSrcValue(), - SVOffset, NewLoadedVT, LD->isVolatile(), Alignment); + SVOffset, NewLoadedVT, LD->isVolatile(), + LD->isNonTemporal(), Alignment); Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, DAG.getConstant(IncrementSize, TLI.getPointerTy())); Hi = DAG.getExtLoad(HiExtType, dl, VT, Chain, Ptr, LD->getSrcValue(), SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(), - MinAlign(Alignment, IncrementSize)); + LD->isNonTemporal(), MinAlign(Alignment, IncrementSize)); } else { Hi = DAG.getExtLoad(HiExtType, dl, VT, Chain, Ptr, LD->getSrcValue(), - SVOffset, NewLoadedVT, LD->isVolatile(), Alignment); + SVOffset, NewLoadedVT, LD->isVolatile(), + LD->isNonTemporal(), Alignment); Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, DAG.getConstant(IncrementSize, TLI.getPointerTy())); Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, VT, Chain, Ptr, LD->getSrcValue(), SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(), - MinAlign(Alignment, IncrementSize)); + LD->isNonTemporal(), MinAlign(Alignment, IncrementSize)); } // aggregate the two parts @@ -643,7 +653,8 @@ PerformInsertVectorEltInMemory(SDValue Vec, SDValue Val, SDValue Idx, // Store the vector. SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, Tmp1, StackPtr, - PseudoSourceValue::getFixedStack(SPFI), 0); + PseudoSourceValue::getFixedStack(SPFI), 0, + false, false, 0); // Truncate or zero extend offset to target pointer type. unsigned CastOpc = IdxVT.bitsGT(PtrVT) ? ISD::TRUNCATE : ISD::ZERO_EXTEND; @@ -654,10 +665,12 @@ PerformInsertVectorEltInMemory(SDValue Vec, SDValue Val, SDValue Idx, SDValue StackPtr2 = DAG.getNode(ISD::ADD, dl, IdxVT, Tmp3, StackPtr); // Store the scalar value. Ch = DAG.getTruncStore(Ch, dl, Tmp2, StackPtr2, - PseudoSourceValue::getFixedStack(SPFI), 0, EltVT); + PseudoSourceValue::getFixedStack(SPFI), 0, EltVT, + false, false, 0); // Load the updated vector. return DAG.getLoad(VT, dl, Ch, StackPtr, - PseudoSourceValue::getFixedStack(SPFI), 0); + PseudoSourceValue::getFixedStack(SPFI), 0, + false, false, 0); } @@ -702,6 +715,7 @@ SDValue SelectionDAGLegalize::OptimizeFloatStore(StoreSDNode* ST) { int SVOffset = ST->getSrcValueOffset(); unsigned Alignment = ST->getAlignment(); bool isVolatile = ST->isVolatile(); + bool isNonTemporal = ST->isNonTemporal(); DebugLoc dl = ST->getDebugLoc(); if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(ST->getValue())) { if (CFP->getValueType(0) == MVT::f32 && @@ -710,14 +724,14 @@ SDValue SelectionDAGLegalize::OptimizeFloatStore(StoreSDNode* ST) { bitcastToAPInt().zextOrTrunc(32), MVT::i32); return DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), - SVOffset, isVolatile, Alignment); + SVOffset, isVolatile, isNonTemporal, Alignment); } else if (CFP->getValueType(0) == MVT::f64) { // If this target supports 64-bit registers, do a single 64-bit store. if (getTypeAction(MVT::i64) == Legal) { Tmp3 = DAG.getConstant(CFP->getValueAPF().bitcastToAPInt(). zextOrTrunc(64), MVT::i64); return DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), - SVOffset, isVolatile, Alignment); + SVOffset, isVolatile, isNonTemporal, Alignment); } else if (getTypeAction(MVT::i32) == Legal && !ST->isVolatile()) { // Otherwise, if the target supports 32-bit registers, use 2 32-bit // stores. If the target supports neither 32- nor 64-bits, this @@ -728,11 +742,11 @@ SDValue SelectionDAGLegalize::OptimizeFloatStore(StoreSDNode* ST) { if (TLI.isBigEndian()) std::swap(Lo, Hi); Lo = DAG.getStore(Tmp1, dl, Lo, Tmp2, ST->getSrcValue(), - SVOffset, isVolatile, Alignment); + SVOffset, isVolatile, isNonTemporal, Alignment); Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2, DAG.getIntPtrConstant(4)); Hi = DAG.getStore(Tmp1, dl, Hi, Tmp2, ST->getSrcValue(), SVOffset+4, - isVolatile, MinAlign(Alignment, 4U)); + isVolatile, isNonTemporal, MinAlign(Alignment, 4U)); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); } @@ -1108,7 +1122,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp1 = DAG.getLoad(NVT, dl, Tmp1, Tmp2, LD->getSrcValue(), LD->getSrcValueOffset(), - LD->isVolatile(), LD->getAlignment()); + LD->isVolatile(), LD->isNonTemporal(), + LD->getAlignment()); Tmp3 = LegalizeOp(DAG.getNode(ISD::BIT_CONVERT, dl, VT, Tmp1)); Tmp4 = LegalizeOp(Tmp1.getValue(1)); break; @@ -1125,6 +1140,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { int SVOffset = LD->getSrcValueOffset(); unsigned Alignment = LD->getAlignment(); bool isVolatile = LD->isVolatile(); + bool isNonTemporal = LD->isNonTemporal(); if (SrcWidth != SrcVT.getStoreSizeInBits() && // Some targets pretend to have an i1 loading operation, and actually @@ -1150,7 +1166,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Result = DAG.getExtLoad(NewExtType, dl, Node->getValueType(0), Tmp1, Tmp2, LD->getSrcValue(), SVOffset, - NVT, isVolatile, Alignment); + NVT, isVolatile, isNonTemporal, Alignment); Ch = Result.getValue(1); // The chain. @@ -1187,7 +1203,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, Node->getValueType(0), Tmp1, Tmp2, LD->getSrcValue(), SVOffset, RoundVT, isVolatile, - Alignment); + isNonTemporal, Alignment); // Load the remaining ExtraWidth bits. IncrementSize = RoundWidth / 8; @@ -1195,7 +1211,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { DAG.getIntPtrConstant(IncrementSize)); Hi = DAG.getExtLoad(ExtType, dl, Node->getValueType(0), Tmp1, Tmp2, LD->getSrcValue(), SVOffset + IncrementSize, - ExtraVT, isVolatile, + ExtraVT, isVolatile, isNonTemporal, MinAlign(Alignment, IncrementSize)); // Build a factor node to remember that this load is independent of the @@ -1215,7 +1231,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // Load the top RoundWidth bits. Hi = DAG.getExtLoad(ExtType, dl, Node->getValueType(0), Tmp1, Tmp2, LD->getSrcValue(), SVOffset, RoundVT, isVolatile, - Alignment); + isNonTemporal, Alignment); // Load the remaining ExtraWidth bits. IncrementSize = RoundWidth / 8; @@ -1224,7 +1240,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, Node->getValueType(0), Tmp1, Tmp2, LD->getSrcValue(), SVOffset + IncrementSize, - ExtraVT, isVolatile, + ExtraVT, isVolatile, isNonTemporal, MinAlign(Alignment, IncrementSize)); // Build a factor node to remember that this load is independent of the @@ -1284,7 +1300,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { (SrcVT == MVT::f64 && Node->getValueType(0) == MVT::f128)) { SDValue Load = DAG.getLoad(SrcVT, dl, Tmp1, Tmp2, LD->getSrcValue(), LD->getSrcValueOffset(), - LD->isVolatile(), LD->getAlignment()); + LD->isVolatile(), LD->isNonTemporal(), + LD->getAlignment()); Result = DAG.getNode(ISD::FP_EXTEND, dl, Node->getValueType(0), Load); Tmp1 = LegalizeOp(Result); // Relegalize new nodes. @@ -1297,7 +1314,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Result = DAG.getExtLoad(ISD::EXTLOAD, dl, Node->getValueType(0), Tmp1, Tmp2, LD->getSrcValue(), LD->getSrcValueOffset(), SrcVT, - LD->isVolatile(), LD->getAlignment()); + LD->isVolatile(), LD->isNonTemporal(), + LD->getAlignment()); SDValue ValRes; if (ExtType == ISD::SEXTLOAD) ValRes = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, @@ -1325,6 +1343,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { int SVOffset = ST->getSrcValueOffset(); unsigned Alignment = ST->getAlignment(); bool isVolatile = ST->isVolatile(); + bool isNonTemporal = ST->isNonTemporal(); if (!ST->isTruncatingStore()) { if (SDNode *OptStore = OptimizeFloatStore(ST).getNode()) { @@ -1361,7 +1380,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { TLI.getTypeToPromoteTo(ISD::STORE, VT), Tmp3); Result = DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), SVOffset, isVolatile, - Alignment); + isNonTemporal, Alignment); break; } break; @@ -1379,7 +1398,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { EVT NVT = EVT::getIntegerVT(*DAG.getContext(), StVT.getStoreSizeInBits()); Tmp3 = DAG.getZeroExtendInReg(Tmp3, dl, StVT); Result = DAG.getTruncStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), - SVOffset, NVT, isVolatile, Alignment); + SVOffset, NVT, isVolatile, isNonTemporal, + Alignment); } else if (StWidth & (StWidth - 1)) { // If not storing a power-of-2 number of bits, expand as two stores. assert(!StVT.isVector() && "Unsupported truncstore!"); @@ -1399,7 +1419,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // Store the bottom RoundWidth bits. Lo = DAG.getTruncStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), SVOffset, RoundVT, - isVolatile, Alignment); + isVolatile, isNonTemporal, Alignment); // Store the remaining ExtraWidth bits. IncrementSize = RoundWidth / 8; @@ -1409,6 +1429,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { DAG.getConstant(RoundWidth, TLI.getShiftAmountTy())); Hi = DAG.getTruncStore(Tmp1, dl, Hi, Tmp2, ST->getSrcValue(), SVOffset + IncrementSize, ExtraVT, isVolatile, + isNonTemporal, MinAlign(Alignment, IncrementSize)); } else { // Big endian - avoid unaligned stores. @@ -1417,7 +1438,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Hi = DAG.getNode(ISD::SRL, dl, Tmp3.getValueType(), Tmp3, DAG.getConstant(ExtraWidth, TLI.getShiftAmountTy())); Hi = DAG.getTruncStore(Tmp1, dl, Hi, Tmp2, ST->getSrcValue(), - SVOffset, RoundVT, isVolatile, Alignment); + SVOffset, RoundVT, isVolatile, isNonTemporal, + Alignment); // Store the remaining ExtraWidth bits. IncrementSize = RoundWidth / 8; @@ -1425,6 +1447,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { DAG.getIntPtrConstant(IncrementSize)); Lo = DAG.getTruncStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), SVOffset + IncrementSize, ExtraVT, isVolatile, + isNonTemporal, MinAlign(Alignment, IncrementSize)); } @@ -1457,7 +1480,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { assert(isTypeLegal(StVT) && "Do not know how to expand this store!"); Tmp3 = DAG.getNode(ISD::TRUNCATE, dl, StVT, Tmp3); Result = DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), - SVOffset, isVolatile, Alignment); + SVOffset, isVolatile, isNonTemporal, + Alignment); break; } } @@ -1484,7 +1508,8 @@ SDValue SelectionDAGLegalize::ExpandExtractFromVectorThroughStack(SDValue Op) { DebugLoc dl = Op.getDebugLoc(); // Store the value to a temporary stack slot, then LOAD the returned part. SDValue StackPtr = DAG.CreateStackTemporary(Vec.getValueType()); - SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, NULL, 0); + SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, NULL, 0, + false, false, 0); // Add the offset to the index. unsigned EltSize = @@ -1500,10 +1525,12 @@ SDValue SelectionDAGLegalize::ExpandExtractFromVectorThroughStack(SDValue Op) { StackPtr = DAG.getNode(ISD::ADD, dl, Idx.getValueType(), Idx, StackPtr); if (Op.getValueType().isVector()) - return DAG.getLoad(Op.getValueType(), dl, Ch, StackPtr, NULL, 0); + return DAG.getLoad(Op.getValueType(), dl, Ch, StackPtr, NULL, 0, + false, false, 0); else return DAG.getExtLoad(ISD::EXTLOAD, dl, Op.getValueType(), Ch, StackPtr, - NULL, 0, Vec.getValueType().getVectorElementType()); + NULL, 0, Vec.getValueType().getVectorElementType(), + false, false, 0); } SDValue SelectionDAGLegalize::ExpandVectorBuildThroughStack(SDNode* Node) { @@ -1533,12 +1560,14 @@ SDValue SelectionDAGLegalize::ExpandVectorBuildThroughStack(SDNode* Node) { Idx = DAG.getNode(ISD::ADD, dl, FIPtr.getValueType(), FIPtr, Idx); // If EltVT smaller than OpVT, only store the bits necessary. - if (EltVT.bitsLT(OpVT)) + if (!OpVT.isVector() && EltVT.bitsLT(OpVT)) { Stores.push_back(DAG.getTruncStore(DAG.getEntryNode(), dl, - Node->getOperand(i), Idx, SV, Offset, EltVT)); - else + Node->getOperand(i), Idx, SV, Offset, + EltVT, false, false, 0)); + } else Stores.push_back(DAG.getStore(DAG.getEntryNode(), dl, - Node->getOperand(i), Idx, SV, Offset)); + Node->getOperand(i), Idx, SV, Offset, + false, false, 0)); } SDValue StoreChain; @@ -1549,7 +1578,7 @@ SDValue SelectionDAGLegalize::ExpandVectorBuildThroughStack(SDNode* Node) { StoreChain = DAG.getEntryNode(); // Result is a load from the stack slot. - return DAG.getLoad(VT, dl, StoreChain, FIPtr, SV, 0); + return DAG.getLoad(VT, dl, StoreChain, FIPtr, SV, 0, false, false, 0); } SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode* Node) { @@ -1572,12 +1601,14 @@ SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode* Node) { SDValue StackPtr = DAG.CreateStackTemporary(Tmp2.getValueType()); SDValue StorePtr = StackPtr, LoadPtr = StackPtr; SDValue Ch = - DAG.getStore(DAG.getEntryNode(), dl, Tmp2, StorePtr, NULL, 0); + DAG.getStore(DAG.getEntryNode(), dl, Tmp2, StorePtr, NULL, 0, + false, false, 0); if (Tmp2.getValueType() == MVT::f64 && TLI.isLittleEndian()) LoadPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), LoadPtr, DAG.getIntPtrConstant(4)); SignBit = DAG.getExtLoad(ISD::SEXTLOAD, dl, TLI.getPointerTy(), - Ch, LoadPtr, NULL, 0, MVT::i32); + Ch, LoadPtr, NULL, 0, MVT::i32, + false, false, 0); } SignBit = DAG.getSetCC(dl, TLI.getSetCCResultType(SignBit.getValueType()), @@ -1701,20 +1732,21 @@ SDValue SelectionDAGLegalize::EmitStackConvert(SDValue SrcOp, if (SrcSize > SlotSize) Store = DAG.getTruncStore(DAG.getEntryNode(), dl, SrcOp, FIPtr, - SV, 0, SlotVT, false, SrcAlign); + SV, 0, SlotVT, false, false, SrcAlign); else { assert(SrcSize == SlotSize && "Invalid store"); Store = DAG.getStore(DAG.getEntryNode(), dl, SrcOp, FIPtr, - SV, 0, false, SrcAlign); + SV, 0, false, false, SrcAlign); } // Result is a load from the stack slot. if (SlotSize == DestSize) - return DAG.getLoad(DestVT, dl, Store, FIPtr, SV, 0, false, DestAlign); + return DAG.getLoad(DestVT, dl, Store, FIPtr, SV, 0, false, false, + DestAlign); assert(SlotSize < DestSize && "Unknown extension!"); return DAG.getExtLoad(ISD::EXTLOAD, dl, DestVT, Store, FIPtr, SV, 0, SlotVT, - false, DestAlign); + false, false, DestAlign); } SDValue SelectionDAGLegalize::ExpandSCALAR_TO_VECTOR(SDNode *Node) { @@ -1729,9 +1761,11 @@ SDValue SelectionDAGLegalize::ExpandSCALAR_TO_VECTOR(SDNode *Node) { SDValue Ch = DAG.getTruncStore(DAG.getEntryNode(), dl, Node->getOperand(0), StackPtr, PseudoSourceValue::getFixedStack(SPFI), 0, - Node->getValueType(0).getVectorElementType()); + Node->getValueType(0).getVectorElementType(), + false, false, 0); return DAG.getLoad(Node->getValueType(0), dl, Ch, StackPtr, - PseudoSourceValue::getFixedStack(SPFI), 0); + PseudoSourceValue::getFixedStack(SPFI), 0, + false, false, 0); } @@ -1805,7 +1839,7 @@ SDValue SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) { unsigned Alignment = cast<ConstantPoolSDNode>(CPIdx)->getAlignment(); return DAG.getLoad(VT, dl, DAG.getEntryNode(), CPIdx, PseudoSourceValue::getConstantPool(), 0, - false, Alignment); + false, false, Alignment); } if (!MoreThanTwoValues) { @@ -1943,13 +1977,16 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned, } // store the lo of the constructed double - based on integer input SDValue Store1 = DAG.getStore(DAG.getEntryNode(), dl, - Op0Mapped, Lo, NULL, 0); + Op0Mapped, Lo, NULL, 0, + false, false, 0); // initial hi portion of constructed double SDValue InitialHi = DAG.getConstant(0x43300000u, MVT::i32); // store the hi of the constructed double - biased exponent - SDValue Store2=DAG.getStore(Store1, dl, InitialHi, Hi, NULL, 0); + SDValue Store2=DAG.getStore(Store1, dl, InitialHi, Hi, NULL, 0, + false, false, 0); // load the constructed double - SDValue Load = DAG.getLoad(MVT::f64, dl, Store2, StackSlot, NULL, 0); + SDValue Load = DAG.getLoad(MVT::f64, dl, Store2, StackSlot, NULL, 0, + false, false, 0); // FP constant to bias correct the final result SDValue Bias = DAG.getConstantFP(isSigned ? BitsToDouble(0x4330000080000000ULL) : @@ -2004,13 +2041,13 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned, if (DestVT == MVT::f32) FudgeInReg = DAG.getLoad(MVT::f32, dl, DAG.getEntryNode(), CPIdx, PseudoSourceValue::getConstantPool(), 0, - false, Alignment); + false, false, Alignment); else { FudgeInReg = LegalizeOp(DAG.getExtLoad(ISD::EXTLOAD, dl, DestVT, DAG.getEntryNode(), CPIdx, PseudoSourceValue::getConstantPool(), 0, - MVT::f32, false, Alignment)); + MVT::f32, false, false, Alignment)); } return DAG.getNode(ISD::FADD, dl, DestVT, Tmp1, FudgeInReg); @@ -2350,16 +2387,19 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, EVT VT = Node->getValueType(0); Tmp1 = Node->getOperand(0); Tmp2 = Node->getOperand(1); - SDValue VAList = DAG.getLoad(TLI.getPointerTy(), dl, Tmp1, Tmp2, V, 0); + SDValue VAList = DAG.getLoad(TLI.getPointerTy(), dl, Tmp1, Tmp2, V, 0, + false, false, 0); // Increment the pointer, VAList, to the next vaarg Tmp3 = DAG.getNode(ISD::ADD, dl, TLI.getPointerTy(), VAList, DAG.getConstant(TLI.getTargetData()-> getTypeAllocSize(VT.getTypeForEVT(*DAG.getContext())), TLI.getPointerTy())); // Store the incremented VAList to the legalized pointer - Tmp3 = DAG.getStore(VAList.getValue(1), dl, Tmp3, Tmp2, V, 0); + Tmp3 = DAG.getStore(VAList.getValue(1), dl, Tmp3, Tmp2, V, 0, + false, false, 0); // Load the actual argument out of the pointer VAList - Results.push_back(DAG.getLoad(VT, dl, Tmp3, VAList, NULL, 0)); + Results.push_back(DAG.getLoad(VT, dl, Tmp3, VAList, NULL, 0, + false, false, 0)); Results.push_back(Results[0].getValue(1)); break; } @@ -2369,8 +2409,9 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, const Value *VD = cast<SrcValueSDNode>(Node->getOperand(3))->getValue(); const Value *VS = cast<SrcValueSDNode>(Node->getOperand(4))->getValue(); Tmp1 = DAG.getLoad(TLI.getPointerTy(), dl, Node->getOperand(0), - Node->getOperand(2), VS, 0); - Tmp1 = DAG.getStore(Tmp1.getValue(1), dl, Tmp1, Node->getOperand(1), VD, 0); + Node->getOperand(2), VS, 0, false, false, 0); + Tmp1 = DAG.getStore(Tmp1.getValue(1), dl, Tmp1, Node->getOperand(1), VD, 0, + false, false, 0); Results.push_back(Tmp1); break; } @@ -2767,7 +2808,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, DAG.getIntPtrConstant(1)); } else { // FIXME: We should be able to fall back to a libcall with an illegal - // type in some cases cases. + // type in some cases. // Also, we can fall back to a division in some cases, but that's a big // performance hit in the general case. llvm_unreachable("Don't know how to expand this operation yet!"); @@ -2816,15 +2857,19 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, SDValue Index = Node->getOperand(2); EVT PTy = TLI.getPointerTy(); - MachineFunction &MF = DAG.getMachineFunction(); - unsigned EntrySize = MF.getJumpTableInfo()->getEntrySize(); - Index= DAG.getNode(ISD::MUL, dl, PTy, + + const TargetData &TD = *TLI.getTargetData(); + unsigned EntrySize = + DAG.getMachineFunction().getJumpTableInfo()->getEntrySize(TD); + + Index = DAG.getNode(ISD::MUL, dl, PTy, Index, DAG.getConstant(EntrySize, PTy)); SDValue Addr = DAG.getNode(ISD::ADD, dl, PTy, Index, Table); EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), EntrySize * 8); SDValue LD = DAG.getExtLoad(ISD::SEXTLOAD, dl, PTy, Chain, Addr, - PseudoSourceValue::getJumpTable(), 0, MemVT); + PseudoSourceValue::getJumpTable(), 0, MemVT, + false, false, 0); Addr = LD; if (TLI.getTargetMachine().getRelocationModel() == Reloc::PIC_) { // For PIC, the sequence is: diff --git a/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp index 4f0fce7..35a7c7c 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp @@ -444,7 +444,7 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_LOAD(SDNode *N) { NewL = DAG.getLoad(L->getAddressingMode(), dl, L->getExtensionType(), NVT, L->getChain(), L->getBasePtr(), L->getOffset(), L->getSrcValue(), L->getSrcValueOffset(), NVT, - L->isVolatile(), L->getAlignment()); + L->isVolatile(), L->isNonTemporal(), L->getAlignment()); // Legalized the chain result - switch anything that used the old chain to // use the new one. ReplaceValueWith(SDValue(N, 1), NewL.getValue(1)); @@ -456,8 +456,8 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_LOAD(SDNode *N) { L->getMemoryVT(), L->getChain(), L->getBasePtr(), L->getOffset(), L->getSrcValue(), L->getSrcValueOffset(), - L->getMemoryVT(), - L->isVolatile(), L->getAlignment()); + L->getMemoryVT(), L->isVolatile(), + L->isNonTemporal(), L->getAlignment()); // Legalized the chain result - switch anything that used the old chain to // use the new one. ReplaceValueWith(SDValue(N, 1), NewL.getValue(1)); @@ -755,7 +755,8 @@ SDValue DAGTypeLegalizer::SoftenFloatOp_STORE(SDNode *N, unsigned OpNo) { return DAG.getStore(ST->getChain(), dl, Val, ST->getBasePtr(), ST->getSrcValue(), ST->getSrcValueOffset(), - ST->isVolatile(), ST->getAlignment()); + ST->isVolatile(), ST->isNonTemporal(), + ST->getAlignment()); } @@ -1073,8 +1074,8 @@ void DAGTypeLegalizer::ExpandFloatRes_LOAD(SDNode *N, SDValue &Lo, Hi = DAG.getExtLoad(LD->getExtensionType(), dl, NVT, Chain, Ptr, LD->getSrcValue(), LD->getSrcValueOffset(), - LD->getMemoryVT(), - LD->isVolatile(), LD->getAlignment()); + LD->getMemoryVT(), LD->isVolatile(), + LD->isNonTemporal(), LD->getAlignment()); // Remember the chain. Chain = Hi.getValue(1); @@ -1382,6 +1383,6 @@ SDValue DAGTypeLegalizer::ExpandFloatOp_STORE(SDNode *N, unsigned OpNo) { return DAG.getTruncStore(Chain, N->getDebugLoc(), Hi, Ptr, ST->getSrcValue(), ST->getSrcValueOffset(), - ST->getMemoryVT(), - ST->isVolatile(), ST->getAlignment()); + ST->getMemoryVT(), ST->isVolatile(), + ST->isNonTemporal(), ST->getAlignment()); } diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index 9932cf4..e4d123f 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -359,7 +359,7 @@ SDValue DAGTypeLegalizer::PromoteIntRes_LOAD(LoadSDNode *N) { SDValue Res = DAG.getExtLoad(ExtType, dl, NVT, N->getChain(), N->getBasePtr(), N->getSrcValue(), N->getSrcValueOffset(), N->getMemoryVT(), N->isVolatile(), - N->getAlignment()); + N->isNonTemporal(), N->getAlignment()); // Legalized the chain result - switch anything that used the old chain to // use the new one. @@ -873,6 +873,7 @@ SDValue DAGTypeLegalizer::PromoteIntOp_STORE(StoreSDNode *N, unsigned OpNo){ int SVOffset = N->getSrcValueOffset(); unsigned Alignment = N->getAlignment(); bool isVolatile = N->isVolatile(); + bool isNonTemporal = N->isNonTemporal(); DebugLoc dl = N->getDebugLoc(); SDValue Val = GetPromotedInteger(N->getValue()); // Get promoted value. @@ -880,7 +881,7 @@ SDValue DAGTypeLegalizer::PromoteIntOp_STORE(StoreSDNode *N, unsigned OpNo){ // Truncate the value and store the result. return DAG.getTruncStore(Ch, dl, Val, Ptr, N->getSrcValue(), SVOffset, N->getMemoryVT(), - isVolatile, Alignment); + isVolatile, isNonTemporal, Alignment); } SDValue DAGTypeLegalizer::PromoteIntOp_TRUNCATE(SDNode *N) { @@ -1500,6 +1501,7 @@ void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, int SVOffset = N->getSrcValueOffset(); unsigned Alignment = N->getAlignment(); bool isVolatile = N->isVolatile(); + bool isNonTemporal = N->isNonTemporal(); DebugLoc dl = N->getDebugLoc(); assert(NVT.isByteSized() && "Expanded type not byte sized!"); @@ -1508,7 +1510,7 @@ void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, EVT MemVT = N->getMemoryVT(); Lo = DAG.getExtLoad(ExtType, dl, NVT, Ch, Ptr, N->getSrcValue(), SVOffset, - MemVT, isVolatile, Alignment); + MemVT, isVolatile, isNonTemporal, Alignment); // Remember the chain. Ch = Lo.getValue(1); @@ -1530,7 +1532,7 @@ void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, } else if (TLI.isLittleEndian()) { // Little-endian - low bits are at low addresses. Lo = DAG.getLoad(NVT, dl, Ch, Ptr, N->getSrcValue(), SVOffset, - isVolatile, Alignment); + isVolatile, isNonTemporal, Alignment); unsigned ExcessBits = N->getMemoryVT().getSizeInBits() - NVT.getSizeInBits(); @@ -1542,7 +1544,8 @@ void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, DAG.getIntPtrConstant(IncrementSize)); Hi = DAG.getExtLoad(ExtType, dl, NVT, Ch, Ptr, N->getSrcValue(), SVOffset+IncrementSize, NEVT, - isVolatile, MinAlign(Alignment, IncrementSize)); + isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); // Build a factor node to remember that this load is independent of the // other one. @@ -1560,7 +1563,7 @@ void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, Hi = DAG.getExtLoad(ExtType, dl, NVT, Ch, Ptr, N->getSrcValue(), SVOffset, EVT::getIntegerVT(*DAG.getContext(), MemVT.getSizeInBits() - ExcessBits), - isVolatile, Alignment); + isVolatile, isNonTemporal, Alignment); // Increment the pointer to the other half. Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, @@ -1569,7 +1572,8 @@ void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, NVT, Ch, Ptr, N->getSrcValue(), SVOffset+IncrementSize, EVT::getIntegerVT(*DAG.getContext(), ExcessBits), - isVolatile, MinAlign(Alignment, IncrementSize)); + isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); // Build a factor node to remember that this load is independent of the // other one. @@ -2212,6 +2216,7 @@ SDValue DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) { int SVOffset = N->getSrcValueOffset(); unsigned Alignment = N->getAlignment(); bool isVolatile = N->isVolatile(); + bool isNonTemporal = N->isNonTemporal(); DebugLoc dl = N->getDebugLoc(); SDValue Lo, Hi; @@ -2220,13 +2225,14 @@ SDValue DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) { if (N->getMemoryVT().bitsLE(NVT)) { GetExpandedInteger(N->getValue(), Lo, Hi); return DAG.getTruncStore(Ch, dl, Lo, Ptr, N->getSrcValue(), SVOffset, - N->getMemoryVT(), isVolatile, Alignment); + N->getMemoryVT(), isVolatile, isNonTemporal, + Alignment); } else if (TLI.isLittleEndian()) { // Little-endian - low bits are at low addresses. GetExpandedInteger(N->getValue(), Lo, Hi); Lo = DAG.getStore(Ch, dl, Lo, Ptr, N->getSrcValue(), SVOffset, - isVolatile, Alignment); + isVolatile, isNonTemporal, Alignment); unsigned ExcessBits = N->getMemoryVT().getSizeInBits() - NVT.getSizeInBits(); @@ -2238,7 +2244,8 @@ SDValue DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) { DAG.getIntPtrConstant(IncrementSize)); Hi = DAG.getTruncStore(Ch, dl, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize, NEVT, - isVolatile, MinAlign(Alignment, IncrementSize)); + isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); } else { // Big-endian - high bits are at low addresses. Favor aligned stores at @@ -2264,7 +2271,8 @@ SDValue DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) { // Store both the high bits and maybe some of the low bits. Hi = DAG.getTruncStore(Ch, dl, Hi, Ptr, N->getSrcValue(), - SVOffset, HiVT, isVolatile, Alignment); + SVOffset, HiVT, isVolatile, isNonTemporal, + Alignment); // Increment the pointer to the other half. Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, @@ -2273,7 +2281,8 @@ SDValue DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) { Lo = DAG.getTruncStore(Ch, dl, Lo, Ptr, N->getSrcValue(), SVOffset+IncrementSize, EVT::getIntegerVT(*DAG.getContext(), ExcessBits), - isVolatile, MinAlign(Alignment, IncrementSize)); + isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); } } @@ -2341,7 +2350,7 @@ SDValue DAGTypeLegalizer::ExpandIntOp_UINT_TO_FP(SDNode *N) { // FIXME: Avoid the extend by constructing the right constant pool? SDValue Fudge = DAG.getExtLoad(ISD::EXTLOAD, dl, DstVT, DAG.getEntryNode(), FudgePtr, NULL, 0, MVT::f32, - false, Alignment); + false, false, Alignment); return DAG.getNode(ISD::FADD, dl, DstVT, SignedConv, Fudge); } diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp index 37f36a3..0d929f1 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp @@ -871,9 +871,10 @@ SDValue DAGTypeLegalizer::CreateStackStoreLoad(SDValue Op, // the source and destination types. SDValue StackPtr = DAG.CreateStackTemporary(Op.getValueType(), DestVT); // Emit a store to the stack slot. - SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Op, StackPtr, NULL, 0); + SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Op, StackPtr, NULL, 0, + false, false, 0); // Result is a load from the stack slot. - return DAG.getLoad(DestVT, dl, Store, StackPtr, NULL, 0); + return DAG.getLoad(DestVT, dl, Store, StackPtr, NULL, 0, false, false, 0); } /// CustomLowerNode - Replace the node's results with custom code provided diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/lib/CodeGen/SelectionDAG/LegalizeTypes.h index b5dbd41..b0af357 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -609,6 +609,7 @@ private: SDValue WidenVecRes_SIGN_EXTEND_INREG(SDNode* N); SDValue WidenVecRes_SELECT(SDNode* N); SDValue WidenVecRes_SELECT_CC(SDNode* N); + SDValue WidenVecRes_SETCC(SDNode* N); SDValue WidenVecRes_UNDEF(SDNode *N); SDValue WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N); SDValue WidenVecRes_VSETCC(SDNode* N); @@ -633,43 +634,33 @@ private: // Vector Widening Utilities Support: LegalizeVectorTypes.cpp //===--------------------------------------------------------------------===// - /// Helper genWidenVectorLoads - Helper function to generate a set of + /// Helper GenWidenVectorLoads - Helper function to generate a set of /// loads to load a vector with a resulting wider type. It takes - /// ExtType: Extension type - /// LdChain: list of chains for the load we have generated. - /// Chain: incoming chain for the ld vector. - /// BasePtr: base pointer to load from. - /// SV: memory disambiguation source value. - /// SVOffset: memory disambiugation offset. - /// Alignment: alignment of the memory. - /// isVolatile: volatile load. - /// LdWidth: width of memory that we want to load. - /// ResType: the wider result result type for the resulting vector. - /// dl: DebugLoc to be applied to new nodes - SDValue GenWidenVectorLoads(SmallVector<SDValue, 16>& LdChain, SDValue Chain, - SDValue BasePtr, const Value *SV, - int SVOffset, unsigned Alignment, - bool isVolatile, unsigned LdWidth, - EVT ResType, DebugLoc dl); + /// LdChain: list of chains for the load to be generated. + /// Ld: load to widen + SDValue GenWidenVectorLoads(SmallVector<SDValue, 16>& LdChain, + LoadSDNode *LD); + + /// GenWidenVectorExtLoads - Helper function to generate a set of extension + /// loads to load a ector with a resulting wider type. It takes + /// LdChain: list of chains for the load to be generated. + /// Ld: load to widen + /// ExtType: extension element type + SDValue GenWidenVectorExtLoads(SmallVector<SDValue, 16>& LdChain, + LoadSDNode *LD, ISD::LoadExtType ExtType); /// Helper genWidenVectorStores - Helper function to generate a set of /// stores to store a widen vector into non widen memory - /// It takes /// StChain: list of chains for the stores we have generated - /// Chain: incoming chain for the ld vector - /// BasePtr: base pointer to load from - /// SV: memory disambiguation source value - /// SVOffset: memory disambiugation offset - /// Alignment: alignment of the memory - /// isVolatile: volatile lod - /// ValOp: value to store - /// StWidth: width of memory that we want to store - /// dl: DebugLoc to be applied to new nodes - void GenWidenVectorStores(SmallVector<SDValue, 16>& StChain, SDValue Chain, - SDValue BasePtr, const Value *SV, - int SVOffset, unsigned Alignment, - bool isVolatile, SDValue ValOp, - unsigned StWidth, DebugLoc dl); + /// ST: store of a widen value + void GenWidenVectorStores(SmallVector<SDValue, 16>& StChain, StoreSDNode *ST); + + /// Helper genWidenVectorTruncStores - Helper function to generate a set of + /// stores to store a truncate widen vector into non widen memory + /// StChain: list of chains for the stores we have generated + /// ST: store of a widen value + void GenWidenVectorTruncStores(SmallVector<SDValue, 16>& StChain, + StoreSDNode *ST); /// Modifies a vector input (widen or narrows) to a vector of NVT. The /// input vector must have the same element type as NVT. diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp index a1b6ced..5e83b4b 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp @@ -122,10 +122,11 @@ void DAGTypeLegalizer::ExpandRes_BIT_CONVERT(SDNode *N, SDValue &Lo, const Value *SV = PseudoSourceValue::getFixedStack(SPFI); // Emit a store to the stack slot. - SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, InOp, StackPtr, SV, 0); + SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, InOp, StackPtr, SV, 0, + false, false, 0); // Load the first half from the stack slot. - Lo = DAG.getLoad(NOutVT, dl, Store, StackPtr, SV, 0); + Lo = DAG.getLoad(NOutVT, dl, Store, StackPtr, SV, 0, false, false, 0); // Increment the pointer to the other half. unsigned IncrementSize = NOutVT.getSizeInBits() / 8; @@ -134,7 +135,7 @@ void DAGTypeLegalizer::ExpandRes_BIT_CONVERT(SDNode *N, SDValue &Lo, // Load the second half from the stack slot. Hi = DAG.getLoad(NOutVT, dl, Store, StackPtr, SV, IncrementSize, false, - MinAlign(Alignment, IncrementSize)); + false, MinAlign(Alignment, IncrementSize)); // Handle endianness of the load. if (TLI.isBigEndian()) @@ -205,11 +206,12 @@ void DAGTypeLegalizer::ExpandRes_NormalLoad(SDNode *N, SDValue &Lo, int SVOffset = LD->getSrcValueOffset(); unsigned Alignment = LD->getAlignment(); bool isVolatile = LD->isVolatile(); + bool isNonTemporal = LD->isNonTemporal(); assert(NVT.isByteSized() && "Expanded type not byte sized!"); Lo = DAG.getLoad(NVT, dl, Chain, Ptr, LD->getSrcValue(), SVOffset, - isVolatile, Alignment); + isVolatile, isNonTemporal, Alignment); // Increment the pointer to the other half. unsigned IncrementSize = NVT.getSizeInBits() / 8; @@ -217,7 +219,8 @@ void DAGTypeLegalizer::ExpandRes_NormalLoad(SDNode *N, SDValue &Lo, DAG.getIntPtrConstant(IncrementSize)); Hi = DAG.getLoad(NVT, dl, Chain, Ptr, LD->getSrcValue(), SVOffset+IncrementSize, - isVolatile, MinAlign(Alignment, IncrementSize)); + isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); // Build a factor node to remember that this load is independent of the // other one. @@ -383,6 +386,7 @@ SDValue DAGTypeLegalizer::ExpandOp_NormalStore(SDNode *N, unsigned OpNo) { int SVOffset = St->getSrcValueOffset(); unsigned Alignment = St->getAlignment(); bool isVolatile = St->isVolatile(); + bool isNonTemporal = St->isNonTemporal(); assert(NVT.isByteSized() && "Expanded type not byte sized!"); unsigned IncrementSize = NVT.getSizeInBits() / 8; @@ -394,14 +398,15 @@ SDValue DAGTypeLegalizer::ExpandOp_NormalStore(SDNode *N, unsigned OpNo) { std::swap(Lo, Hi); Lo = DAG.getStore(Chain, dl, Lo, Ptr, St->getSrcValue(), SVOffset, - isVolatile, Alignment); + isVolatile, isNonTemporal, Alignment); Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, DAG.getIntPtrConstant(IncrementSize)); assert(isTypeLegal(Ptr.getValueType()) && "Pointers must be legal!"); Hi = DAG.getStore(Chain, dl, Hi, Ptr, St->getSrcValue(), SVOffset + IncrementSize, - isVolatile, MinAlign(Alignment, IncrementSize)); + isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); } diff --git a/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp index 808bac7..8363c3a 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -172,7 +172,8 @@ SDValue DAGTypeLegalizer::ScalarizeVecRes_LOAD(LoadSDNode *N) { DAG.getUNDEF(N->getBasePtr().getValueType()), N->getSrcValue(), N->getSrcValueOffset(), N->getMemoryVT().getVectorElementType(), - N->isVolatile(), N->getOriginalAlignment()); + N->isVolatile(), N->isNonTemporal(), + N->getOriginalAlignment()); // Legalized the chain result - switch anything that used the old chain to // use the new one. @@ -366,11 +367,13 @@ SDValue DAGTypeLegalizer::ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo){ N->getBasePtr(), N->getSrcValue(), N->getSrcValueOffset(), N->getMemoryVT().getVectorElementType(), - N->isVolatile(), N->getAlignment()); + N->isVolatile(), N->isNonTemporal(), + N->getAlignment()); return DAG.getStore(N->getChain(), dl, GetScalarizedVector(N->getOperand(1)), N->getBasePtr(), N->getSrcValue(), N->getSrcValueOffset(), - N->isVolatile(), N->getOriginalAlignment()); + N->isVolatile(), N->isNonTemporal(), + N->getOriginalAlignment()); } @@ -696,17 +699,20 @@ void DAGTypeLegalizer::SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo, EVT VecVT = Vec.getValueType(); EVT EltVT = VecVT.getVectorElementType(); SDValue StackPtr = DAG.CreateStackTemporary(VecVT); - SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, NULL, 0); + SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, NULL, 0, + false, false, 0); // Store the new element. This may be larger than the vector element type, // so use a truncating store. SDValue EltPtr = GetVectorElementPointer(StackPtr, EltVT, Idx); unsigned Alignment = TLI.getTargetData()->getPrefTypeAlignment(VecVT.getTypeForEVT(*DAG.getContext())); - Store = DAG.getTruncStore(Store, dl, Elt, EltPtr, NULL, 0, EltVT); + Store = DAG.getTruncStore(Store, dl, Elt, EltPtr, NULL, 0, EltVT, + false, false, 0); // Load the Lo part from the stack slot. - Lo = DAG.getLoad(Lo.getValueType(), dl, Store, StackPtr, NULL, 0); + Lo = DAG.getLoad(Lo.getValueType(), dl, Store, StackPtr, NULL, 0, + false, false, 0); // Increment the pointer to the other part. unsigned IncrementSize = Lo.getValueType().getSizeInBits() / 8; @@ -715,7 +721,7 @@ void DAGTypeLegalizer::SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo, // Load the Hi part from the stack slot. Hi = DAG.getLoad(Hi.getValueType(), dl, Store, StackPtr, NULL, 0, false, - MinAlign(Alignment, IncrementSize)); + false, MinAlign(Alignment, IncrementSize)); } void DAGTypeLegalizer::SplitVecRes_SCALAR_TO_VECTOR(SDNode *N, SDValue &Lo, @@ -743,19 +749,20 @@ void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo, EVT MemoryVT = LD->getMemoryVT(); unsigned Alignment = LD->getOriginalAlignment(); bool isVolatile = LD->isVolatile(); + bool isNonTemporal = LD->isNonTemporal(); EVT LoMemVT, HiMemVT; GetSplitDestVTs(MemoryVT, LoMemVT, HiMemVT); Lo = DAG.getLoad(ISD::UNINDEXED, dl, ExtType, LoVT, Ch, Ptr, Offset, - SV, SVOffset, LoMemVT, isVolatile, Alignment); + SV, SVOffset, LoMemVT, isVolatile, isNonTemporal, Alignment); unsigned IncrementSize = LoMemVT.getSizeInBits()/8; Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, DAG.getIntPtrConstant(IncrementSize)); SVOffset += IncrementSize; Hi = DAG.getLoad(ISD::UNINDEXED, dl, ExtType, HiVT, Ch, Ptr, Offset, - SV, SVOffset, HiMemVT, isVolatile, Alignment); + SV, SVOffset, HiMemVT, isVolatile, isNonTemporal, Alignment); // Build a factor node to remember that this load is independent of the // other one. @@ -1086,12 +1093,13 @@ SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N) { SDValue StackPtr = DAG.CreateStackTemporary(VecVT); int SPFI = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex(); const Value *SV = PseudoSourceValue::getFixedStack(SPFI); - SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, SV, 0); + SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, SV, 0, + false, false, 0); // Load back the required element. StackPtr = GetVectorElementPointer(StackPtr, EltVT, Idx); return DAG.getExtLoad(ISD::EXTLOAD, dl, N->getValueType(0), Store, StackPtr, - SV, 0, EltVT); + SV, 0, EltVT, false, false, 0); } SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) { @@ -1106,6 +1114,7 @@ SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) { EVT MemoryVT = N->getMemoryVT(); unsigned Alignment = N->getOriginalAlignment(); bool isVol = N->isVolatile(); + bool isNT = N->isNonTemporal(); SDValue Lo, Hi; GetSplitVector(N->getOperand(1), Lo, Hi); @@ -1116,10 +1125,10 @@ SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) { if (isTruncating) Lo = DAG.getTruncStore(Ch, dl, Lo, Ptr, N->getSrcValue(), SVOffset, - LoMemVT, isVol, Alignment); + LoMemVT, isVol, isNT, Alignment); else Lo = DAG.getStore(Ch, dl, Lo, Ptr, N->getSrcValue(), SVOffset, - isVol, Alignment); + isVol, isNT, Alignment); // Increment the pointer to the other half. Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, @@ -1128,10 +1137,10 @@ SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) { if (isTruncating) Hi = DAG.getTruncStore(Ch, dl, Hi, Ptr, N->getSrcValue(), SVOffset, - HiMemVT, isVol, Alignment); + HiMemVT, isVol, isNT, Alignment); else Hi = DAG.getStore(Ch, dl, Hi, Ptr, N->getSrcValue(), SVOffset, - isVol, Alignment); + isVol, isNT, Alignment); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); } @@ -1172,6 +1181,7 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) { case ISD::SIGN_EXTEND_INREG: Res = WidenVecRes_InregOp(N); break; case ISD::SELECT: Res = WidenVecRes_SELECT(N); break; case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break; + case ISD::SETCC: Res = WidenVecRes_SETCC(N); break; case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break; case ISD::VECTOR_SHUFFLE: Res = WidenVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N)); @@ -1241,10 +1251,96 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) { SDValue DAGTypeLegalizer::WidenVecRes_Binary(SDNode *N) { // Binary op widening. + unsigned Opcode = N->getOpcode(); + DebugLoc dl = N->getDebugLoc(); EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); - SDValue InOp1 = GetWidenedVector(N->getOperand(0)); - SDValue InOp2 = GetWidenedVector(N->getOperand(1)); - return DAG.getNode(N->getOpcode(), N->getDebugLoc(), WidenVT, InOp1, InOp2); + EVT WidenEltVT = WidenVT.getVectorElementType(); + EVT VT = WidenVT; + unsigned NumElts = VT.getVectorNumElements(); + while (!TLI.isTypeLegal(VT) && NumElts != 1) { + NumElts = NumElts / 2; + VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts); + } + + if (NumElts != 1 && !TLI.canOpTrap(N->getOpcode(), VT)) { + // Operation doesn't trap so just widen as normal. + SDValue InOp1 = GetWidenedVector(N->getOperand(0)); + SDValue InOp2 = GetWidenedVector(N->getOperand(1)); + return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2); + } else if (NumElts == 1) { + // No legal vector version so unroll the vector operation and then widen. + return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements()); + } else { + // Since the operation can trap, apply operation on the original vector. + SDValue InOp1 = GetWidenedVector(N->getOperand(0)); + SDValue InOp2 = GetWidenedVector(N->getOperand(1)); + unsigned CurNumElts = N->getValueType(0).getVectorNumElements(); + + SmallVector<SDValue, 16> ConcatOps(CurNumElts); + unsigned ConcatEnd = 0; // Current ConcatOps index. + unsigned Idx = 0; // Current Idx into input vectors. + while (CurNumElts != 0) { + while (CurNumElts >= NumElts) { + SDValue EOp1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, InOp1, + DAG.getIntPtrConstant(Idx)); + SDValue EOp2 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, InOp2, + DAG.getIntPtrConstant(Idx)); + ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, VT, EOp1, EOp2); + Idx += NumElts; + CurNumElts -= NumElts; + } + EVT PrevVecVT = VT; + do { + NumElts = NumElts / 2; + VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts); + } while (!TLI.isTypeLegal(VT) && NumElts != 1); + + if (NumElts == 1) { + // Since we are using concat vector, build a vector from the scalar ops. + SDValue VecOp = DAG.getUNDEF(PrevVecVT); + for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) { + SDValue EOp1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, WidenEltVT, + InOp1, DAG.getIntPtrConstant(Idx)); + SDValue EOp2 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, WidenEltVT, + InOp2, DAG.getIntPtrConstant(Idx)); + VecOp = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, PrevVecVT, VecOp, + DAG.getNode(Opcode, dl, WidenEltVT, EOp1, EOp2), + DAG.getIntPtrConstant(i)); + } + CurNumElts = 0; + ConcatOps[ConcatEnd++] = VecOp; + } + } + + // Check to see if we have a single operation with the widen type. + if (ConcatEnd == 1) { + VT = ConcatOps[0].getValueType(); + if (VT == WidenVT) + return ConcatOps[0]; + } + + // Rebuild vector to one with the widen type + Idx = ConcatEnd - 1; + while (Idx != 0) { + VT = ConcatOps[Idx--].getValueType(); + while (Idx != 0 && ConcatOps[Idx].getValueType() == VT) + --Idx; + if (Idx != 0) { + VT = ConcatOps[Idx].getValueType(); + ConcatOps[Idx+1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, VT, + &ConcatOps[Idx+1], ConcatEnd - Idx - 1); + ConcatEnd = Idx + 2; + } + } + + unsigned NumOps = WidenVT.getVectorNumElements()/VT.getVectorNumElements(); + if (NumOps != ConcatEnd ) { + SDValue UndefVal = DAG.getUNDEF(VT); + for (unsigned j = ConcatEnd; j < NumOps; ++j) + ConcatOps[j] = UndefVal; + } + return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, &ConcatOps[0], NumOps); + } } SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) { @@ -1655,68 +1751,24 @@ SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) { SDValue DAGTypeLegalizer::WidenVecRes_LOAD(SDNode *N) { LoadSDNode *LD = cast<LoadSDNode>(N); - EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), LD->getValueType(0)); - EVT LdVT = LD->getMemoryVT(); - DebugLoc dl = N->getDebugLoc(); - assert(LdVT.isVector() && WidenVT.isVector()); - - // Load information - SDValue Chain = LD->getChain(); - SDValue BasePtr = LD->getBasePtr(); - int SVOffset = LD->getSrcValueOffset(); - unsigned Align = LD->getAlignment(); - bool isVolatile = LD->isVolatile(); - const Value *SV = LD->getSrcValue(); ISD::LoadExtType ExtType = LD->getExtensionType(); SDValue Result; SmallVector<SDValue, 16> LdChain; // Chain for the series of load - if (ExtType != ISD::NON_EXTLOAD) { - // For extension loads, we can not play the tricks of chopping legal - // vector types and bit cast it to the right type. Instead, we unroll - // the load and build a vector. - EVT EltVT = WidenVT.getVectorElementType(); - EVT LdEltVT = LdVT.getVectorElementType(); - unsigned NumElts = LdVT.getVectorNumElements(); - - // Load each element and widen - unsigned WidenNumElts = WidenVT.getVectorNumElements(); - SmallVector<SDValue, 16> Ops(WidenNumElts); - unsigned Increment = LdEltVT.getSizeInBits() / 8; - Ops[0] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, SV, SVOffset, - LdEltVT, isVolatile, Align); - LdChain.push_back(Ops[0].getValue(1)); - unsigned i = 0, Offset = Increment; - for (i=1; i < NumElts; ++i, Offset += Increment) { - SDValue NewBasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), - BasePtr, DAG.getIntPtrConstant(Offset)); - Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr, SV, - SVOffset + Offset, LdEltVT, isVolatile, Align); - LdChain.push_back(Ops[i].getValue(1)); - } - - // Fill the rest with undefs - SDValue UndefVal = DAG.getUNDEF(EltVT); - for (; i != WidenNumElts; ++i) - Ops[i] = UndefVal; - - Result = DAG.getNode(ISD::BUILD_VECTOR, dl, WidenVT, &Ops[0], Ops.size()); - } else { - assert(LdVT.getVectorElementType() == WidenVT.getVectorElementType()); - unsigned int LdWidth = LdVT.getSizeInBits(); - Result = GenWidenVectorLoads(LdChain, Chain, BasePtr, SV, SVOffset, - Align, isVolatile, LdWidth, WidenVT, dl); - } - - // If we generate a single load, we can use that for the chain. Otherwise, - // build a factor node to remember the multiple loads are independent and - // chain to that. - SDValue NewChain; - if (LdChain.size() == 1) - NewChain = LdChain[0]; - else - NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &LdChain[0], - LdChain.size()); + if (ExtType != ISD::NON_EXTLOAD) + Result = GenWidenVectorExtLoads(LdChain, LD, ExtType); + else + Result = GenWidenVectorLoads(LdChain, LD); + + // If we generate a single load, we can use that for the chain. Otherwise, + // build a factor node to remember the multiple loads are independent and + // chain to that. + SDValue NewChain; + if (LdChain.size() == 1) + NewChain = LdChain[0]; + else + NewChain = DAG.getNode(ISD::TokenFactor, LD->getDebugLoc(), MVT::Other, + &LdChain[0], LdChain.size()); // Modified the chain - switch anything that used the old chain to use // the new one. @@ -1762,6 +1814,14 @@ SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) { N->getOperand(1), InOp1, InOp2, N->getOperand(4)); } +SDValue DAGTypeLegalizer::WidenVecRes_SETCC(SDNode *N) { + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue InOp1 = GetWidenedVector(N->getOperand(0)); + SDValue InOp2 = GetWidenedVector(N->getOperand(1)); + return DAG.getNode(ISD::SETCC, N->getDebugLoc(), WidenVT, + InOp1, InOp2, N->getOperand(2)); +} + SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) { EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); return DAG.getUNDEF(WidenVT); @@ -1954,57 +2014,17 @@ SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) { // We have to widen the value but we want only to store the original // vector type. StoreSDNode *ST = cast<StoreSDNode>(N); - SDValue Chain = ST->getChain(); - SDValue BasePtr = ST->getBasePtr(); - const Value *SV = ST->getSrcValue(); - int SVOffset = ST->getSrcValueOffset(); - unsigned Align = ST->getAlignment(); - bool isVolatile = ST->isVolatile(); - SDValue ValOp = GetWidenedVector(ST->getValue()); - DebugLoc dl = N->getDebugLoc(); - - EVT StVT = ST->getMemoryVT(); - EVT ValVT = ValOp.getValueType(); - // It must be true that we the widen vector type is bigger than where - // we need to store. - assert(StVT.isVector() && ValOp.getValueType().isVector()); - assert(StVT.bitsLT(ValOp.getValueType())); SmallVector<SDValue, 16> StChain; - if (ST->isTruncatingStore()) { - // For truncating stores, we can not play the tricks of chopping legal - // vector types and bit cast it to the right type. Instead, we unroll - // the store. - EVT StEltVT = StVT.getVectorElementType(); - EVT ValEltVT = ValVT.getVectorElementType(); - unsigned Increment = ValEltVT.getSizeInBits() / 8; - unsigned NumElts = StVT.getVectorNumElements(); - SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, ValEltVT, ValOp, - DAG.getIntPtrConstant(0)); - StChain.push_back(DAG.getTruncStore(Chain, dl, EOp, BasePtr, SV, - SVOffset, StEltVT, - isVolatile, Align)); - unsigned Offset = Increment; - for (unsigned i=1; i < NumElts; ++i, Offset += Increment) { - SDValue NewBasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), - BasePtr, DAG.getIntPtrConstant(Offset)); - SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, ValEltVT, ValOp, - DAG.getIntPtrConstant(0)); - StChain.push_back(DAG.getTruncStore(Chain, dl, EOp, NewBasePtr, SV, - SVOffset + Offset, StEltVT, - isVolatile, MinAlign(Align, Offset))); - } - } - else { - assert(StVT.getVectorElementType() == ValVT.getVectorElementType()); - // Store value - GenWidenVectorStores(StChain, Chain, BasePtr, SV, SVOffset, - Align, isVolatile, ValOp, StVT.getSizeInBits(), dl); - } + if (ST->isTruncatingStore()) + GenWidenVectorTruncStores(StChain, ST); + else + GenWidenVectorStores(StChain, ST); + if (StChain.size() == 1) return StChain[0]; else - return DAG.getNode(ISD::TokenFactor, dl, + return DAG.getNode(ISD::TokenFactor, ST->getDebugLoc(), MVT::Other,&StChain[0],StChain.size()); } @@ -2012,179 +2032,390 @@ SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) { // Vector Widening Utilities //===----------------------------------------------------------------------===// +// Utility function to find the type to chop up a widen vector for load/store +// TLI: Target lowering used to determine legal types. +// Width: Width left need to load/store. +// WidenVT: The widen vector type to load to/store from +// Align: If 0, don't allow use of a wider type +// WidenEx: If Align is not 0, the amount additional we can load/store from. + +static EVT FindMemType(SelectionDAG& DAG, const TargetLowering &TLI, + unsigned Width, EVT WidenVT, + unsigned Align = 0, unsigned WidenEx = 0) { + EVT WidenEltVT = WidenVT.getVectorElementType(); + unsigned WidenWidth = WidenVT.getSizeInBits(); + unsigned WidenEltWidth = WidenEltVT.getSizeInBits(); + unsigned AlignInBits = Align*8; + + // If we have one element to load/store, return it. + EVT RetVT = WidenEltVT; + if (Width == WidenEltWidth) + return RetVT; + + // See if there is larger legal integer than the element type to load/store + unsigned VT; + for (VT = (unsigned)MVT::LAST_INTEGER_VALUETYPE; + VT >= (unsigned)MVT::FIRST_INTEGER_VALUETYPE; --VT) { + EVT MemVT((MVT::SimpleValueType) VT); + unsigned MemVTWidth = MemVT.getSizeInBits(); + if (MemVT.getSizeInBits() <= WidenEltWidth) + break; + if (TLI.isTypeLegal(MemVT) && (WidenWidth % MemVTWidth) == 0 && + (MemVTWidth <= Width || + (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) { + RetVT = MemVT; + break; + } + } -// Utility function to find a vector type and its associated element -// type from a preferred width and whose vector type must be the same size -// as the VecVT. -// TLI: Target lowering used to determine legal types. -// Width: Preferred width to store. -// VecVT: Vector value type whose size we must match. -// Returns NewVecVT and NewEltVT - the vector type and its associated -// element type. -static void FindAssocWidenVecType(SelectionDAG& DAG, - const TargetLowering &TLI, unsigned Width, - EVT VecVT, - EVT& NewEltVT, EVT& NewVecVT) { - unsigned EltWidth = Width + 1; - if (TLI.isTypeLegal(VecVT)) { - // We start with the preferred with, making it a power of 2 and find a - // legal vector type of that width. If not, we reduce it by another of 2. - // For incoming type is legal, this process will end as a vector of the - // smallest loadable type should always be legal. - do { - assert(EltWidth > 0); - EltWidth = 1 << Log2_32(EltWidth - 1); - NewEltVT = EVT::getIntegerVT(*DAG.getContext(), EltWidth); - unsigned NumElts = VecVT.getSizeInBits() / EltWidth; - NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewEltVT, NumElts); - } while (!TLI.isTypeLegal(NewVecVT) || - VecVT.getSizeInBits() != NewVecVT.getSizeInBits()); - } else { - // The incoming vector type is illegal and is the result of widening - // a vector to a power of 2. In this case, we will use the preferred - // with as long as it is a multiple of the incoming vector length. - // The legalization process will eventually make this into a legal type - // and remove the illegal bit converts (which would turn to stack converts - // if they are allow to exist). - do { - assert(EltWidth > 0); - EltWidth = 1 << Log2_32(EltWidth - 1); - NewEltVT = EVT::getIntegerVT(*DAG.getContext(), EltWidth); - unsigned NumElts = VecVT.getSizeInBits() / EltWidth; - NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewEltVT, NumElts); - } while (!TLI.isTypeLegal(NewEltVT) || - VecVT.getSizeInBits() != NewVecVT.getSizeInBits()); + // See if there is a larger vector type to load/store that has the same vector + // element type and is evenly divisible with the WidenVT. + for (VT = (unsigned)MVT::LAST_VECTOR_VALUETYPE; + VT >= (unsigned)MVT::FIRST_VECTOR_VALUETYPE; --VT) { + EVT MemVT = (MVT::SimpleValueType) VT; + unsigned MemVTWidth = MemVT.getSizeInBits(); + if (TLI.isTypeLegal(MemVT) && WidenEltVT == MemVT.getVectorElementType() && + (WidenWidth % MemVTWidth) == 0 && + (MemVTWidth <= Width || + (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) { + if (RetVT.getSizeInBits() < MemVTWidth || MemVT == WidenVT) + return MemVT; + } } + + return RetVT; +} + +// Builds a vector type from scalar loads +// VecTy: Resulting Vector type +// LDOps: Load operators to build a vector type +// [Start,End) the list of loads to use. +static SDValue BuildVectorFromScalar(SelectionDAG& DAG, EVT VecTy, + SmallVector<SDValue, 16>& LdOps, + unsigned Start, unsigned End) { + DebugLoc dl = LdOps[Start].getDebugLoc(); + EVT LdTy = LdOps[Start].getValueType(); + unsigned Width = VecTy.getSizeInBits(); + unsigned NumElts = Width / LdTy.getSizeInBits(); + EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), LdTy, NumElts); + + unsigned Idx = 1; + SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT,LdOps[Start]); + + for (unsigned i = Start + 1; i != End; ++i) { + EVT NewLdTy = LdOps[i].getValueType(); + if (NewLdTy != LdTy) { + NumElts = Width / NewLdTy.getSizeInBits(); + NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewLdTy, NumElts); + VecOp = DAG.getNode(ISD::BIT_CONVERT, dl, NewVecVT, VecOp); + // Readjust position and vector position based on new load type + Idx = Idx * LdTy.getSizeInBits() / NewLdTy.getSizeInBits(); + LdTy = NewLdTy; + } + VecOp = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, NewVecVT, VecOp, LdOps[i], + DAG.getIntPtrConstant(Idx++)); + } + return DAG.getNode(ISD::BIT_CONVERT, dl, VecTy, VecOp); } SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVector<SDValue, 16>& LdChain, - SDValue Chain, - SDValue BasePtr, - const Value *SV, - int SVOffset, - unsigned Alignment, - bool isVolatile, - unsigned LdWidth, - EVT ResType, - DebugLoc dl) { + LoadSDNode * LD) { // The strategy assumes that we can efficiently load powers of two widths. - // The routines chops the vector into the largest power of 2 load and - // can be inserted into a legal vector and then cast the result into the - // vector type we want. This avoids unnecessary stack converts. + // The routines chops the vector into the largest vector loads with the same + // element type or scalar loads and then recombines it to the widen vector + // type. + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), LD->getValueType(0)); + unsigned WidenWidth = WidenVT.getSizeInBits(); + EVT LdVT = LD->getMemoryVT(); + DebugLoc dl = LD->getDebugLoc(); + assert(LdVT.isVector() && WidenVT.isVector()); + assert(LdVT.getVectorElementType() == WidenVT.getVectorElementType()); - // TODO: If the Ldwidth is legal, alignment is the same as the LdWidth, and - // the load is nonvolatile, we an use a wider load for the value. + // Load information + SDValue Chain = LD->getChain(); + SDValue BasePtr = LD->getBasePtr(); + int SVOffset = LD->getSrcValueOffset(); + unsigned Align = LD->getAlignment(); + bool isVolatile = LD->isVolatile(); + bool isNonTemporal = LD->isNonTemporal(); + const Value *SV = LD->getSrcValue(); + + int LdWidth = LdVT.getSizeInBits(); + int WidthDiff = WidenWidth - LdWidth; // Difference + unsigned LdAlign = (isVolatile) ? 0 : Align; // Allow wider loads // Find the vector type that can load from. - EVT NewEltVT, NewVecVT; - unsigned NewEltVTWidth; - FindAssocWidenVecType(DAG, TLI, LdWidth, ResType, NewEltVT, NewVecVT); - NewEltVTWidth = NewEltVT.getSizeInBits(); - - SDValue LdOp = DAG.getLoad(NewEltVT, dl, Chain, BasePtr, SV, SVOffset, - isVolatile, Alignment); - SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp); + EVT NewVT = FindMemType(DAG, TLI, LdWidth, WidenVT, LdAlign, WidthDiff); + int NewVTWidth = NewVT.getSizeInBits(); + SDValue LdOp = DAG.getLoad(NewVT, dl, Chain, BasePtr, SV, SVOffset, + isVolatile, isNonTemporal, Align); LdChain.push_back(LdOp.getValue(1)); // Check if we can load the element with one instruction - if (LdWidth == NewEltVTWidth) { - return DAG.getNode(ISD::BIT_CONVERT, dl, ResType, VecOp); + if (LdWidth <= NewVTWidth) { + if (NewVT.isVector()) { + if (NewVT != WidenVT) { + assert(WidenWidth % NewVTWidth == 0); + unsigned NumConcat = WidenWidth / NewVTWidth; + SmallVector<SDValue, 16> ConcatOps(NumConcat); + SDValue UndefVal = DAG.getUNDEF(NewVT); + ConcatOps[0] = LdOp; + for (unsigned i = 1; i != NumConcat; ++i) + ConcatOps[i] = UndefVal; + return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, &ConcatOps[0], + NumConcat); + } else + return LdOp; + } else { + unsigned NumElts = WidenWidth / LdWidth; + EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts); + SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp); + return DAG.getNode(ISD::BIT_CONVERT, dl, WidenVT, VecOp); + } } - unsigned Idx = 1; - LdWidth -= NewEltVTWidth; + // Load vector by using multiple loads from largest vector to scalar + SmallVector<SDValue, 16> LdOps; + LdOps.push_back(LdOp); + + LdWidth -= NewVTWidth; unsigned Offset = 0; while (LdWidth > 0) { - unsigned Increment = NewEltVTWidth / 8; + unsigned Increment = NewVTWidth / 8; Offset += Increment; BasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), BasePtr, DAG.getIntPtrConstant(Increment)); - if (LdWidth < NewEltVTWidth) { - // Our current type we are using is too large, use a smaller size by - // using a smaller power of 2 - unsigned oNewEltVTWidth = NewEltVTWidth; - FindAssocWidenVecType(DAG, TLI, LdWidth, ResType, NewEltVT, NewVecVT); - NewEltVTWidth = NewEltVT.getSizeInBits(); - // Readjust position and vector position based on new load type - Idx = Idx * (oNewEltVTWidth/NewEltVTWidth); - VecOp = DAG.getNode(ISD::BIT_CONVERT, dl, NewVecVT, VecOp); + if (LdWidth < NewVTWidth) { + // Our current type we are using is too large, find a better size + NewVT = FindMemType(DAG, TLI, LdWidth, WidenVT, LdAlign, WidthDiff); + NewVTWidth = NewVT.getSizeInBits(); } - SDValue LdOp = DAG.getLoad(NewEltVT, dl, Chain, BasePtr, SV, - SVOffset+Offset, isVolatile, - MinAlign(Alignment, Offset)); + SDValue LdOp = DAG.getLoad(NewVT, dl, Chain, BasePtr, SV, + SVOffset+Offset, isVolatile, + isNonTemporal, MinAlign(Align, Increment)); LdChain.push_back(LdOp.getValue(1)); - VecOp = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, NewVecVT, VecOp, LdOp, - DAG.getIntPtrConstant(Idx++)); + LdOps.push_back(LdOp); - LdWidth -= NewEltVTWidth; + LdWidth -= NewVTWidth; } - return DAG.getNode(ISD::BIT_CONVERT, dl, ResType, VecOp); -} + // Build the vector from the loads operations + unsigned End = LdOps.size(); + if (LdOps[0].getValueType().isVector()) { + // If the load contains vectors, build the vector using concat vector. + // All of the vectors used to loads are power of 2 and the scalars load + // can be combined to make a power of 2 vector. + SmallVector<SDValue, 16> ConcatOps(End); + int i = End - 1; + int Idx = End; + EVT LdTy = LdOps[i].getValueType(); + // First combine the scalar loads to a vector + if (!LdTy.isVector()) { + for (--i; i >= 0; --i) { + LdTy = LdOps[i].getValueType(); + if (LdTy.isVector()) + break; + } + ConcatOps[--Idx] = BuildVectorFromScalar(DAG, LdTy, LdOps, i+1, End); + } + ConcatOps[--Idx] = LdOps[i]; + for (--i; i >= 0; --i) { + EVT NewLdTy = LdOps[i].getValueType(); + if (NewLdTy != LdTy) { + // Create a larger vector + ConcatOps[End-1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewLdTy, + &ConcatOps[Idx], End - Idx); + Idx = End - 1; + LdTy = NewLdTy; + } + ConcatOps[--Idx] = LdOps[i]; + } -void DAGTypeLegalizer::GenWidenVectorStores(SmallVector<SDValue, 16>& StChain, - SDValue Chain, - SDValue BasePtr, - const Value *SV, - int SVOffset, - unsigned Alignment, - bool isVolatile, - SDValue ValOp, - unsigned StWidth, - DebugLoc dl) { - // Breaks the stores into a series of power of 2 width stores. For any - // width, we convert the vector to the vector of element size that we - // want to store. This avoids requiring a stack convert. - - // Find a width of the element type we can store with - EVT WidenVT = ValOp.getValueType(); - EVT NewEltVT, NewVecVT; - - FindAssocWidenVecType(DAG, TLI, StWidth, WidenVT, NewEltVT, NewVecVT); - unsigned NewEltVTWidth = NewEltVT.getSizeInBits(); - - SDValue VecOp = DAG.getNode(ISD::BIT_CONVERT, dl, NewVecVT, ValOp); - SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NewEltVT, VecOp, - DAG.getIntPtrConstant(0)); - SDValue StOp = DAG.getStore(Chain, dl, EOp, BasePtr, SV, SVOffset, - isVolatile, Alignment); - StChain.push_back(StOp); + if (WidenWidth != LdTy.getSizeInBits()*(End - Idx)) { + // We need to fill the rest with undefs to build the vector + unsigned NumOps = WidenWidth / LdTy.getSizeInBits(); + SmallVector<SDValue, 16> WidenOps(NumOps); + SDValue UndefVal = DAG.getUNDEF(LdTy); + unsigned i = 0; + for (; i != End-Idx; ++i) + WidenOps[i] = ConcatOps[Idx+i]; + for (; i != NumOps; ++i) + WidenOps[i] = UndefVal; + return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, &WidenOps[0],NumOps); + } else + return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, + &ConcatOps[Idx], End - Idx); + } else // All the loads are scalar loads. + return BuildVectorFromScalar(DAG, WidenVT, LdOps, 0, End); +} + +SDValue +DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVector<SDValue, 16>& LdChain, + LoadSDNode * LD, + ISD::LoadExtType ExtType) { + // For extension loads, it may not be more efficient to chop up the vector + // and then extended it. Instead, we unroll the load and build a new vector. + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0)); + EVT LdVT = LD->getMemoryVT(); + DebugLoc dl = LD->getDebugLoc(); + assert(LdVT.isVector() && WidenVT.isVector()); - // Check if we are done - if (StWidth == NewEltVTWidth) { - return; + // Load information + SDValue Chain = LD->getChain(); + SDValue BasePtr = LD->getBasePtr(); + int SVOffset = LD->getSrcValueOffset(); + unsigned Align = LD->getAlignment(); + bool isVolatile = LD->isVolatile(); + bool isNonTemporal = LD->isNonTemporal(); + const Value *SV = LD->getSrcValue(); + + EVT EltVT = WidenVT.getVectorElementType(); + EVT LdEltVT = LdVT.getVectorElementType(); + unsigned NumElts = LdVT.getVectorNumElements(); + + // Load each element and widen + unsigned WidenNumElts = WidenVT.getVectorNumElements(); + SmallVector<SDValue, 16> Ops(WidenNumElts); + unsigned Increment = LdEltVT.getSizeInBits() / 8; + Ops[0] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, SV, SVOffset, + LdEltVT, isVolatile, isNonTemporal, Align); + LdChain.push_back(Ops[0].getValue(1)); + unsigned i = 0, Offset = Increment; + for (i=1; i < NumElts; ++i, Offset += Increment) { + SDValue NewBasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), + BasePtr, DAG.getIntPtrConstant(Offset)); + Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr, SV, + SVOffset + Offset, LdEltVT, isVolatile, + isNonTemporal, Align); + LdChain.push_back(Ops[i].getValue(1)); } - unsigned Idx = 1; - StWidth -= NewEltVTWidth; - unsigned Offset = 0; + // Fill the rest with undefs + SDValue UndefVal = DAG.getUNDEF(EltVT); + for (; i != WidenNumElts; ++i) + Ops[i] = UndefVal; - while (StWidth > 0) { - unsigned Increment = NewEltVTWidth / 8; - Offset += Increment; - BasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), BasePtr, - DAG.getIntPtrConstant(Increment)); + return DAG.getNode(ISD::BUILD_VECTOR, dl, WidenVT, &Ops[0], Ops.size()); +} - if (StWidth < NewEltVTWidth) { - // Our current type we are using is too large, use a smaller size by - // using a smaller power of 2 - unsigned oNewEltVTWidth = NewEltVTWidth; - FindAssocWidenVecType(DAG, TLI, StWidth, WidenVT, NewEltVT, NewVecVT); - NewEltVTWidth = NewEltVT.getSizeInBits(); - // Readjust position and vector position based on new load type - Idx = Idx * (oNewEltVTWidth/NewEltVTWidth); - VecOp = DAG.getNode(ISD::BIT_CONVERT, dl, NewVecVT, VecOp); - } - EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NewEltVT, VecOp, +void DAGTypeLegalizer::GenWidenVectorStores(SmallVector<SDValue, 16>& StChain, + StoreSDNode *ST) { + // The strategy assumes that we can efficiently store powers of two widths. + // The routines chops the vector into the largest vector stores with the same + // element type or scalar stores. + SDValue Chain = ST->getChain(); + SDValue BasePtr = ST->getBasePtr(); + const Value *SV = ST->getSrcValue(); + int SVOffset = ST->getSrcValueOffset(); + unsigned Align = ST->getAlignment(); + bool isVolatile = ST->isVolatile(); + bool isNonTemporal = ST->isNonTemporal(); + SDValue ValOp = GetWidenedVector(ST->getValue()); + DebugLoc dl = ST->getDebugLoc(); + + EVT StVT = ST->getMemoryVT(); + unsigned StWidth = StVT.getSizeInBits(); + EVT ValVT = ValOp.getValueType(); + unsigned ValWidth = ValVT.getSizeInBits(); + EVT ValEltVT = ValVT.getVectorElementType(); + unsigned ValEltWidth = ValEltVT.getSizeInBits(); + assert(StVT.getVectorElementType() == ValEltVT); + + int Idx = 0; // current index to store + unsigned Offset = 0; // offset from base to store + while (StWidth != 0) { + // Find the largest vector type we can store with + EVT NewVT = FindMemType(DAG, TLI, StWidth, ValVT); + unsigned NewVTWidth = NewVT.getSizeInBits(); + unsigned Increment = NewVTWidth / 8; + if (NewVT.isVector()) { + unsigned NumVTElts = NewVT.getVectorNumElements(); + do { + SDValue EOp = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, NewVT, ValOp, + DAG.getIntPtrConstant(Idx)); + StChain.push_back(DAG.getStore(Chain, dl, EOp, BasePtr, SV, + SVOffset + Offset, isVolatile, + isNonTemporal, + MinAlign(Align, Offset))); + StWidth -= NewVTWidth; + Offset += Increment; + Idx += NumVTElts; + BasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), BasePtr, + DAG.getIntPtrConstant(Increment)); + } while (StWidth != 0 && StWidth >= NewVTWidth); + } else { + // Cast the vector to the scalar type we can store + unsigned NumElts = ValWidth / NewVTWidth; + EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts); + SDValue VecOp = DAG.getNode(ISD::BIT_CONVERT, dl, NewVecVT, ValOp); + // Readjust index position based on new vector type + Idx = Idx * ValEltWidth / NewVTWidth; + do { + SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NewVT, VecOp, DAG.getIntPtrConstant(Idx++)); - StChain.push_back(DAG.getStore(Chain, dl, EOp, BasePtr, SV, - SVOffset + Offset, isVolatile, - MinAlign(Alignment, Offset))); - StWidth -= NewEltVTWidth; + StChain.push_back(DAG.getStore(Chain, dl, EOp, BasePtr, SV, + SVOffset + Offset, isVolatile, + isNonTemporal, MinAlign(Align, Offset))); + StWidth -= NewVTWidth; + Offset += Increment; + BasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), BasePtr, + DAG.getIntPtrConstant(Increment)); + } while (StWidth != 0 && StWidth >= NewVTWidth); + // Restore index back to be relative to the original widen element type + Idx = Idx * NewVTWidth / ValEltWidth; + } + } +} + +void +DAGTypeLegalizer::GenWidenVectorTruncStores(SmallVector<SDValue, 16>& StChain, + StoreSDNode *ST) { + // For extension loads, it may not be more efficient to truncate the vector + // and then store it. Instead, we extract each element and then store it. + SDValue Chain = ST->getChain(); + SDValue BasePtr = ST->getBasePtr(); + const Value *SV = ST->getSrcValue(); + int SVOffset = ST->getSrcValueOffset(); + unsigned Align = ST->getAlignment(); + bool isVolatile = ST->isVolatile(); + bool isNonTemporal = ST->isNonTemporal(); + SDValue ValOp = GetWidenedVector(ST->getValue()); + DebugLoc dl = ST->getDebugLoc(); + + EVT StVT = ST->getMemoryVT(); + EVT ValVT = ValOp.getValueType(); + + // It must be true that we the widen vector type is bigger than where + // we need to store. + assert(StVT.isVector() && ValOp.getValueType().isVector()); + assert(StVT.bitsLT(ValOp.getValueType())); + + // For truncating stores, we can not play the tricks of chopping legal + // vector types and bit cast it to the right type. Instead, we unroll + // the store. + EVT StEltVT = StVT.getVectorElementType(); + EVT ValEltVT = ValVT.getVectorElementType(); + unsigned Increment = ValEltVT.getSizeInBits() / 8; + unsigned NumElts = StVT.getVectorNumElements(); + SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, ValEltVT, ValOp, + DAG.getIntPtrConstant(0)); + StChain.push_back(DAG.getTruncStore(Chain, dl, EOp, BasePtr, SV, + SVOffset, StEltVT, + isVolatile, isNonTemporal, Align)); + unsigned Offset = Increment; + for (unsigned i=1; i < NumElts; ++i, Offset += Increment) { + SDValue NewBasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), + BasePtr, DAG.getIntPtrConstant(Offset)); + SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, ValEltVT, ValOp, + DAG.getIntPtrConstant(0)); + StChain.push_back(DAG.getTruncStore(Chain, dl, EOp, NewBasePtr, SV, + SVOffset + Offset, StEltVT, + isVolatile, isNonTemporal, + MinAlign(Align, Offset))); } } diff --git a/lib/CodeGen/SelectionDAG/Makefile b/lib/CodeGen/SelectionDAG/Makefile index 4706e68..ea716fd 100644 --- a/lib/CodeGen/SelectionDAG/Makefile +++ b/lib/CodeGen/SelectionDAG/Makefile @@ -9,6 +9,5 @@ LEVEL = ../../.. LIBRARYNAME = LLVMSelectionDAG -CXXFLAGS = -fno-rtti include $(LEVEL)/Makefile.common diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp index dea5993..3f1766d 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp @@ -345,6 +345,15 @@ void ScheduleDAGRRList::BacktrackBottomUp(SUnit *SU, unsigned BtCycle, ++NumBacktracks; } +static bool isOperandOf(const SUnit *SU, SDNode *N) { + for (const SDNode *SUNode = SU->getNode(); SUNode; + SUNode = SUNode->getFlaggedNode()) { + if (SUNode->isOperandOf(N)) + return true; + } + return false; +} + /// CopyAndMoveSuccessors - Clone the specified node and move its scheduled /// successors to the newly created node. SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(SUnit *SU) { @@ -427,8 +436,7 @@ SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(SUnit *SU) { I != E; ++I) { if (I->isCtrl()) ChainPreds.push_back(*I); - else if (I->getSUnit()->getNode() && - I->getSUnit()->getNode()->isOperandOf(LoadNode)) + else if (isOperandOf(I->getSUnit(), LoadNode)) LoadPreds.push_back(*I); else NodePreds.push_back(*I); @@ -1034,9 +1042,9 @@ namespace { // CopyToReg should be close to its uses to facilitate coalescing and // avoid spilling. return 0; - if (Opc == TargetInstrInfo::EXTRACT_SUBREG || - Opc == TargetInstrInfo::SUBREG_TO_REG || - Opc == TargetInstrInfo::INSERT_SUBREG) + if (Opc == TargetOpcode::EXTRACT_SUBREG || + Opc == TargetOpcode::SUBREG_TO_REG || + Opc == TargetOpcode::INSERT_SUBREG) // EXTRACT_SUBREG, INSERT_SUBREG, and SUBREG_TO_REG nodes should be // close to their uses to facilitate coalescing. return 0; @@ -1437,7 +1445,7 @@ void RegReductionPriorityQueue<SF>::AddPseudoTwoAddrDeps() { while (SuccSU->Succs.size() == 1 && SuccSU->getNode()->isMachineOpcode() && SuccSU->getNode()->getMachineOpcode() == - TargetInstrInfo::COPY_TO_REGCLASS) + TargetOpcode::COPY_TO_REGCLASS) SuccSU = SuccSU->Succs.front().getSUnit(); // Don't constrain non-instruction nodes. if (!SuccSU->getNode() || !SuccSU->getNode()->isMachineOpcode()) @@ -1451,9 +1459,9 @@ void RegReductionPriorityQueue<SF>::AddPseudoTwoAddrDeps() { // Don't constrain EXTRACT_SUBREG, INSERT_SUBREG, and SUBREG_TO_REG; // these may be coalesced away. We want them close to their uses. unsigned SuccOpc = SuccSU->getNode()->getMachineOpcode(); - if (SuccOpc == TargetInstrInfo::EXTRACT_SUBREG || - SuccOpc == TargetInstrInfo::INSERT_SUBREG || - SuccOpc == TargetInstrInfo::SUBREG_TO_REG) + if (SuccOpc == TargetOpcode::EXTRACT_SUBREG || + SuccOpc == TargetOpcode::INSERT_SUBREG || + SuccOpc == TargetOpcode::SUBREG_TO_REG) continue; if ((!canClobber(SuccSU, DUSU) || (hasCopyToRegUse(SU) && !hasCopyToRegUse(SuccSU)) || diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index f1b6f1e..43cf37e 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -829,6 +829,7 @@ void SelectionDAG::clear() { EntryNode.UseList = 0; AllNodes.push_back(&EntryNode); Root = getEntryNode(); + delete Ordering; Ordering = new SDNodeOrdering(); } @@ -1925,19 +1926,28 @@ void SelectionDAG::ComputeMaskedBits(SDValue Op, const APInt &Mask, } case ISD::SREM: if (ConstantSDNode *Rem = dyn_cast<ConstantSDNode>(Op.getOperand(1))) { - const APInt &RA = Rem->getAPIntValue(); - if (RA.isPowerOf2() || (-RA).isPowerOf2()) { - APInt LowBits = RA.isStrictlyPositive() ? (RA - 1) : ~RA; + const APInt &RA = Rem->getAPIntValue().abs(); + if (RA.isPowerOf2()) { + APInt LowBits = RA - 1; APInt Mask2 = LowBits | APInt::getSignBit(BitWidth); ComputeMaskedBits(Op.getOperand(0), Mask2,KnownZero2,KnownOne2,Depth+1); - // If the sign bit of the first operand is zero, the sign bit of - // the result is zero. If the first operand has no one bits below - // the second operand's single 1 bit, its sign will be zero. + // The low bits of the first operand are unchanged by the srem. + KnownZero = KnownZero2 & LowBits; + KnownOne = KnownOne2 & LowBits; + + // If the first operand is non-negative or has all low bits zero, then + // the upper bits are all zero. if (KnownZero2[BitWidth-1] || ((KnownZero2 & LowBits) == LowBits)) - KnownZero2 |= ~LowBits; + KnownZero |= ~LowBits; - KnownZero |= KnownZero2 & Mask; + // If the first operand is negative and not all low bits are zero, then + // the upper bits are all one. + if (KnownOne2[BitWidth-1] && ((KnownOne2 & LowBits) != 0)) + KnownOne |= ~LowBits; + + KnownZero &= Mask; + KnownOne &= Mask; assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?"); } @@ -2755,13 +2765,16 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT, // EXTRACT_VECTOR_ELT of INSERT_VECTOR_ELT is often formed when vector // operations are lowered to scalars. if (N1.getOpcode() == ISD::INSERT_VECTOR_ELT) { - // If the indices are the same, return the inserted element. - if (N1.getOperand(2) == N2) - return N1.getOperand(1); - // If the indices are known different, extract the element from + // If the indices are the same, return the inserted element else + // if the indices are known different, extract the element from // the original vector. - else if (isa<ConstantSDNode>(N1.getOperand(2)) && - isa<ConstantSDNode>(N2)) + if (N1.getOperand(2) == N2) { + if (VT == N1.getOperand(1).getValueType()) + return N1.getOperand(1); + else + return getSExtOrTrunc(N1.getOperand(1), DL, VT); + } else if (isa<ConstantSDNode>(N1.getOperand(2)) && + isa<ConstantSDNode>(N2)) return getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, N1.getOperand(0), N2); } break; @@ -3287,7 +3300,7 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, Value = getMemsetStringVal(VT, dl, DAG, TLI, Str, SrcOff); Store = DAG.getStore(Chain, dl, Value, getMemBasePlusOffset(Dst, DstOff, DAG), - DstSV, DstSVOff + DstOff, false, DstAlign); + DstSV, DstSVOff + DstOff, false, false, DstAlign); } else { // The type might not be legal for the target. This should only happen // if the type is smaller than a legal type, as on PPC, so the right @@ -3298,10 +3311,11 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, assert(NVT.bitsGE(VT)); Value = DAG.getExtLoad(ISD::EXTLOAD, dl, NVT, Chain, getMemBasePlusOffset(Src, SrcOff, DAG), - SrcSV, SrcSVOff + SrcOff, VT, false, Align); + SrcSV, SrcSVOff + SrcOff, VT, false, false, Align); Store = DAG.getTruncStore(Chain, dl, Value, - getMemBasePlusOffset(Dst, DstOff, DAG), - DstSV, DstSVOff + DstOff, VT, false, DstAlign); + getMemBasePlusOffset(Dst, DstOff, DAG), + DstSV, DstSVOff + DstOff, VT, false, false, + DstAlign); } OutChains.push_back(Store); SrcOff += VTSize; @@ -3346,7 +3360,7 @@ static SDValue getMemmoveLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, Value = DAG.getLoad(VT, dl, Chain, getMemBasePlusOffset(Src, SrcOff, DAG), - SrcSV, SrcSVOff + SrcOff, false, Align); + SrcSV, SrcSVOff + SrcOff, false, false, Align); LoadValues.push_back(Value); LoadChains.push_back(Value.getValue(1)); SrcOff += VTSize; @@ -3361,7 +3375,7 @@ static SDValue getMemmoveLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, Store = DAG.getStore(Chain, dl, LoadValues[i], getMemBasePlusOffset(Dst, DstOff, DAG), - DstSV, DstSVOff + DstOff, false, DstAlign); + DstSV, DstSVOff + DstOff, false, false, DstAlign); OutChains.push_back(Store); DstOff += VTSize; } @@ -3396,7 +3410,7 @@ static SDValue getMemsetStores(SelectionDAG &DAG, DebugLoc dl, SDValue Value = getMemsetValue(Src, VT, DAG, dl); SDValue Store = DAG.getStore(Chain, dl, Value, getMemBasePlusOffset(Dst, DstOff, DAG), - DstSV, DstSVOff + DstOff); + DstSV, DstSVOff + DstOff, false, false, 0); OutChains.push_back(Store); DstOff += VTSize; } @@ -3776,7 +3790,8 @@ SelectionDAG::getLoad(ISD::MemIndexedMode AM, DebugLoc dl, ISD::LoadExtType ExtType, EVT VT, SDValue Chain, SDValue Ptr, SDValue Offset, const Value *SV, int SVOffset, EVT MemVT, - bool isVolatile, unsigned Alignment) { + bool isVolatile, bool isNonTemporal, + unsigned Alignment) { if (Alignment == 0) // Ensure that codegen never sees alignment 0 Alignment = getEVTAlignment(VT); @@ -3790,6 +3805,8 @@ SelectionDAG::getLoad(ISD::MemIndexedMode AM, DebugLoc dl, unsigned Flags = MachineMemOperand::MOLoad; if (isVolatile) Flags |= MachineMemOperand::MOVolatile; + if (isNonTemporal) + Flags |= MachineMemOperand::MONonTemporal; MachineMemOperand *MMO = MF.getMachineMemOperand(SV, Flags, SVOffset, MemVT.getStoreSize(), Alignment); @@ -3844,20 +3861,22 @@ SelectionDAG::getLoad(ISD::MemIndexedMode AM, DebugLoc dl, SDValue SelectionDAG::getLoad(EVT VT, DebugLoc dl, SDValue Chain, SDValue Ptr, const Value *SV, int SVOffset, - bool isVolatile, unsigned Alignment) { + bool isVolatile, bool isNonTemporal, + unsigned Alignment) { SDValue Undef = getUNDEF(Ptr.getValueType()); return getLoad(ISD::UNINDEXED, dl, ISD::NON_EXTLOAD, VT, Chain, Ptr, Undef, - SV, SVOffset, VT, isVolatile, Alignment); + SV, SVOffset, VT, isVolatile, isNonTemporal, Alignment); } SDValue SelectionDAG::getExtLoad(ISD::LoadExtType ExtType, DebugLoc dl, EVT VT, SDValue Chain, SDValue Ptr, const Value *SV, int SVOffset, EVT MemVT, - bool isVolatile, unsigned Alignment) { + bool isVolatile, bool isNonTemporal, + unsigned Alignment) { SDValue Undef = getUNDEF(Ptr.getValueType()); return getLoad(ISD::UNINDEXED, dl, ExtType, VT, Chain, Ptr, Undef, - SV, SVOffset, MemVT, isVolatile, Alignment); + SV, SVOffset, MemVT, isVolatile, isNonTemporal, Alignment); } SDValue @@ -3869,12 +3888,13 @@ SelectionDAG::getIndexedLoad(SDValue OrigLoad, DebugLoc dl, SDValue Base, return getLoad(AM, dl, LD->getExtensionType(), OrigLoad.getValueType(), LD->getChain(), Base, Offset, LD->getSrcValue(), LD->getSrcValueOffset(), LD->getMemoryVT(), - LD->isVolatile(), LD->getAlignment()); + LD->isVolatile(), LD->isNonTemporal(), LD->getAlignment()); } SDValue SelectionDAG::getStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, const Value *SV, int SVOffset, - bool isVolatile, unsigned Alignment) { + bool isVolatile, bool isNonTemporal, + unsigned Alignment) { if (Alignment == 0) // Ensure that codegen never sees alignment 0 Alignment = getEVTAlignment(Val.getValueType()); @@ -3888,6 +3908,8 @@ SDValue SelectionDAG::getStore(SDValue Chain, DebugLoc dl, SDValue Val, unsigned Flags = MachineMemOperand::MOStore; if (isVolatile) Flags |= MachineMemOperand::MOVolatile; + if (isNonTemporal) + Flags |= MachineMemOperand::MONonTemporal; MachineMemOperand *MMO = MF.getMachineMemOperand(SV, Flags, SVOffset, Val.getValueType().getStoreSize(), Alignment); @@ -3920,7 +3942,8 @@ SDValue SelectionDAG::getStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue SelectionDAG::getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, const Value *SV, int SVOffset, EVT SVT, - bool isVolatile, unsigned Alignment) { + bool isVolatile, bool isNonTemporal, + unsigned Alignment) { if (Alignment == 0) // Ensure that codegen never sees alignment 0 Alignment = getEVTAlignment(SVT); @@ -3934,6 +3957,8 @@ SDValue SelectionDAG::getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, unsigned Flags = MachineMemOperand::MOStore; if (isVolatile) Flags |= MachineMemOperand::MOVolatile; + if (isNonTemporal) + Flags |= MachineMemOperand::MONonTemporal; MachineMemOperand *MMO = MF.getMachineMemOperand(SV, Flags, SVOffset, SVT.getStoreSize(), Alignment); @@ -4860,23 +4885,23 @@ SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, } /// getTargetExtractSubreg - A convenience function for creating -/// TargetInstrInfo::EXTRACT_SUBREG nodes. +/// TargetOpcode::EXTRACT_SUBREG nodes. SDValue SelectionDAG::getTargetExtractSubreg(int SRIdx, DebugLoc DL, EVT VT, SDValue Operand) { SDValue SRIdxVal = getTargetConstant(SRIdx, MVT::i32); - SDNode *Subreg = getMachineNode(TargetInstrInfo::EXTRACT_SUBREG, DL, + SDNode *Subreg = getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, VT, Operand, SRIdxVal); return SDValue(Subreg, 0); } /// getTargetInsertSubreg - A convenience function for creating -/// TargetInstrInfo::INSERT_SUBREG nodes. +/// TargetOpcode::INSERT_SUBREG nodes. SDValue SelectionDAG::getTargetInsertSubreg(int SRIdx, DebugLoc DL, EVT VT, SDValue Operand, SDValue Subreg) { SDValue SRIdxVal = getTargetConstant(SRIdx, MVT::i32); - SDNode *Result = getMachineNode(TargetInstrInfo::INSERT_SUBREG, DL, + SDNode *Result = getMachineNode(TargetOpcode::INSERT_SUBREG, DL, VT, Operand, Subreg, SRIdxVal); return SDValue(Result, 0); } @@ -5212,11 +5237,12 @@ unsigned SelectionDAG::AssignTopologicalOrder() { } } if (I == SortedPos) { - allnodes_iterator J = I; - SDNode *S = ++J; - dbgs() << "Offending node:\n"; +#ifndef NDEBUG + SDNode *S = ++I; + dbgs() << "Overran sorted position:\n"; S->dumprFull(); - assert(0 && "Overran sorted position"); +#endif + llvm_unreachable(0); } } @@ -5237,7 +5263,7 @@ unsigned SelectionDAG::AssignTopologicalOrder() { } /// AssignOrdering - Assign an order to the SDNode. -void SelectionDAG::AssignOrdering(SDNode *SD, unsigned Order) { +void SelectionDAG::AssignOrdering(const SDNode *SD, unsigned Order) { assert(SD && "Trying to assign an order to a null node!"); Ordering->add(SD, Order); } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 23c7059..85ecb95 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -131,6 +131,17 @@ namespace { } } + /// areValueTypesLegal - Return true if types of all the values are legal. + bool areValueTypesLegal() { + for (unsigned Value = 0, e = ValueVTs.size(); Value != e; ++Value) { + EVT RegisterVT = RegVTs[Value]; + if (!TLI->isTypeLegal(RegisterVT)) + return false; + } + return true; + } + + /// append - Add the specified values to this one. void append(const RegsForValue &RHS) { TLI = RHS.TLI; @@ -176,7 +187,6 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, assert(NumParts > 0 && "No parts to assemble!"); const TargetLowering &TLI = DAG.getTargetLoweringInfo(); SDValue Val = Parts[0]; - DAG.AssignOrdering(Val.getNode(), Order); if (NumParts > 1) { // Assemble the value from multiple parts. @@ -209,10 +219,6 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, Val = DAG.getNode(ISD::BUILD_PAIR, dl, RoundVT, Lo, Hi); - DAG.AssignOrdering(Lo.getNode(), Order); - DAG.AssignOrdering(Hi.getNode(), Order); - DAG.AssignOrdering(Val.getNode(), Order); - if (RoundParts < NumParts) { // Assemble the trailing non-power-of-2 part. unsigned OddParts = NumParts - RoundParts; @@ -226,15 +232,11 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, std::swap(Lo, Hi); EVT TotalVT = EVT::getIntegerVT(*DAG.getContext(), NumParts * PartBits); Hi = DAG.getNode(ISD::ANY_EXTEND, dl, TotalVT, Hi); - DAG.AssignOrdering(Hi.getNode(), Order); Hi = DAG.getNode(ISD::SHL, dl, TotalVT, Hi, DAG.getConstant(Lo.getValueType().getSizeInBits(), TLI.getPointerTy())); - DAG.AssignOrdering(Hi.getNode(), Order); Lo = DAG.getNode(ISD::ZERO_EXTEND, dl, TotalVT, Lo); - DAG.AssignOrdering(Lo.getNode(), Order); Val = DAG.getNode(ISD::OR, dl, TotalVT, Lo, Hi); - DAG.AssignOrdering(Val.getNode(), Order); } } else if (ValueVT.isVector()) { // Handle a multi-element vector. @@ -275,7 +277,6 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, Val = DAG.getNode(IntermediateVT.isVector() ? ISD::CONCAT_VECTORS : ISD::BUILD_VECTOR, dl, ValueVT, &Ops[0], NumIntermediates); - DAG.AssignOrdering(Val.getNode(), Order); } else if (PartVT.isFloatingPoint()) { // FP split into multiple FP parts (for ppcf128) assert(ValueVT == EVT(MVT::ppcf128) && PartVT == EVT(MVT::f64) && @@ -286,10 +287,6 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, if (TLI.isBigEndian()) std::swap(Lo, Hi); Val = DAG.getNode(ISD::BUILD_PAIR, dl, ValueVT, Lo, Hi); - - DAG.AssignOrdering(Hi.getNode(), Order); - DAG.AssignOrdering(Lo.getNode(), Order); - DAG.AssignOrdering(Val.getNode(), Order); } else { // FP split into integer parts (soft fp) assert(ValueVT.isFloatingPoint() && PartVT.isInteger() && @@ -307,18 +304,14 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, if (PartVT.isVector()) { assert(ValueVT.isVector() && "Unknown vector conversion!"); - SDValue Res = DAG.getNode(ISD::BIT_CONVERT, dl, ValueVT, Val); - DAG.AssignOrdering(Res.getNode(), Order); - return Res; + return DAG.getNode(ISD::BIT_CONVERT, dl, ValueVT, Val); } if (ValueVT.isVector()) { assert(ValueVT.getVectorElementType() == PartVT && ValueVT.getVectorNumElements() == 1 && "Only trivial scalar-to-vector conversions should get here!"); - SDValue Res = DAG.getNode(ISD::BUILD_VECTOR, dl, ValueVT, Val); - DAG.AssignOrdering(Res.getNode(), Order); - return Res; + return DAG.getNode(ISD::BUILD_VECTOR, dl, ValueVT, Val); } if (PartVT.isInteger() && @@ -330,36 +323,24 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, if (AssertOp != ISD::DELETED_NODE) Val = DAG.getNode(AssertOp, dl, PartVT, Val, DAG.getValueType(ValueVT)); - DAG.AssignOrdering(Val.getNode(), Order); - Val = DAG.getNode(ISD::TRUNCATE, dl, ValueVT, Val); - DAG.AssignOrdering(Val.getNode(), Order); - return Val; + return DAG.getNode(ISD::TRUNCATE, dl, ValueVT, Val); } else { - Val = DAG.getNode(ISD::ANY_EXTEND, dl, ValueVT, Val); - DAG.AssignOrdering(Val.getNode(), Order); - return Val; + return DAG.getNode(ISD::ANY_EXTEND, dl, ValueVT, Val); } } if (PartVT.isFloatingPoint() && ValueVT.isFloatingPoint()) { if (ValueVT.bitsLT(Val.getValueType())) { // FP_ROUND's are always exact here. - Val = DAG.getNode(ISD::FP_ROUND, dl, ValueVT, Val, - DAG.getIntPtrConstant(1)); - DAG.AssignOrdering(Val.getNode(), Order); - return Val; + return DAG.getNode(ISD::FP_ROUND, dl, ValueVT, Val, + DAG.getIntPtrConstant(1)); } - Val = DAG.getNode(ISD::FP_EXTEND, dl, ValueVT, Val); - DAG.AssignOrdering(Val.getNode(), Order); - return Val; + return DAG.getNode(ISD::FP_EXTEND, dl, ValueVT, Val); } - if (PartVT.getSizeInBits() == ValueVT.getSizeInBits()) { - Val = DAG.getNode(ISD::BIT_CONVERT, dl, ValueVT, Val); - DAG.AssignOrdering(Val.getNode(), Order); - return Val; - } + if (PartVT.getSizeInBits() == ValueVT.getSizeInBits()) + return DAG.getNode(ISD::BIT_CONVERT, dl, ValueVT, Val); llvm_unreachable("Unknown mismatch!"); return SDValue(); @@ -414,8 +395,6 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, } } - DAG.AssignOrdering(Val.getNode(), Order); - // The value may have changed - recompute ValueVT. ValueVT = Val.getValueType(); assert(NumParts * PartBits == ValueVT.getSizeInBits() && @@ -448,9 +427,6 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, NumParts = RoundParts; ValueVT = EVT::getIntegerVT(*DAG.getContext(), NumParts * PartBits); Val = DAG.getNode(ISD::TRUNCATE, dl, ValueVT, Val); - - DAG.AssignOrdering(OddVal.getNode(), Order); - DAG.AssignOrdering(Val.getNode(), Order); } // The number of parts is a power of 2. Repeatedly bisect the value using @@ -460,8 +436,6 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, ValueVT.getSizeInBits()), Val); - DAG.AssignOrdering(Parts[0].getNode(), Order); - for (unsigned StepSize = NumParts; StepSize > 1; StepSize /= 2) { for (unsigned i = 0; i < NumParts; i += StepSize) { unsigned ThisBits = StepSize * PartBits / 2; @@ -476,16 +450,11 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, ThisVT, Part0, DAG.getConstant(0, PtrVT)); - DAG.AssignOrdering(Part0.getNode(), Order); - DAG.AssignOrdering(Part1.getNode(), Order); - if (ThisBits == PartBits && ThisVT != PartVT) { Part0 = DAG.getNode(ISD::BIT_CONVERT, dl, PartVT, Part0); Part1 = DAG.getNode(ISD::BIT_CONVERT, dl, PartVT, Part1); - DAG.AssignOrdering(Part0.getNode(), Order); - DAG.AssignOrdering(Part1.getNode(), Order); } } } @@ -511,7 +480,6 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, } } - DAG.AssignOrdering(Val.getNode(), Order); Parts[0] = Val; return; } @@ -539,8 +507,6 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, Ops[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, IntermediateVT, Val, DAG.getConstant(i, PtrVT)); - - DAG.AssignOrdering(Ops[i].getNode(), Order); } // Split the intermediate operands into legal parts. @@ -638,23 +604,34 @@ SDValue SelectionDAGBuilder::getControlRoot() { return Root; } +void SelectionDAGBuilder::AssignOrderingToNode(const SDNode *Node) { + if (DAG.GetOrdering(Node) != 0) return; // Already has ordering. + DAG.AssignOrdering(Node, SDNodeOrder); + + for (unsigned I = 0, E = Node->getNumOperands(); I != E; ++I) + AssignOrderingToNode(Node->getOperand(I).getNode()); +} + void SelectionDAGBuilder::visit(Instruction &I) { visit(I.getOpcode(), I); } void SelectionDAGBuilder::visit(unsigned Opcode, User &I) { - // We're processing a new instruction. - ++SDNodeOrder; - // Note: this doesn't use InstVisitor, because it has to work with // ConstantExpr's in addition to instructions. switch (Opcode) { default: llvm_unreachable("Unknown instruction type encountered!"); // Build the switch statement using the Instruction.def file. #define HANDLE_INST(NUM, OPCODE, CLASS) \ - case Instruction::OPCODE: return visit##OPCODE((CLASS&)I); + case Instruction::OPCODE: visit##OPCODE((CLASS&)I); break; #include "llvm/Instruction.def" } + + // Assign the ordering to the freshly created DAG nodes. + if (NodeMap.count(&I)) { + ++SDNodeOrder; + AssignOrderingToNode(getValue(&I).getNode()); + } } SDValue SelectionDAGBuilder::getValue(const Value *V) { @@ -699,10 +676,8 @@ SDValue SelectionDAGBuilder::getValue(const Value *V) { Constants.push_back(SDValue(Val, i)); } - SDValue Res = DAG.getMergeValues(&Constants[0], Constants.size(), - getCurDebugLoc()); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); - return Res; + return DAG.getMergeValues(&Constants[0], Constants.size(), + getCurDebugLoc()); } if (isa<StructType>(C->getType()) || isa<ArrayType>(C->getType())) { @@ -725,10 +700,8 @@ SDValue SelectionDAGBuilder::getValue(const Value *V) { Constants[i] = DAG.getConstant(0, EltVT); } - SDValue Res = DAG.getMergeValues(&Constants[0], NumElts, - getCurDebugLoc()); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); - return Res; + return DAG.getMergeValues(&Constants[0], NumElts, + getCurDebugLoc()); } if (BlockAddress *BA = dyn_cast<BlockAddress>(C)) @@ -756,10 +729,8 @@ SDValue SelectionDAGBuilder::getValue(const Value *V) { } // Create a BUILD_VECTOR node. - SDValue Res = DAG.getNode(ISD::BUILD_VECTOR, getCurDebugLoc(), - VT, &Ops[0], Ops.size()); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); - return NodeMap[V] = Res; + return NodeMap[V] = DAG.getNode(ISD::BUILD_VECTOR, getCurDebugLoc(), + VT, &Ops[0], Ops.size()); } // If this is a static alloca, generate it as the frameindex instead of @@ -873,16 +844,11 @@ void SelectionDAGBuilder::visitRet(ReturnInst &I) { Chains[i] = DAG.getStore(Chain, getCurDebugLoc(), SDValue(RetOp.getNode(), RetOp.getResNo() + i), - Add, NULL, Offsets[i], false, 0); - - DAG.AssignOrdering(Add.getNode(), SDNodeOrder); - DAG.AssignOrdering(Chains[i].getNode(), SDNodeOrder); + Add, NULL, Offsets[i], false, false, 0); } Chain = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), MVT::Other, &Chains[0], NumValues); - - DAG.AssignOrdering(Chain.getNode(), SDNodeOrder); } else { for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { SmallVector<EVT, 4> ValueVTs; @@ -948,7 +914,6 @@ void SelectionDAGBuilder::visitRet(ReturnInst &I) { // Update the DAG with the new chain value resulting from return lowering. DAG.setRoot(Chain); - DAG.AssignOrdering(Chain.getNode(), SDNodeOrder); } /// CopyToExportRegsIfNeeded - If the given value has virtual registers @@ -1209,13 +1174,10 @@ void SelectionDAGBuilder::visitBr(BranchInst &I) { CurMBB->addSuccessor(Succ0MBB); // If this is not a fall-through branch, emit the branch. - if (Succ0MBB != NextBlock) { - SDValue V = DAG.getNode(ISD::BR, getCurDebugLoc(), + if (Succ0MBB != NextBlock) + DAG.setRoot(DAG.getNode(ISD::BR, getCurDebugLoc(), MVT::Other, getControlRoot(), - DAG.getBasicBlock(Succ0MBB)); - DAG.setRoot(V); - DAG.AssignOrdering(V.getNode(), SDNodeOrder); - } + DAG.getBasicBlock(Succ0MBB))); return; } @@ -1321,8 +1283,6 @@ void SelectionDAGBuilder::visitSwitchCase(CaseBlock &CB) { } } - DAG.AssignOrdering(Cond.getNode(), SDNodeOrder); - // Update successor info CurMBB->addSuccessor(CB.TrueBB); CurMBB->addSuccessor(CB.FalseBB); @@ -1340,13 +1300,11 @@ void SelectionDAGBuilder::visitSwitchCase(CaseBlock &CB) { std::swap(CB.TrueBB, CB.FalseBB); SDValue True = DAG.getConstant(1, Cond.getValueType()); Cond = DAG.getNode(ISD::XOR, dl, Cond.getValueType(), Cond, True); - DAG.AssignOrdering(Cond.getNode(), SDNodeOrder); } SDValue BrCond = DAG.getNode(ISD::BRCOND, dl, MVT::Other, getControlRoot(), Cond, DAG.getBasicBlock(CB.TrueBB)); - DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder); // If the branch was constant folded, fix up the CFG. if (BrCond.getOpcode() == ISD::BR) { @@ -1356,12 +1314,9 @@ void SelectionDAGBuilder::visitSwitchCase(CaseBlock &CB) { if (BrCond == getControlRoot()) CurMBB->removeSuccessor(CB.TrueBB); - if (CB.FalseBB != NextBlock) { + if (CB.FalseBB != NextBlock) BrCond = DAG.getNode(ISD::BR, dl, MVT::Other, BrCond, DAG.getBasicBlock(CB.FalseBB)); - - DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder); - } } DAG.setRoot(BrCond); @@ -1379,10 +1334,6 @@ void SelectionDAGBuilder::visitJumpTable(JumpTable &JT) { MVT::Other, Index.getValue(1), Table, Index); DAG.setRoot(BrJumpTable); - - DAG.AssignOrdering(Index.getNode(), SDNodeOrder); - DAG.AssignOrdering(Table.getNode(), SDNodeOrder); - DAG.AssignOrdering(BrJumpTable.getNode(), SDNodeOrder); } /// visitJumpTableHeader - This function emits necessary code to produce index @@ -1398,7 +1349,7 @@ void SelectionDAGBuilder::visitJumpTableHeader(JumpTable &JT, DAG.getConstant(JTH.First, VT)); // The SDNode we just created, which holds the value being switched on minus - // the the smallest case value, needs to be copied to a virtual register so it + // the smallest case value, needs to be copied to a virtual register so it // can be used as an index into the jump table in a subsequent basic block. // This value may be smaller or larger than the target's pointer type, and // therefore require extension or truncating. @@ -1417,11 +1368,6 @@ void SelectionDAGBuilder::visitJumpTableHeader(JumpTable &JT, DAG.getConstant(JTH.Last-JTH.First,VT), ISD::SETUGT); - DAG.AssignOrdering(Sub.getNode(), SDNodeOrder); - DAG.AssignOrdering(SwitchOp.getNode(), SDNodeOrder); - DAG.AssignOrdering(CopyTo.getNode(), SDNodeOrder); - DAG.AssignOrdering(CMP.getNode(), SDNodeOrder); - // Set NextBlock to be the MBB immediately after the current one, if any. // This is used to avoid emitting unnecessary branches to the next block. MachineBasicBlock *NextBlock = 0; @@ -1434,13 +1380,9 @@ void SelectionDAGBuilder::visitJumpTableHeader(JumpTable &JT, MVT::Other, CopyTo, CMP, DAG.getBasicBlock(JT.Default)); - DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder); - - if (JT.MBB != NextBlock) { + if (JT.MBB != NextBlock) BrCond = DAG.getNode(ISD::BR, getCurDebugLoc(), MVT::Other, BrCond, DAG.getBasicBlock(JT.MBB)); - DAG.AssignOrdering(BrCond.getNode(), SDNodeOrder); - } DAG.setRoot(BrCond); } @@ -1467,11 +1409,6 @@ void SelectionDAGBuilder::visitBitTestHeader(BitTestBlock &B) { SDValue CopyTo = DAG.getCopyToReg(getControlRoot(), getCurDebugLoc(), B.Reg, ShiftOp); - DAG.AssignOrdering(Sub.getNode(), SDNodeOrder); - DAG.AssignOrdering(RangeCmp.getNode(), SDNodeOrder); - DAG.AssignOrdering(ShiftOp.getNode(), SDNodeOrder); - DAG.AssignOrdering(CopyTo.getNode(), SDNodeOrder); - // Set NextBlock to be the MBB immediately after the current one, if any. // This is used to avoid emitting unnecessary branches to the next block. MachineBasicBlock *NextBlock = 0; @@ -1488,13 +1425,9 @@ void SelectionDAGBuilder::visitBitTestHeader(BitTestBlock &B) { MVT::Other, CopyTo, RangeCmp, DAG.getBasicBlock(B.Default)); - DAG.AssignOrdering(BrRange.getNode(), SDNodeOrder); - - if (MBB != NextBlock) { + if (MBB != NextBlock) BrRange = DAG.getNode(ISD::BR, getCurDebugLoc(), MVT::Other, CopyTo, DAG.getBasicBlock(MBB)); - DAG.AssignOrdering(BrRange.getNode(), SDNodeOrder); - } DAG.setRoot(BrRange); } @@ -1520,11 +1453,6 @@ void SelectionDAGBuilder::visitBitTestCase(MachineBasicBlock* NextMBB, AndOp, DAG.getConstant(0, TLI.getPointerTy()), ISD::SETNE); - DAG.AssignOrdering(ShiftOp.getNode(), SDNodeOrder); - DAG.AssignOrdering(SwitchVal.getNode(), SDNodeOrder); - DAG.AssignOrdering(AndOp.getNode(), SDNodeOrder); - DAG.AssignOrdering(AndCmp.getNode(), SDNodeOrder); - CurMBB->addSuccessor(B.TargetBB); CurMBB->addSuccessor(NextMBB); @@ -1532,8 +1460,6 @@ void SelectionDAGBuilder::visitBitTestCase(MachineBasicBlock* NextMBB, MVT::Other, getControlRoot(), AndCmp, DAG.getBasicBlock(B.TargetBB)); - DAG.AssignOrdering(BrAnd.getNode(), SDNodeOrder); - // Set NextBlock to be the MBB immediately after the current one, if any. // This is used to avoid emitting unnecessary branches to the next block. MachineBasicBlock *NextBlock = 0; @@ -1541,11 +1467,9 @@ void SelectionDAGBuilder::visitBitTestCase(MachineBasicBlock* NextMBB, if (++BBI != FuncInfo.MF->end()) NextBlock = BBI; - if (NextMBB != NextBlock) { + if (NextMBB != NextBlock) BrAnd = DAG.getNode(ISD::BR, getCurDebugLoc(), MVT::Other, BrAnd, DAG.getBasicBlock(NextMBB)); - DAG.AssignOrdering(BrAnd.getNode(), SDNodeOrder); - } DAG.setRoot(BrAnd); } @@ -1570,11 +1494,9 @@ void SelectionDAGBuilder::visitInvoke(InvokeInst &I) { CurMBB->addSuccessor(LandingPad); // Drop into normal successor. - SDValue Branch = DAG.getNode(ISD::BR, getCurDebugLoc(), - MVT::Other, getControlRoot(), - DAG.getBasicBlock(Return)); - DAG.setRoot(Branch); - DAG.AssignOrdering(Branch.getNode(), SDNodeOrder); + DAG.setRoot(DAG.getNode(ISD::BR, getCurDebugLoc(), + MVT::Other, getControlRoot(), + DAG.getBasicBlock(Return))); } void SelectionDAGBuilder::visitUnwind(UnwindInst &I) { @@ -1733,8 +1655,8 @@ bool SelectionDAGBuilder::handleJTSwitchCase(CaseRec& CR, std::vector<MachineBasicBlock*> DestBBs; APInt TEI = First; for (CaseItr I = CR.Range.first, E = CR.Range.second; I != E; ++TEI) { - const APInt& Low = cast<ConstantInt>(I->Low)->getValue(); - const APInt& High = cast<ConstantInt>(I->High)->getValue(); + const APInt &Low = cast<ConstantInt>(I->Low)->getValue(); + const APInt &High = cast<ConstantInt>(I->High)->getValue(); if (Low.sle(TEI) && TEI.sle(High)) { DestBBs.push_back(I->BB); @@ -1757,7 +1679,9 @@ bool SelectionDAGBuilder::handleJTSwitchCase(CaseRec& CR, // Create a jump table index for this jump table, or return an existing // one. - unsigned JTI = CurMF->getJumpTableInfo()->getJumpTableIndex(DestBBs); + unsigned JTEncoding = TLI.getJumpTableEncoding(); + unsigned JTI = CurMF->getOrCreateJumpTableInfo(JTEncoding) + ->getJumpTableIndex(DestBBs); // Set the jump table information so that we can codegen it as a second // MachineBasicBlock @@ -2086,13 +2010,10 @@ void SelectionDAGBuilder::visitSwitch(SwitchInst &SI) { // If this is not a fall-through branch, emit the branch. CurMBB->addSuccessor(Default); - if (Default != NextBlock) { - SDValue Res = DAG.getNode(ISD::BR, getCurDebugLoc(), - MVT::Other, getControlRoot(), - DAG.getBasicBlock(Default)); - DAG.setRoot(Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); - } + if (Default != NextBlock) + DAG.setRoot(DAG.getNode(ISD::BR, getCurDebugLoc(), + MVT::Other, getControlRoot(), + DAG.getBasicBlock(Default))); return; } @@ -2141,15 +2062,19 @@ void SelectionDAGBuilder::visitSwitch(SwitchInst &SI) { } void SelectionDAGBuilder::visitIndirectBr(IndirectBrInst &I) { - // Update machine-CFG edges. + // Update machine-CFG edges with unique successors. + SmallVector<BasicBlock*, 32> succs; + succs.reserve(I.getNumSuccessors()); for (unsigned i = 0, e = I.getNumSuccessors(); i != e; ++i) - CurMBB->addSuccessor(FuncInfo.MBBMap[I.getSuccessor(i)]); - - SDValue Res = DAG.getNode(ISD::BRIND, getCurDebugLoc(), - MVT::Other, getControlRoot(), - getValue(I.getAddress())); - DAG.setRoot(Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + succs.push_back(I.getSuccessor(i)); + array_pod_sort(succs.begin(), succs.end()); + succs.erase(std::unique(succs.begin(), succs.end()), succs.end()); + for (unsigned i = 0, e = succs.size(); i != e; ++i) + CurMBB->addSuccessor(FuncInfo.MBBMap[succs[i]]); + + DAG.setRoot(DAG.getNode(ISD::BRIND, getCurDebugLoc(), + MVT::Other, getControlRoot(), + getValue(I.getAddress()))); } void SelectionDAGBuilder::visitFSub(User &I) { @@ -2164,10 +2089,8 @@ void SelectionDAGBuilder::visitFSub(User &I) { Constant *CNZ = ConstantVector::get(&NZ[0], NZ.size()); if (CV == CNZ) { SDValue Op2 = getValue(I.getOperand(1)); - SDValue Res = DAG.getNode(ISD::FNEG, getCurDebugLoc(), - Op2.getValueType(), Op2); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::FNEG, getCurDebugLoc(), + Op2.getValueType(), Op2)); return; } } @@ -2176,10 +2099,8 @@ void SelectionDAGBuilder::visitFSub(User &I) { if (ConstantFP *CFP = dyn_cast<ConstantFP>(I.getOperand(0))) if (CFP->isExactlyValue(ConstantFP::getNegativeZero(Ty)->getValueAPF())) { SDValue Op2 = getValue(I.getOperand(1)); - SDValue Res = DAG.getNode(ISD::FNEG, getCurDebugLoc(), - Op2.getValueType(), Op2); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::FNEG, getCurDebugLoc(), + Op2.getValueType(), Op2)); return; } @@ -2189,10 +2110,8 @@ void SelectionDAGBuilder::visitFSub(User &I) { void SelectionDAGBuilder::visitBinary(User &I, unsigned OpCode) { SDValue Op1 = getValue(I.getOperand(0)); SDValue Op2 = getValue(I.getOperand(1)); - SDValue Res = DAG.getNode(OpCode, getCurDebugLoc(), - Op1.getValueType(), Op1, Op2); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(OpCode, getCurDebugLoc(), + Op1.getValueType(), Op1, Op2)); } void SelectionDAGBuilder::visitShift(User &I, unsigned Opcode) { @@ -2225,12 +2144,8 @@ void SelectionDAGBuilder::visitShift(User &I, unsigned Opcode) { TLI.getPointerTy(), Op2); } - SDValue Res = DAG.getNode(Opcode, getCurDebugLoc(), - Op1.getValueType(), Op1, Op2); - setValue(&I, Res); - DAG.AssignOrdering(Op1.getNode(), SDNodeOrder); - DAG.AssignOrdering(Op2.getNode(), SDNodeOrder); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(Opcode, getCurDebugLoc(), + Op1.getValueType(), Op1, Op2)); } void SelectionDAGBuilder::visitICmp(User &I) { @@ -2244,9 +2159,7 @@ void SelectionDAGBuilder::visitICmp(User &I) { ISD::CondCode Opcode = getICmpCondCode(predicate); EVT DestVT = TLI.getValueType(I.getType()); - SDValue Res = DAG.getSetCC(getCurDebugLoc(), DestVT, Op1, Op2, Opcode); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getSetCC(getCurDebugLoc(), DestVT, Op1, Op2, Opcode)); } void SelectionDAGBuilder::visitFCmp(User &I) { @@ -2259,9 +2172,7 @@ void SelectionDAGBuilder::visitFCmp(User &I) { SDValue Op2 = getValue(I.getOperand(1)); ISD::CondCode Condition = getFCmpCondCode(predicate); EVT DestVT = TLI.getValueType(I.getType()); - SDValue Res = DAG.getSetCC(getCurDebugLoc(), DestVT, Op1, Op2, Condition); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getSetCC(getCurDebugLoc(), DestVT, Op1, Op2, Condition)); } void SelectionDAGBuilder::visitSelect(User &I) { @@ -2275,7 +2186,7 @@ void SelectionDAGBuilder::visitSelect(User &I) { SDValue TrueVal = getValue(I.getOperand(1)); SDValue FalseVal = getValue(I.getOperand(2)); - for (unsigned i = 0; i != NumValues; ++i) { + for (unsigned i = 0; i != NumValues; ++i) Values[i] = DAG.getNode(ISD::SELECT, getCurDebugLoc(), TrueVal.getNode()->getValueType(i), Cond, SDValue(TrueVal.getNode(), @@ -2283,23 +2194,16 @@ void SelectionDAGBuilder::visitSelect(User &I) { SDValue(FalseVal.getNode(), FalseVal.getResNo() + i)); - DAG.AssignOrdering(Values[i].getNode(), SDNodeOrder); - } - - SDValue Res = DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), - DAG.getVTList(&ValueVTs[0], NumValues), - &Values[0], NumValues); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), + DAG.getVTList(&ValueVTs[0], NumValues), + &Values[0], NumValues)); } void SelectionDAGBuilder::visitTrunc(User &I) { // TruncInst cannot be a no-op cast because sizeof(src) > sizeof(dest). SDValue N = getValue(I.getOperand(0)); EVT DestVT = TLI.getValueType(I.getType()); - SDValue Res = DAG.getNode(ISD::TRUNCATE, getCurDebugLoc(), DestVT, N); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::TRUNCATE, getCurDebugLoc(), DestVT, N)); } void SelectionDAGBuilder::visitZExt(User &I) { @@ -2307,9 +2211,7 @@ void SelectionDAGBuilder::visitZExt(User &I) { // ZExt also can't be a cast to bool for same reason. So, nothing much to do SDValue N = getValue(I.getOperand(0)); EVT DestVT = TLI.getValueType(I.getType()); - SDValue Res = DAG.getNode(ISD::ZERO_EXTEND, getCurDebugLoc(), DestVT, N); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::ZERO_EXTEND, getCurDebugLoc(), DestVT, N)); } void SelectionDAGBuilder::visitSExt(User &I) { @@ -2317,64 +2219,50 @@ void SelectionDAGBuilder::visitSExt(User &I) { // SExt also can't be a cast to bool for same reason. So, nothing much to do SDValue N = getValue(I.getOperand(0)); EVT DestVT = TLI.getValueType(I.getType()); - SDValue Res = DAG.getNode(ISD::SIGN_EXTEND, getCurDebugLoc(), DestVT, N); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::SIGN_EXTEND, getCurDebugLoc(), DestVT, N)); } void SelectionDAGBuilder::visitFPTrunc(User &I) { // FPTrunc is never a no-op cast, no need to check SDValue N = getValue(I.getOperand(0)); EVT DestVT = TLI.getValueType(I.getType()); - SDValue Res = DAG.getNode(ISD::FP_ROUND, getCurDebugLoc(), - DestVT, N, DAG.getIntPtrConstant(0)); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::FP_ROUND, getCurDebugLoc(), + DestVT, N, DAG.getIntPtrConstant(0))); } void SelectionDAGBuilder::visitFPExt(User &I){ // FPTrunc is never a no-op cast, no need to check SDValue N = getValue(I.getOperand(0)); EVT DestVT = TLI.getValueType(I.getType()); - SDValue Res = DAG.getNode(ISD::FP_EXTEND, getCurDebugLoc(), DestVT, N); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::FP_EXTEND, getCurDebugLoc(), DestVT, N)); } void SelectionDAGBuilder::visitFPToUI(User &I) { // FPToUI is never a no-op cast, no need to check SDValue N = getValue(I.getOperand(0)); EVT DestVT = TLI.getValueType(I.getType()); - SDValue Res = DAG.getNode(ISD::FP_TO_UINT, getCurDebugLoc(), DestVT, N); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::FP_TO_UINT, getCurDebugLoc(), DestVT, N)); } void SelectionDAGBuilder::visitFPToSI(User &I) { // FPToSI is never a no-op cast, no need to check SDValue N = getValue(I.getOperand(0)); EVT DestVT = TLI.getValueType(I.getType()); - SDValue Res = DAG.getNode(ISD::FP_TO_SINT, getCurDebugLoc(), DestVT, N); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::FP_TO_SINT, getCurDebugLoc(), DestVT, N)); } void SelectionDAGBuilder::visitUIToFP(User &I) { // UIToFP is never a no-op cast, no need to check SDValue N = getValue(I.getOperand(0)); EVT DestVT = TLI.getValueType(I.getType()); - SDValue Res = DAG.getNode(ISD::UINT_TO_FP, getCurDebugLoc(), DestVT, N); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::UINT_TO_FP, getCurDebugLoc(), DestVT, N)); } void SelectionDAGBuilder::visitSIToFP(User &I){ // SIToFP is never a no-op cast, no need to check SDValue N = getValue(I.getOperand(0)); EVT DestVT = TLI.getValueType(I.getType()); - SDValue Res = DAG.getNode(ISD::SINT_TO_FP, getCurDebugLoc(), DestVT, N); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::SINT_TO_FP, getCurDebugLoc(), DestVT, N)); } void SelectionDAGBuilder::visitPtrToInt(User &I) { @@ -2383,9 +2271,7 @@ void SelectionDAGBuilder::visitPtrToInt(User &I) { SDValue N = getValue(I.getOperand(0)); EVT SrcVT = N.getValueType(); EVT DestVT = TLI.getValueType(I.getType()); - SDValue Res = DAG.getZExtOrTrunc(N, getCurDebugLoc(), DestVT); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getZExtOrTrunc(N, getCurDebugLoc(), DestVT)); } void SelectionDAGBuilder::visitIntToPtr(User &I) { @@ -2394,9 +2280,7 @@ void SelectionDAGBuilder::visitIntToPtr(User &I) { SDValue N = getValue(I.getOperand(0)); EVT SrcVT = N.getValueType(); EVT DestVT = TLI.getValueType(I.getType()); - SDValue Res = DAG.getZExtOrTrunc(N, getCurDebugLoc(), DestVT); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getZExtOrTrunc(N, getCurDebugLoc(), DestVT)); } void SelectionDAGBuilder::visitBitCast(User &I) { @@ -2405,14 +2289,11 @@ void SelectionDAGBuilder::visitBitCast(User &I) { // BitCast assures us that source and destination are the same size so this is // either a BIT_CONVERT or a no-op. - if (DestVT != N.getValueType()) { - SDValue Res = DAG.getNode(ISD::BIT_CONVERT, getCurDebugLoc(), - DestVT, N); // convert types. - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); - } else { + if (DestVT != N.getValueType()) + setValue(&I, DAG.getNode(ISD::BIT_CONVERT, getCurDebugLoc(), + DestVT, N)); // convert types. + else setValue(&I, N); // noop cast. - } } void SelectionDAGBuilder::visitInsertElement(User &I) { @@ -2421,13 +2302,9 @@ void SelectionDAGBuilder::visitInsertElement(User &I) { SDValue InIdx = DAG.getNode(ISD::ZERO_EXTEND, getCurDebugLoc(), TLI.getPointerTy(), getValue(I.getOperand(2))); - SDValue Res = DAG.getNode(ISD::INSERT_VECTOR_ELT, getCurDebugLoc(), - TLI.getValueType(I.getType()), - InVec, InVal, InIdx); - setValue(&I, Res); - - DAG.AssignOrdering(InIdx.getNode(), SDNodeOrder); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::INSERT_VECTOR_ELT, getCurDebugLoc(), + TLI.getValueType(I.getType()), + InVec, InVal, InIdx)); } void SelectionDAGBuilder::visitExtractElement(User &I) { @@ -2435,15 +2312,10 @@ void SelectionDAGBuilder::visitExtractElement(User &I) { SDValue InIdx = DAG.getNode(ISD::ZERO_EXTEND, getCurDebugLoc(), TLI.getPointerTy(), getValue(I.getOperand(1))); - SDValue Res = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, getCurDebugLoc(), - TLI.getValueType(I.getType()), InVec, InIdx); - setValue(&I, Res); - - DAG.AssignOrdering(InIdx.getNode(), SDNodeOrder); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::EXTRACT_VECTOR_ELT, getCurDebugLoc(), + TLI.getValueType(I.getType()), InVec, InIdx)); } - // Utility for visitShuffleVector - Returns true if the mask is mask starting // from SIndx and increasing to the element length (undefs are allowed). static bool SequentialMask(SmallVectorImpl<int> &Mask, unsigned SIndx) { @@ -2462,8 +2334,7 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) { // Convert the ConstantVector mask operand into an array of ints, with -1 // representing undef values. SmallVector<Constant*, 8> MaskElts; - cast<Constant>(I.getOperand(2))->getVectorElements(*DAG.getContext(), - MaskElts); + cast<Constant>(I.getOperand(2))->getVectorElements(MaskElts); unsigned MaskNumElts = MaskElts.size(); for (unsigned i = 0; i != MaskNumElts; ++i) { if (isa<UndefValue>(MaskElts[i])) @@ -2477,10 +2348,8 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) { unsigned SrcNumElts = SrcVT.getVectorNumElements(); if (SrcNumElts == MaskNumElts) { - SDValue Res = DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, - &Mask[0]); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, + &Mask[0])); return; } @@ -2491,10 +2360,8 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) { // lengths match. if (SrcNumElts*2 == MaskNumElts && SequentialMask(Mask, 0)) { // The shuffle is concatenating two vectors together. - SDValue Res = DAG.getNode(ISD::CONCAT_VECTORS, getCurDebugLoc(), - VT, Src1, Src2); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::CONCAT_VECTORS, getCurDebugLoc(), + VT, Src1, Src2)); return; } @@ -2526,12 +2393,8 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) { MappedOps.push_back(Idx + MaskNumElts - SrcNumElts); } - SDValue Res = DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, - &MappedOps[0]); - setValue(&I, Res); - DAG.AssignOrdering(Src1.getNode(), SDNodeOrder); - DAG.AssignOrdering(Src2.getNode(), SDNodeOrder); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, + &MappedOps[0])); return; } @@ -2583,9 +2446,7 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) { } if (RangeUse[0] == 0 && RangeUse[1] == 0) { - SDValue Res = DAG.getUNDEF(VT); - setValue(&I, Res); // Vectors are not used. - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getUNDEF(VT)); // Vectors are not used. return; } else if (RangeUse[0] < 2 && RangeUse[1] < 2) { @@ -2597,8 +2458,6 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) { else Src = DAG.getNode(ISD::EXTRACT_SUBVECTOR, getCurDebugLoc(), VT, Src, DAG.getIntPtrConstant(StartIdx[Input])); - - DAG.AssignOrdering(Src.getNode(), SDNodeOrder); } // Calculate new mask. @@ -2613,10 +2472,8 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) { MappedOps.push_back(Idx - SrcNumElts - StartIdx[1] + MaskNumElts); } - SDValue Res = DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, - &MappedOps[0]); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, + &MappedOps[0])); return; } } @@ -2643,14 +2500,11 @@ void SelectionDAGBuilder::visitShuffleVector(User &I) { DAG.getConstant(Idx - SrcNumElts, PtrVT)); Ops.push_back(Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } } - SDValue Res = DAG.getNode(ISD::BUILD_VECTOR, getCurDebugLoc(), - VT, &Ops[0], Ops.size()); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::BUILD_VECTOR, getCurDebugLoc(), + VT, &Ops[0], Ops.size())); } void SelectionDAGBuilder::visitInsertValue(InsertValueInst &I) { @@ -2689,11 +2543,9 @@ void SelectionDAGBuilder::visitInsertValue(InsertValueInst &I) { Values[i] = IntoUndef ? DAG.getUNDEF(AggValueVTs[i]) : SDValue(Agg.getNode(), Agg.getResNo() + i); - SDValue Res = DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), - DAG.getVTList(&AggValueVTs[0], NumAggValues), - &Values[0], NumAggValues); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), + DAG.getVTList(&AggValueVTs[0], NumAggValues), + &Values[0], NumAggValues)); } void SelectionDAGBuilder::visitExtractValue(ExtractValueInst &I) { @@ -2719,11 +2571,9 @@ void SelectionDAGBuilder::visitExtractValue(ExtractValueInst &I) { DAG.getUNDEF(Agg.getNode()->getValueType(Agg.getResNo() + i)) : SDValue(Agg.getNode(), Agg.getResNo() + i); - SDValue Res = DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), - DAG.getVTList(&ValValueVTs[0], NumValValues), - &Values[0], NumValValues); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), + DAG.getVTList(&ValValueVTs[0], NumValValues), + &Values[0], NumValValues)); } void SelectionDAGBuilder::visitGetElementPtr(User &I) { @@ -2740,7 +2590,6 @@ void SelectionDAGBuilder::visitGetElementPtr(User &I) { uint64_t Offset = TD->getStructLayout(StTy)->getElementOffset(Field); N = DAG.getNode(ISD::ADD, getCurDebugLoc(), N.getValueType(), N, DAG.getIntPtrConstant(Offset)); - DAG.AssignOrdering(N.getNode(), SDNodeOrder); } Ty = StTy->getElementType(Field); @@ -2764,9 +2613,6 @@ void SelectionDAGBuilder::visitGetElementPtr(User &I) { N = DAG.getNode(ISD::ADD, getCurDebugLoc(), N.getValueType(), N, OffsVal); - - DAG.AssignOrdering(OffsVal.getNode(), SDNodeOrder); - DAG.AssignOrdering(N.getNode(), SDNodeOrder); continue; } @@ -2792,13 +2638,10 @@ void SelectionDAGBuilder::visitGetElementPtr(User &I) { IdxN = DAG.getNode(ISD::MUL, getCurDebugLoc(), N.getValueType(), IdxN, Scale); } - - DAG.AssignOrdering(IdxN.getNode(), SDNodeOrder); } N = DAG.getNode(ISD::ADD, getCurDebugLoc(), N.getValueType(), N, IdxN); - DAG.AssignOrdering(N.getNode(), SDNodeOrder); } } @@ -2823,11 +2666,8 @@ void SelectionDAGBuilder::visitAlloca(AllocaInst &I) { AllocSize, DAG.getConstant(TySize, AllocSize.getValueType())); - DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder); - EVT IntPtr = TLI.getPointerTy(); AllocSize = DAG.getZExtOrTrunc(AllocSize, getCurDebugLoc(), IntPtr); - DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder); // Handle alignment. If the requested alignment is less than or equal to // the stack alignment, ignore it. If the size is greater than or equal to @@ -2842,13 +2682,11 @@ void SelectionDAGBuilder::visitAlloca(AllocaInst &I) { AllocSize = DAG.getNode(ISD::ADD, getCurDebugLoc(), AllocSize.getValueType(), AllocSize, DAG.getIntPtrConstant(StackAlign-1)); - DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder); // Mask out the low bits for alignment purposes. AllocSize = DAG.getNode(ISD::AND, getCurDebugLoc(), AllocSize.getValueType(), AllocSize, DAG.getIntPtrConstant(~(uint64_t)(StackAlign-1))); - DAG.AssignOrdering(AllocSize.getNode(), SDNodeOrder); SDValue Ops[] = { getRoot(), AllocSize, DAG.getIntPtrConstant(Align) }; SDVTList VTs = DAG.getVTList(AllocSize.getValueType(), MVT::Other); @@ -2856,7 +2694,6 @@ void SelectionDAGBuilder::visitAlloca(AllocaInst &I) { VTs, Ops, 3); setValue(&I, DSA); DAG.setRoot(DSA.getValue(1)); - DAG.AssignOrdering(DSA.getNode(), SDNodeOrder); // Inform the Frame Information that we have just allocated a variable-sized // object. @@ -2868,7 +2705,9 @@ void SelectionDAGBuilder::visitLoad(LoadInst &I) { SDValue Ptr = getValue(SV); const Type *Ty = I.getType(); + bool isVolatile = I.isVolatile(); + bool isNonTemporal = I.getMetadata("nontemporal") != 0; unsigned Alignment = I.getAlignment(); SmallVector<EVT, 4> ValueVTs; @@ -2900,13 +2739,11 @@ void SelectionDAGBuilder::visitLoad(LoadInst &I) { PtrVT, Ptr, DAG.getConstant(Offsets[i], PtrVT)); SDValue L = DAG.getLoad(ValueVTs[i], getCurDebugLoc(), Root, - A, SV, Offsets[i], isVolatile, Alignment); + A, SV, Offsets[i], isVolatile, + isNonTemporal, Alignment); Values[i] = L; Chains[i] = L.getValue(1); - - DAG.AssignOrdering(A.getNode(), SDNodeOrder); - DAG.AssignOrdering(L.getNode(), SDNodeOrder); } if (!ConstantMemory) { @@ -2916,15 +2753,11 @@ void SelectionDAGBuilder::visitLoad(LoadInst &I) { DAG.setRoot(Chain); else PendingLoads.push_back(Chain); - - DAG.AssignOrdering(Chain.getNode(), SDNodeOrder); } - SDValue Res = DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), - DAG.getVTList(&ValueVTs[0], NumValues), - &Values[0], NumValues); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), + DAG.getVTList(&ValueVTs[0], NumValues), + &Values[0], NumValues)); } void SelectionDAGBuilder::visitStore(StoreInst &I) { @@ -2948,6 +2781,7 @@ void SelectionDAGBuilder::visitStore(StoreInst &I) { SmallVector<SDValue, 4> Chains(NumValues); EVT PtrVT = Ptr.getValueType(); bool isVolatile = I.isVolatile(); + bool isNonTemporal = I.getMetadata("nontemporal") != 0; unsigned Alignment = I.getAlignment(); for (unsigned i = 0; i != NumValues; ++i) { @@ -2955,16 +2789,12 @@ void SelectionDAGBuilder::visitStore(StoreInst &I) { DAG.getConstant(Offsets[i], PtrVT)); Chains[i] = DAG.getStore(Root, getCurDebugLoc(), SDValue(Src.getNode(), Src.getResNo() + i), - Add, PtrV, Offsets[i], isVolatile, Alignment); - - DAG.AssignOrdering(Add.getNode(), SDNodeOrder); - DAG.AssignOrdering(Chains[i].getNode(), SDNodeOrder); + Add, PtrV, Offsets[i], isVolatile, + isNonTemporal, Alignment); } - SDValue Res = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), - MVT::Other, &Chains[0], NumValues); - DAG.setRoot(Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.setRoot(DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), + MVT::Other, &Chains[0], NumValues)); } /// visitTargetIntrinsic - Lower a call of a target intrinsic to an INTRINSIC @@ -3035,8 +2865,6 @@ void SelectionDAGBuilder::visitTargetIntrinsic(CallInst &I, VTs, &Ops[0], Ops.size()); } - DAG.AssignOrdering(Result.getNode(), SDNodeOrder); - if (HasChain) { SDValue Chain = Result.getValue(Result.getNode()->getNumValues()-1); if (OnlyLoad) @@ -3049,7 +2877,6 @@ void SelectionDAGBuilder::visitTargetIntrinsic(CallInst &I, if (const VectorType *PTy = dyn_cast<VectorType>(I.getType())) { EVT VT = TLI.getValueType(PTy); Result = DAG.getNode(ISD::BIT_CONVERT, getCurDebugLoc(), VT, Result); - DAG.AssignOrdering(Result.getNode(), SDNodeOrder); } setValue(&I, Result); @@ -3068,12 +2895,7 @@ GetSignificand(SelectionDAG &DAG, SDValue Op, DebugLoc dl, unsigned Order) { DAG.getConstant(0x007fffff, MVT::i32)); SDValue t2 = DAG.getNode(ISD::OR, dl, MVT::i32, t1, DAG.getConstant(0x3f800000, MVT::i32)); - SDValue Res = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, t2); - - DAG.AssignOrdering(t1.getNode(), Order); - DAG.AssignOrdering(t2.getNode(), Order); - DAG.AssignOrdering(Res.getNode(), Order); - return Res; + return DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, t2); } /// GetExponent - Get the exponent: @@ -3090,13 +2912,7 @@ GetExponent(SelectionDAG &DAG, SDValue Op, const TargetLowering &TLI, DAG.getConstant(23, TLI.getPointerTy())); SDValue t2 = DAG.getNode(ISD::SUB, dl, MVT::i32, t1, DAG.getConstant(127, MVT::i32)); - SDValue Res = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, t2); - - DAG.AssignOrdering(t0.getNode(), Order); - DAG.AssignOrdering(t1.getNode(), Order); - DAG.AssignOrdering(t2.getNode(), Order); - DAG.AssignOrdering(Res.getNode(), Order); - return Res; + return DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, t2); } /// getF32Constant - Get 32-bit floating point constant. @@ -3120,7 +2936,6 @@ SelectionDAGBuilder::implVisitBinaryAtomic(CallInst& I, ISD::NodeType Op) { I.getOperand(1)); setValue(&I, L); DAG.setRoot(L.getValue(1)); - DAG.AssignOrdering(L.getNode(), SDNodeOrder); return 0; } @@ -3131,10 +2946,7 @@ SelectionDAGBuilder::implVisitAluOverflow(CallInst &I, ISD::NodeType Op) { SDValue Op2 = getValue(I.getOperand(2)); SDVTList VTs = DAG.getVTList(Op1.getValueType(), MVT::i1); - SDValue Result = DAG.getNode(Op, getCurDebugLoc(), VTs, Op1, Op2); - - setValue(&I, Result); - DAG.AssignOrdering(Result.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(Op, getCurDebugLoc(), VTs, Op1, Op2)); return 0; } @@ -3162,15 +2974,9 @@ SelectionDAGBuilder::visitExp(CallInst &I) { SDValue t1 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, IntegerPartOfX); SDValue X = DAG.getNode(ISD::FSUB, dl, MVT::f32, t0, t1); - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(X.getNode(), SDNodeOrder); - // IntegerPartOfX <<= 23; IntegerPartOfX = DAG.getNode(ISD::SHL, dl, MVT::i32, IntegerPartOfX, DAG.getConstant(23, TLI.getPointerTy())); - DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder); if (LimitFloatPrecision <= 6) { // For floating-point precision of 6: @@ -3194,14 +3000,6 @@ SelectionDAGBuilder::visitExp(CallInst &I) { TwoToFracPartOfX, IntegerPartOfX); result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, t6); - - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(TwoToFracPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { // For floating-point precision of 12: // @@ -3228,16 +3026,6 @@ SelectionDAGBuilder::visitExp(CallInst &I) { TwoToFracPartOfX, IntegerPartOfX); result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, t8); - - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(t7.getNode(), SDNodeOrder); - DAG.AssignOrdering(t8.getNode(), SDNodeOrder); - DAG.AssignOrdering(TwoToFracPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 // For floating-point precision of 18: // @@ -3277,29 +3065,12 @@ SelectionDAGBuilder::visitExp(CallInst &I) { TwoToFracPartOfX, IntegerPartOfX); result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, t14); - - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(t7.getNode(), SDNodeOrder); - DAG.AssignOrdering(t8.getNode(), SDNodeOrder); - DAG.AssignOrdering(t9.getNode(), SDNodeOrder); - DAG.AssignOrdering(t10.getNode(), SDNodeOrder); - DAG.AssignOrdering(t11.getNode(), SDNodeOrder); - DAG.AssignOrdering(t12.getNode(), SDNodeOrder); - DAG.AssignOrdering(t13.getNode(), SDNodeOrder); - DAG.AssignOrdering(t14.getNode(), SDNodeOrder); - DAG.AssignOrdering(TwoToFracPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } } else { // No special expansion. result = DAG.getNode(ISD::FEXP, dl, getValue(I.getOperand(1)).getValueType(), getValue(I.getOperand(1))); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } setValue(&I, result); @@ -3317,15 +3088,11 @@ SelectionDAGBuilder::visitLog(CallInst &I) { SDValue Op = getValue(I.getOperand(1)); SDValue Op1 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Op); - DAG.AssignOrdering(Op1.getNode(), SDNodeOrder); - // Scale the exponent by log(2) [0.69314718f]. SDValue Exp = GetExponent(DAG, Op1, TLI, dl, SDNodeOrder); SDValue LogOfExponent = DAG.getNode(ISD::FMUL, dl, MVT::f32, Exp, getF32Constant(DAG, 0x3f317218)); - DAG.AssignOrdering(LogOfExponent.getNode(), SDNodeOrder); - // Get the significand and build it into a floating-point number with // exponent of 1. SDValue X = GetSignificand(DAG, Op1, dl, SDNodeOrder); @@ -3348,12 +3115,6 @@ SelectionDAGBuilder::visitLog(CallInst &I) { result = DAG.getNode(ISD::FADD, dl, MVT::f32, LogOfExponent, LogOfMantissa); - - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(LogOfMantissa.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { // For floating-point precision of 12: // @@ -3380,16 +3141,6 @@ SelectionDAGBuilder::visitLog(CallInst &I) { result = DAG.getNode(ISD::FADD, dl, MVT::f32, LogOfExponent, LogOfMantissa); - - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(LogOfMantissa.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 // For floating-point precision of 18: // @@ -3424,27 +3175,12 @@ SelectionDAGBuilder::visitLog(CallInst &I) { result = DAG.getNode(ISD::FADD, dl, MVT::f32, LogOfExponent, LogOfMantissa); - - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(t7.getNode(), SDNodeOrder); - DAG.AssignOrdering(t8.getNode(), SDNodeOrder); - DAG.AssignOrdering(t9.getNode(), SDNodeOrder); - DAG.AssignOrdering(t10.getNode(), SDNodeOrder); - DAG.AssignOrdering(LogOfMantissa.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } } else { // No special expansion. result = DAG.getNode(ISD::FLOG, dl, getValue(I.getOperand(1)).getValueType(), getValue(I.getOperand(1))); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } setValue(&I, result); @@ -3462,13 +3198,9 @@ SelectionDAGBuilder::visitLog2(CallInst &I) { SDValue Op = getValue(I.getOperand(1)); SDValue Op1 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Op); - DAG.AssignOrdering(Op1.getNode(), SDNodeOrder); - // Get the exponent. SDValue LogOfExponent = GetExponent(DAG, Op1, TLI, dl, SDNodeOrder); - DAG.AssignOrdering(LogOfExponent.getNode(), SDNodeOrder); - // Get the significand and build it into a floating-point number with // exponent of 1. SDValue X = GetSignificand(DAG, Op1, dl, SDNodeOrder); @@ -3491,12 +3223,6 @@ SelectionDAGBuilder::visitLog2(CallInst &I) { result = DAG.getNode(ISD::FADD, dl, MVT::f32, LogOfExponent, Log2ofMantissa); - - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(Log2ofMantissa.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { // For floating-point precision of 12: // @@ -3523,16 +3249,6 @@ SelectionDAGBuilder::visitLog2(CallInst &I) { result = DAG.getNode(ISD::FADD, dl, MVT::f32, LogOfExponent, Log2ofMantissa); - - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(Log2ofMantissa.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 // For floating-point precision of 18: // @@ -3568,27 +3284,12 @@ SelectionDAGBuilder::visitLog2(CallInst &I) { result = DAG.getNode(ISD::FADD, dl, MVT::f32, LogOfExponent, Log2ofMantissa); - - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(t7.getNode(), SDNodeOrder); - DAG.AssignOrdering(t8.getNode(), SDNodeOrder); - DAG.AssignOrdering(t9.getNode(), SDNodeOrder); - DAG.AssignOrdering(t10.getNode(), SDNodeOrder); - DAG.AssignOrdering(Log2ofMantissa.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } } else { // No special expansion. result = DAG.getNode(ISD::FLOG2, dl, getValue(I.getOperand(1)).getValueType(), getValue(I.getOperand(1))); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } setValue(&I, result); @@ -3606,15 +3307,11 @@ SelectionDAGBuilder::visitLog10(CallInst &I) { SDValue Op = getValue(I.getOperand(1)); SDValue Op1 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Op); - DAG.AssignOrdering(Op1.getNode(), SDNodeOrder); - // Scale the exponent by log10(2) [0.30102999f]. SDValue Exp = GetExponent(DAG, Op1, TLI, dl, SDNodeOrder); SDValue LogOfExponent = DAG.getNode(ISD::FMUL, dl, MVT::f32, Exp, getF32Constant(DAG, 0x3e9a209a)); - DAG.AssignOrdering(LogOfExponent.getNode(), SDNodeOrder); - // Get the significand and build it into a floating-point number with // exponent of 1. SDValue X = GetSignificand(DAG, Op1, dl, SDNodeOrder); @@ -3637,12 +3334,6 @@ SelectionDAGBuilder::visitLog10(CallInst &I) { result = DAG.getNode(ISD::FADD, dl, MVT::f32, LogOfExponent, Log10ofMantissa); - - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(Log10ofMantissa.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { // For floating-point precision of 12: // @@ -3665,14 +3356,6 @@ SelectionDAGBuilder::visitLog10(CallInst &I) { result = DAG.getNode(ISD::FADD, dl, MVT::f32, LogOfExponent, Log10ofMantissa); - - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(Log10ofMantissa.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 // For floating-point precision of 18: // @@ -3703,25 +3386,12 @@ SelectionDAGBuilder::visitLog10(CallInst &I) { result = DAG.getNode(ISD::FADD, dl, MVT::f32, LogOfExponent, Log10ofMantissa); - - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(t7.getNode(), SDNodeOrder); - DAG.AssignOrdering(t8.getNode(), SDNodeOrder); - DAG.AssignOrdering(Log10ofMantissa.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } } else { // No special expansion. result = DAG.getNode(ISD::FLOG10, dl, getValue(I.getOperand(1)).getValueType(), getValue(I.getOperand(1))); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } setValue(&I, result); @@ -3740,8 +3410,6 @@ SelectionDAGBuilder::visitExp2(CallInst &I) { SDValue IntegerPartOfX = DAG.getNode(ISD::FP_TO_SINT, dl, MVT::i32, Op); - DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder); - // FractionalPartOfX = x - (float)IntegerPartOfX; SDValue t1 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, IntegerPartOfX); SDValue X = DAG.getNode(ISD::FSUB, dl, MVT::f32, Op, t1); @@ -3750,10 +3418,6 @@ SelectionDAGBuilder::visitExp2(CallInst &I) { IntegerPartOfX = DAG.getNode(ISD::SHL, dl, MVT::i32, IntegerPartOfX, DAG.getConstant(23, TLI.getPointerTy())); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(X.getNode(), SDNodeOrder); - DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder); - if (LimitFloatPrecision <= 6) { // For floating-point precision of 6: // @@ -3775,14 +3439,6 @@ SelectionDAGBuilder::visitExp2(CallInst &I) { result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, TwoToFractionalPartOfX); - - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { // For floating-point precision of 12: // @@ -3808,16 +3464,6 @@ SelectionDAGBuilder::visitExp2(CallInst &I) { result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, TwoToFractionalPartOfX); - - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(t7.getNode(), SDNodeOrder); - DAG.AssignOrdering(t8.getNode(), SDNodeOrder); - DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 // For floating-point precision of 18: // @@ -3854,29 +3500,12 @@ SelectionDAGBuilder::visitExp2(CallInst &I) { result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, TwoToFractionalPartOfX); - - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(t7.getNode(), SDNodeOrder); - DAG.AssignOrdering(t8.getNode(), SDNodeOrder); - DAG.AssignOrdering(t9.getNode(), SDNodeOrder); - DAG.AssignOrdering(t10.getNode(), SDNodeOrder); - DAG.AssignOrdering(t11.getNode(), SDNodeOrder); - DAG.AssignOrdering(t12.getNode(), SDNodeOrder); - DAG.AssignOrdering(t13.getNode(), SDNodeOrder); - DAG.AssignOrdering(t14.getNode(), SDNodeOrder); - DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } } else { // No special expansion. result = DAG.getNode(ISD::FEXP2, dl, getValue(I.getOperand(1)).getValueType(), getValue(I.getOperand(1))); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } setValue(&I, result); @@ -3918,17 +3547,10 @@ SelectionDAGBuilder::visitPow(CallInst &I) { SDValue t1 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, IntegerPartOfX); SDValue X = DAG.getNode(ISD::FSUB, dl, MVT::f32, t0, t1); - DAG.AssignOrdering(t0.getNode(), SDNodeOrder); - DAG.AssignOrdering(t1.getNode(), SDNodeOrder); - DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(X.getNode(), SDNodeOrder); - // IntegerPartOfX <<= 23; IntegerPartOfX = DAG.getNode(ISD::SHL, dl, MVT::i32, IntegerPartOfX, DAG.getConstant(23, TLI.getPointerTy())); - DAG.AssignOrdering(IntegerPartOfX.getNode(), SDNodeOrder); - if (LimitFloatPrecision <= 6) { // For floating-point precision of 6: // @@ -3950,14 +3572,6 @@ SelectionDAGBuilder::visitPow(CallInst &I) { result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, TwoToFractionalPartOfX); - - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { // For floating-point precision of 12: // @@ -3983,16 +3597,6 @@ SelectionDAGBuilder::visitPow(CallInst &I) { result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, TwoToFractionalPartOfX); - - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(t7.getNode(), SDNodeOrder); - DAG.AssignOrdering(t8.getNode(), SDNodeOrder); - DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 // For floating-point precision of 18: // @@ -4029,22 +3633,6 @@ SelectionDAGBuilder::visitPow(CallInst &I) { result = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, TwoToFractionalPartOfX); - - DAG.AssignOrdering(t2.getNode(), SDNodeOrder); - DAG.AssignOrdering(t3.getNode(), SDNodeOrder); - DAG.AssignOrdering(t4.getNode(), SDNodeOrder); - DAG.AssignOrdering(t5.getNode(), SDNodeOrder); - DAG.AssignOrdering(t6.getNode(), SDNodeOrder); - DAG.AssignOrdering(t7.getNode(), SDNodeOrder); - DAG.AssignOrdering(t8.getNode(), SDNodeOrder); - DAG.AssignOrdering(t9.getNode(), SDNodeOrder); - DAG.AssignOrdering(t10.getNode(), SDNodeOrder); - DAG.AssignOrdering(t11.getNode(), SDNodeOrder); - DAG.AssignOrdering(t12.getNode(), SDNodeOrder); - DAG.AssignOrdering(t13.getNode(), SDNodeOrder); - DAG.AssignOrdering(t14.getNode(), SDNodeOrder); - DAG.AssignOrdering(TwoToFractionalPartOfX.getNode(), SDNodeOrder); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } } else { // No special expansion. @@ -4052,7 +3640,6 @@ SelectionDAGBuilder::visitPow(CallInst &I) { getValue(I.getOperand(1)).getValueType(), getValue(I.getOperand(1)), getValue(I.getOperand(2))); - DAG.AssignOrdering(result.getNode(), SDNodeOrder); } setValue(&I, result); @@ -4129,16 +3716,12 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { case Intrinsic::vaend: visitVAEnd(I); return 0; case Intrinsic::vacopy: visitVACopy(I); return 0; case Intrinsic::returnaddress: - Res = DAG.getNode(ISD::RETURNADDR, dl, TLI.getPointerTy(), - getValue(I.getOperand(1))); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::RETURNADDR, dl, TLI.getPointerTy(), + getValue(I.getOperand(1)))); return 0; case Intrinsic::frameaddress: - Res = DAG.getNode(ISD::FRAMEADDR, dl, TLI.getPointerTy(), - getValue(I.getOperand(1))); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::FRAMEADDR, dl, TLI.getPointerTy(), + getValue(I.getOperand(1)))); return 0; case Intrinsic::setjmp: return "_setjmp"+!TLI.usesUnderscoreSetJmp(); @@ -4149,10 +3732,8 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { SDValue Op2 = getValue(I.getOperand(2)); SDValue Op3 = getValue(I.getOperand(3)); unsigned Align = cast<ConstantInt>(I.getOperand(4))->getZExtValue(); - Res = DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, false, - I.getOperand(1), 0, I.getOperand(2), 0); - DAG.setRoot(Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.setRoot(DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, false, + I.getOperand(1), 0, I.getOperand(2), 0)); return 0; } case Intrinsic::memset: { @@ -4160,10 +3741,8 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { SDValue Op2 = getValue(I.getOperand(2)); SDValue Op3 = getValue(I.getOperand(3)); unsigned Align = cast<ConstantInt>(I.getOperand(4))->getZExtValue(); - Res = DAG.getMemset(getRoot(), dl, Op1, Op2, Op3, Align, - I.getOperand(1), 0); - DAG.setRoot(Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.setRoot(DAG.getMemset(getRoot(), dl, Op1, Op2, Op3, Align, + I.getOperand(1), 0)); return 0; } case Intrinsic::memmove: { @@ -4179,20 +3758,18 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { Size = C->getZExtValue(); if (AA->alias(I.getOperand(1), Size, I.getOperand(2), Size) == AliasAnalysis::NoAlias) { - Res = DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, false, - I.getOperand(1), 0, I.getOperand(2), 0); - DAG.setRoot(Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.setRoot(DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, false, + I.getOperand(1), 0, I.getOperand(2), 0)); return 0; } - Res = DAG.getMemmove(getRoot(), dl, Op1, Op2, Op3, Align, - I.getOperand(1), 0, I.getOperand(2), 0); - DAG.setRoot(Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.setRoot(DAG.getMemmove(getRoot(), dl, Op1, Op2, Op3, Align, + I.getOperand(1), 0, I.getOperand(2), 0)); return 0; } case Intrinsic::dbg_declare: { + // FIXME: currently, we get here only if OptLevel != CodeGenOpt::None. + // The real handling of this intrinsic is in FastISel. if (OptLevel != CodeGenOpt::None) // FIXME: Variable debug info is not supported here. return 0; @@ -4205,6 +3782,8 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { MDNode *Variable = DI.getVariable(); Value *Address = DI.getAddress(); + if (!Address) + return 0; if (BitCastInst *BCI = dyn_cast<BitCastInst>(Address)) Address = BCI->getOperand(0); AllocaInst *AI = dyn_cast<AllocaInst>(Address); @@ -4222,6 +3801,39 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { MMI->setVariableDbgInfo(Variable, FI, Dbg); return 0; } + case Intrinsic::dbg_value: { + // FIXME: currently, we get here only if OptLevel != CodeGenOpt::None. + // The real handling of this intrinsic is in FastISel. + if (OptLevel != CodeGenOpt::None) + // FIXME: Variable debug info is not supported here. + return 0; + DwarfWriter *DW = DAG.getDwarfWriter(); + if (!DW) + return 0; + DbgValueInst &DI = cast<DbgValueInst>(I); + if (!DIDescriptor::ValidDebugInfo(DI.getVariable(), CodeGenOpt::None)) + return 0; + + MDNode *Variable = DI.getVariable(); + Value *V = DI.getValue(); + if (!V) + return 0; + if (BitCastInst *BCI = dyn_cast<BitCastInst>(V)) + V = BCI->getOperand(0); + AllocaInst *AI = dyn_cast<AllocaInst>(V); + // Don't handle byval struct arguments or VLAs, for example. + if (!AI) + return 0; + DenseMap<const AllocaInst*, int>::iterator SI = + FuncInfo.StaticAllocaMap.find(AI); + if (SI == FuncInfo.StaticAllocaMap.end()) + return 0; // VLAs. + int FI = SI->second; + if (MachineModuleInfo *MMI = DAG.getMachineModuleInfo()) + if (MDNode *Dbg = DI.getMetadata("dbg")) + MMI->setVariableDbgInfo(Variable, FI, Dbg); + return 0; + } case Intrinsic::eh_exception: { // Insert the EXCEPTIONADDR instruction. assert(CurMBB->isLandingPad() &&"Call to eh.exception not in landing pad!"); @@ -4231,7 +3843,6 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { SDValue Op = DAG.getNode(ISD::EXCEPTIONADDR, dl, VTs, Ops, 1); setValue(&I, Op); DAG.setRoot(Op.getValue(1)); - DAG.AssignOrdering(Op.getNode(), SDNodeOrder); return 0; } @@ -4255,13 +3866,8 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { Ops[0] = getValue(I.getOperand(1)); Ops[1] = getRoot(); SDValue Op = DAG.getNode(ISD::EHSELECTION, dl, VTs, Ops, 2); - DAG.setRoot(Op.getValue(1)); - - Res = DAG.getSExtOrTrunc(Op, dl, MVT::i32); - setValue(&I, Res); - DAG.AssignOrdering(Op.getNode(), SDNodeOrder); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getSExtOrTrunc(Op, dl, MVT::i32)); return 0; } @@ -4279,7 +3885,6 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { } setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } @@ -4287,13 +3892,11 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { case Intrinsic::eh_return_i64: if (MachineModuleInfo *MMI = DAG.getMachineModuleInfo()) { MMI->setCallsEHReturn(true); - Res = DAG.getNode(ISD::EH_RETURN, dl, - MVT::Other, - getControlRoot(), - getValue(I.getOperand(1)), - getValue(I.getOperand(2))); - DAG.setRoot(Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.setRoot(DAG.getNode(ISD::EH_RETURN, dl, + MVT::Other, + getControlRoot(), + getValue(I.getOperand(1)), + getValue(I.getOperand(2)))); } else { setValue(&I, DAG.getConstant(0, TLI.getPointerTy())); } @@ -4316,15 +3919,20 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { SDValue FA = DAG.getNode(ISD::FRAMEADDR, dl, TLI.getPointerTy(), DAG.getConstant(0, TLI.getPointerTy())); - Res = DAG.getNode(ISD::ADD, dl, TLI.getPointerTy(), - FA, Offset); - setValue(&I, Res); - DAG.AssignOrdering(CfaArg.getNode(), SDNodeOrder); - DAG.AssignOrdering(Offset.getNode(), SDNodeOrder); - DAG.AssignOrdering(FA.getNode(), SDNodeOrder); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::ADD, dl, TLI.getPointerTy(), + FA, Offset)); + return 0; + } + case Intrinsic::eh_sjlj_callsite: { + MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); + ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1)); + assert(CI && "Non-constant call site value in eh.sjlj.callsite!"); + assert(MMI->getCurrentCallSite() == 0 && "Overlapping call sites!"); + + MMI->setCurrentCallSite(CI->getZExtValue()); return 0; } + case Intrinsic::convertff: case Intrinsic::convertfsi: case Intrinsic::convertfui: @@ -4355,35 +3963,26 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { getValue(I.getOperand(3)), Code); setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::sqrt: - Res = DAG.getNode(ISD::FSQRT, dl, - getValue(I.getOperand(1)).getValueType(), - getValue(I.getOperand(1))); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::FSQRT, dl, + getValue(I.getOperand(1)).getValueType(), + getValue(I.getOperand(1)))); return 0; case Intrinsic::powi: - Res = ExpandPowI(dl, getValue(I.getOperand(1)), getValue(I.getOperand(2)), - DAG); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, ExpandPowI(dl, getValue(I.getOperand(1)), + getValue(I.getOperand(2)), DAG)); return 0; case Intrinsic::sin: - Res = DAG.getNode(ISD::FSIN, dl, - getValue(I.getOperand(1)).getValueType(), - getValue(I.getOperand(1))); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::FSIN, dl, + getValue(I.getOperand(1)).getValueType(), + getValue(I.getOperand(1)))); return 0; case Intrinsic::cos: - Res = DAG.getNode(ISD::FCOS, dl, - getValue(I.getOperand(1)).getValueType(), - getValue(I.getOperand(1))); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::FCOS, dl, + getValue(I.getOperand(1)).getValueType(), + getValue(I.getOperand(1)))); return 0; case Intrinsic::log: visitLog(I); @@ -4405,9 +4004,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { return 0; case Intrinsic::pcmarker: { SDValue Tmp = getValue(I.getOperand(1)); - Res = DAG.getNode(ISD::PCMARKER, dl, MVT::Other, getRoot(), Tmp); - DAG.setRoot(Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.setRoot(DAG.getNode(ISD::PCMARKER, dl, MVT::Other, getRoot(), Tmp)); return 0; } case Intrinsic::readcyclecounter: { @@ -4417,38 +4014,29 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { &Op, 1); setValue(&I, Res); DAG.setRoot(Res.getValue(1)); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::bswap: - Res = DAG.getNode(ISD::BSWAP, dl, - getValue(I.getOperand(1)).getValueType(), - getValue(I.getOperand(1))); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::BSWAP, dl, + getValue(I.getOperand(1)).getValueType(), + getValue(I.getOperand(1)))); return 0; case Intrinsic::cttz: { SDValue Arg = getValue(I.getOperand(1)); EVT Ty = Arg.getValueType(); - Res = DAG.getNode(ISD::CTTZ, dl, Ty, Arg); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::CTTZ, dl, Ty, Arg)); return 0; } case Intrinsic::ctlz: { SDValue Arg = getValue(I.getOperand(1)); EVT Ty = Arg.getValueType(); - Res = DAG.getNode(ISD::CTLZ, dl, Ty, Arg); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::CTLZ, dl, Ty, Arg)); return 0; } case Intrinsic::ctpop: { SDValue Arg = getValue(I.getOperand(1)); EVT Ty = Arg.getValueType(); - Res = DAG.getNode(ISD::CTPOP, dl, Ty, Arg); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::CTPOP, dl, Ty, Arg)); return 0; } case Intrinsic::stacksave: { @@ -4457,14 +4045,11 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { DAG.getVTList(TLI.getPointerTy(), MVT::Other), &Op, 1); setValue(&I, Res); DAG.setRoot(Res.getValue(1)); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::stackrestore: { Res = getValue(I.getOperand(1)); - Res = DAG.getNode(ISD::STACKRESTORE, dl, MVT::Other, getRoot(), Res); - DAG.setRoot(Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.setRoot(DAG.getNode(ISD::STACKRESTORE, dl, MVT::Other, getRoot(), Res)); return 0; } case Intrinsic::stackprotector: { @@ -4484,10 +4069,9 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { // Store the stack protector onto the stack. Res = DAG.getStore(getRoot(), getCurDebugLoc(), Src, FIN, PseudoSourceValue::getFixedStack(FI), - 0, true); + 0, true, false, 0); setValue(&I, Res); DAG.setRoot(Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::objectsize: { @@ -4505,7 +4089,6 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { Res = DAG.getConstant(0, Ty); setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::var_annotation: @@ -4529,7 +4112,6 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { setValue(&I, Res); DAG.setRoot(Res.getValue(1)); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); return 0; } case Intrinsic::gcroot: @@ -4546,14 +4128,10 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { llvm_unreachable("GC failed to lower gcread/gcwrite intrinsics!"); return 0; case Intrinsic::flt_rounds: - Res = DAG.getNode(ISD::FLT_ROUNDS_, dl, MVT::i32); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getNode(ISD::FLT_ROUNDS_, dl, MVT::i32)); return 0; case Intrinsic::trap: - Res = DAG.getNode(ISD::TRAP, dl,MVT::Other, getRoot()); - DAG.setRoot(Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.setRoot(DAG.getNode(ISD::TRAP, dl,MVT::Other, getRoot())); return 0; case Intrinsic::uadd_with_overflow: return implVisitAluOverflow(I, ISD::UADDO); @@ -4574,9 +4152,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { Ops[1] = getValue(I.getOperand(1)); Ops[2] = getValue(I.getOperand(2)); Ops[3] = getValue(I.getOperand(3)); - Res = DAG.getNode(ISD::PREFETCH, dl, MVT::Other, &Ops[0], 4); - DAG.setRoot(Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.setRoot(DAG.getNode(ISD::PREFETCH, dl, MVT::Other, &Ops[0], 4)); return 0; } @@ -4586,9 +4162,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { for (int x = 1; x < 6; ++x) Ops[x] = getValue(I.getOperand(x)); - Res = DAG.getNode(ISD::MEMBARRIER, dl, MVT::Other, &Ops[0], 6); - DAG.setRoot(Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + DAG.setRoot(DAG.getNode(ISD::MEMBARRIER, dl, MVT::Other, &Ops[0], 6)); return 0; } case Intrinsic::atomic_cmp_swap: { @@ -4603,7 +4177,6 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { I.getOperand(1)); setValue(&I, L); DAG.setRoot(L.getValue(1)); - DAG.AssignOrdering(L.getNode(), SDNodeOrder); return 0; } case Intrinsic::atomic_load_add: @@ -4632,9 +4205,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { case Intrinsic::invariant_start: case Intrinsic::lifetime_start: // Discard region information. - Res = DAG.getUNDEF(TLI.getPointerTy()); - setValue(&I, Res); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); + setValue(&I, DAG.getUNDEF(TLI.getPointerTy())); return 0; case Intrinsic::invariant_end: case Intrinsic::lifetime_end: @@ -4649,19 +4220,25 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { /// between it and the return. /// /// This function only tests target-independent requirements. -/// For target-dependent requirements, a target should override -/// TargetLowering::IsEligibleForTailCallOptimization. -/// static bool -isInTailCallPosition(const Instruction *I, Attributes CalleeRetAttr, +isInTailCallPosition(CallSite CS, Attributes CalleeRetAttr, const TargetLowering &TLI) { + const Instruction *I = CS.getInstruction(); const BasicBlock *ExitBB = I->getParent(); const TerminatorInst *Term = ExitBB->getTerminator(); const ReturnInst *Ret = dyn_cast<ReturnInst>(Term); const Function *F = ExitBB->getParent(); - // The block must end in a return statement or an unreachable. - if (!Ret && !isa<UnreachableInst>(Term)) return false; + // The block must end in a return statement or unreachable. + // + // FIXME: Decline tailcall if it's not guaranteed and if the block ends in + // an unreachable, for now. The way tailcall optimization is currently + // implemented means it will add an epilogue followed by a jump. That is + // not profitable. Also, if the callee is a special function (e.g. + // longjmp on x86), it can end up causing miscompilation that has not + // been fully understood. + if (!Ret && + (!GuaranteedTailCallOpt || !isa<UnreachableInst>(Term))) return false; // If I will have a chain, make sure no other instruction that will have a // chain interposes between I and the return. @@ -4690,6 +4267,10 @@ isInTailCallPosition(const Instruction *I, Attributes CalleeRetAttr, if ((CalleeRetAttr ^ CallerRetAttr) & ~Attribute::NoAlias) return false; + // It's not safe to eliminate the sign / zero extension of the return value. + if ((CallerRetAttr & Attribute::ZExt) || (CallerRetAttr & Attribute::SExt)) + return false; + // Otherwise, make sure the unmodified return value of I is the return value. for (const Instruction *U = dyn_cast<Instruction>(Ret->getOperand(0)); ; U = dyn_cast<Instruction>(U->getOperand(0))) { @@ -4785,6 +4366,15 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee, // used to detect deletion of the invoke via the MachineModuleInfo. BeginLabel = MMI->NextLabelID(); + // For SjLj, keep track of which landing pads go with which invokes + // so as to maintain the ordering of pads in the LSDA. + unsigned CallSiteIndex = MMI->getCurrentCallSite(); + if (CallSiteIndex) { + MMI->setCallSiteBeginLabel(BeginLabel, CallSiteIndex); + // Now that the call site is handled, stop tracking it. + MMI->setCurrentCallSite(0); + } + // Both PendingLoads and PendingExports must be flushed here; // this call might not return. (void)getRoot(); @@ -4795,9 +4385,7 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee, // Check if target-independent constraints permit a tail call here. // Target-dependent constraints are checked within TLI.LowerCallTo. if (isTailCall && - !isInTailCallPosition(CS.getInstruction(), - CS.getAttributes().getRetAttributes(), - TLI)) + !isInTailCallPosition(CS, CS.getAttributes().getRetAttributes(), TLI)) isTailCall = false; std::pair<SDValue,SDValue> Result = @@ -4815,7 +4403,6 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee, "Null value expected with tail call!"); if (Result.first.getNode()) { setValue(CS.getInstruction(), Result.first); - DAG.AssignOrdering(Result.first.getNode(), SDNodeOrder); } else if (!CanLowerReturn && Result.second.getNode()) { // The instruction result is the result of loading from the // hidden sret parameter. @@ -4834,7 +4421,7 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee, DemoteStackSlot, DAG.getConstant(Offsets[i], PtrVT)); SDValue L = DAG.getLoad(OutVTs[i], getCurDebugLoc(), Result.second, - Add, NULL, Offsets[i], false, 1); + Add, NULL, Offsets[i], false, false, 1); Values[i] = L; Chains[i] = L.getValue(1); } @@ -4860,27 +4447,22 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee, getCopyFromParts(DAG, getCurDebugLoc(), SDNodeOrder, &Values[CurReg], NumRegs, RegisterVT, VT, AssertOp); ReturnValues.push_back(ReturnValue); - DAG.AssignOrdering(ReturnValue.getNode(), SDNodeOrder); CurReg += NumRegs; } - SDValue Res = DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), - DAG.getVTList(&RetTys[0], RetTys.size()), - &ReturnValues[0], ReturnValues.size()); - setValue(CS.getInstruction(), Res); + setValue(CS.getInstruction(), + DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), + DAG.getVTList(&RetTys[0], RetTys.size()), + &ReturnValues[0], ReturnValues.size())); - DAG.AssignOrdering(Chain.getNode(), SDNodeOrder); - DAG.AssignOrdering(Res.getNode(), SDNodeOrder); } // As a special case, a null chain means that a tail call has been emitted and // the DAG root is already updated. - if (Result.second.getNode()) { + if (Result.second.getNode()) DAG.setRoot(Result.second); - DAG.AssignOrdering(Result.second.getNode(), SDNodeOrder); - } else { + else HasTailCall = true; - } if (LandingPad && MMI) { // Insert a label at the end of the invoke call to mark the try range. This @@ -4941,7 +4523,8 @@ static SDValue getMemCmpLoad(Value *PtrVal, MVT LoadVT, const Type *LoadTy, SDValue Ptr = Builder.getValue(PtrVal); SDValue LoadVal = Builder.DAG.getLoad(LoadVT, Builder.getCurDebugLoc(), Root, Ptr, PtrVal /*SrcValue*/, 0/*SVOffset*/, - false /*volatile*/, 1 /* align=1 */); + false /*volatile*/, + false /*nontemporal*/, 1 /* align=1 */); if (!ConstantMemory) Builder.PendingLoads.push_back(LoadVal.getValue(1)); @@ -5054,7 +4637,7 @@ void SelectionDAGBuilder::visitCall(CallInst &I) { StringRef Name = F->getName(); if (Name == "copysign" || Name == "copysignf") { if (I.getNumOperands() == 3 && // Basic sanity checks. - I.getOperand(1)->getType()->isFloatingPoint() && + I.getOperand(1)->getType()->isFloatingPointTy() && I.getType() == I.getOperand(1)->getType() && I.getType() == I.getOperand(2)->getType()) { SDValue LHS = getValue(I.getOperand(1)); @@ -5065,7 +4648,7 @@ void SelectionDAGBuilder::visitCall(CallInst &I) { } } else if (Name == "fabs" || Name == "fabsf" || Name == "fabsl") { if (I.getNumOperands() == 2 && // Basic sanity checks. - I.getOperand(1)->getType()->isFloatingPoint() && + I.getOperand(1)->getType()->isFloatingPointTy() && I.getType() == I.getOperand(1)->getType()) { SDValue Tmp = getValue(I.getOperand(1)); setValue(&I, DAG.getNode(ISD::FABS, getCurDebugLoc(), @@ -5074,7 +4657,7 @@ void SelectionDAGBuilder::visitCall(CallInst &I) { } } else if (Name == "sin" || Name == "sinf" || Name == "sinl") { if (I.getNumOperands() == 2 && // Basic sanity checks. - I.getOperand(1)->getType()->isFloatingPoint() && + I.getOperand(1)->getType()->isFloatingPointTy() && I.getType() == I.getOperand(1)->getType() && I.onlyReadsMemory()) { SDValue Tmp = getValue(I.getOperand(1)); @@ -5084,7 +4667,7 @@ void SelectionDAGBuilder::visitCall(CallInst &I) { } } else if (Name == "cos" || Name == "cosf" || Name == "cosl") { if (I.getNumOperands() == 2 && // Basic sanity checks. - I.getOperand(1)->getType()->isFloatingPoint() && + I.getOperand(1)->getType()->isFloatingPointTy() && I.getType() == I.getOperand(1)->getType() && I.onlyReadsMemory()) { SDValue Tmp = getValue(I.getOperand(1)); @@ -5094,7 +4677,7 @@ void SelectionDAGBuilder::visitCall(CallInst &I) { } } else if (Name == "sqrt" || Name == "sqrtf" || Name == "sqrtl") { if (I.getNumOperands() == 2 && // Basic sanity checks. - I.getOperand(1)->getType()->isFloatingPoint() && + I.getOperand(1)->getType()->isFloatingPointTy() && I.getType() == I.getOperand(1)->getType() && I.onlyReadsMemory()) { SDValue Tmp = getValue(I.getOperand(1)); @@ -5120,9 +4703,7 @@ void SelectionDAGBuilder::visitCall(CallInst &I) { // Check if we can potentially perform a tail call. More detailed checking is // be done within LowerCallTo, after more information about the call is known. - bool isTailCall = PerformTailCallOpt && I.isTailCall(); - - LowerCallTo(&I, Callee, isTailCall); + LowerCallTo(&I, Callee, I.isTailCall()); } /// getCopyFromRegs - Emit a series of CopyFromReg nodes that copies from @@ -5152,7 +4733,6 @@ SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG, DebugLoc dl, } Chain = P.getValue(1); - DAG.AssignOrdering(P.getNode(), Order); // If the source register was virtual and if we know something about it, // add an assert node. @@ -5188,11 +4768,9 @@ SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG, DebugLoc dl, else if (NumZeroBits >= RegSize-32) isSExt = false, FromVT = MVT::i32; // ASSERT ZEXT 32 - if (FromVT != MVT::Other) { + if (FromVT != MVT::Other) P = DAG.getNode(isSExt ? ISD::AssertSext : ISD::AssertZext, dl, RegisterVT, P, DAG.getValueType(FromVT)); - DAG.AssignOrdering(P.getNode(), Order); - } } } @@ -5201,16 +4779,13 @@ SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG, DebugLoc dl, Values[Value] = getCopyFromParts(DAG, dl, Order, Parts.begin(), NumRegs, RegisterVT, ValueVT); - DAG.AssignOrdering(Values[Value].getNode(), Order); Part += NumRegs; Parts.clear(); } - SDValue Res = DAG.getNode(ISD::MERGE_VALUES, dl, - DAG.getVTList(&ValueVTs[0], ValueVTs.size()), - &Values[0], ValueVTs.size()); - DAG.AssignOrdering(Res.getNode(), Order); - return Res; + return DAG.getNode(ISD::MERGE_VALUES, dl, + DAG.getVTList(&ValueVTs[0], ValueVTs.size()), + &Values[0], ValueVTs.size()); } /// getCopyToRegs - Emit a series of CopyToReg nodes that copies the @@ -5246,7 +4821,6 @@ void RegsForValue::getCopyToRegs(SDValue Val, SelectionDAG &DAG, DebugLoc dl, } Chains[i] = Part.getValue(0); - DAG.AssignOrdering(Part.getNode(), Order); } if (NumRegs == 1 || Flag) @@ -5263,8 +4837,6 @@ void RegsForValue::getCopyToRegs(SDValue Val, SelectionDAG &DAG, DebugLoc dl, Chain = Chains[NumRegs-1]; else Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &Chains[0], NumRegs); - - DAG.AssignOrdering(Chain.getNode(), Order); } /// AddInlineAsmOperands - Add this value to the specified inlineasm node @@ -5281,16 +4853,12 @@ void RegsForValue::AddInlineAsmOperands(unsigned Code, SDValue Res = DAG.getTargetConstant(Flag, MVT::i32); Ops.push_back(Res); - DAG.AssignOrdering(Res.getNode(), Order); - for (unsigned Value = 0, Reg = 0, e = ValueVTs.size(); Value != e; ++Value) { unsigned NumRegs = TLI->getNumRegisters(*DAG.getContext(), ValueVTs[Value]); EVT RegisterVT = RegVTs[Value]; for (unsigned i = 0; i != NumRegs; ++i) { assert(Reg < Regs.size() && "Mismatch in # registers expected"); - SDValue Res = DAG.getRegister(Regs[Reg++], RegisterVT); - Ops.push_back(Res); - DAG.AssignOrdering(Res.getNode(), Order); + Ops.push_back(DAG.getRegister(Regs[Reg++], RegisterVT)); } } } @@ -5309,7 +4877,7 @@ isAllocatableRegister(unsigned Reg, MachineFunction &MF, EVT ThisVT = MVT::Other; const TargetRegisterClass *RC = *RCI; - // If none of the the value types for this register class are valid, we + // If none of the value types for this register class are valid, we // can't use it. For example, 64-bit reg classes on 32-bit targets. for (TargetRegisterClass::vt_iterator I = RC->vt_begin(), E = RC->vt_end(); I != E; ++I) { @@ -5509,8 +5077,6 @@ GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, RegVT, OpInfo.CallOperand); OpInfo.ConstraintVT = RegVT; } - - DAG.AssignOrdering(OpInfo.CallOperand.getNode(), SDNodeOrder); } NumRegs = TLI.getNumRegisters(Context, OpInfo.ConstraintVT); @@ -5776,7 +5342,8 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) { int SSFI = MF.getFrameInfo()->CreateStackObject(TySize, Align, false); SDValue StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy()); Chain = DAG.getStore(Chain, getCurDebugLoc(), - OpInfo.CallOperand, StackSlot, NULL, 0); + OpInfo.CallOperand, StackSlot, NULL, 0, + false, false, 0); OpInfo.CallOperand = StackSlot; } @@ -5972,7 +5539,8 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) { "Don't know how to handle indirect register inputs yet!"); // Copy the input into the appropriate registers. - if (OpInfo.AssignedRegs.Regs.empty()) { + if (OpInfo.AssignedRegs.Regs.empty() || + !OpInfo.AssignedRegs.areValueTypesLegal()) { llvm_report_error("Couldn't allocate input reg for" " constraint '"+ OpInfo.ConstraintCode +"'!"); } @@ -6061,7 +5629,8 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) { SDValue Val = DAG.getStore(Chain, getCurDebugLoc(), StoresToEmit[i].first, getValue(StoresToEmit[i].second), - StoresToEmit[i].second, 0); + StoresToEmit[i].second, 0, + false, false, 0); OutChains.push_back(Val); } @@ -6116,9 +5685,6 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, SDValue Callee, ArgListTy &Args, SelectionDAG &DAG, DebugLoc dl, unsigned Order) { - assert((!isTailCall || PerformTailCallOpt) && - "isTailCall set when tail-call optimizations are disabled!"); - // Handle all of the outgoing arguments. SmallVector<ISD::OutputArg, 32> Outs; for (unsigned i = 0, e = Args.size(); i != e; ++i) { @@ -6207,12 +5773,6 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, } } - // Check if target-dependent constraints permit a tail call here. - // Target-independent constraints should be checked by the caller. - if (isTailCall && - !IsEligibleForTailCallOptimization(Callee, CallConv, isVarArg, Ins, DAG)) - isTailCall = false; - SmallVector<SDValue, 4> InVals; Chain = LowerCall(Chain, Callee, CallConv, isVarArg, isTailCall, Outs, Ins, dl, DAG, InVals); @@ -6231,8 +5791,6 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, "LowerCall emitted a value with the wrong type!"); }); - DAG.AssignOrdering(Chain.getNode(), Order); - // For a tail call, the return value is merely live-out and there aren't // any nodes in the DAG representing it. Return a special value to // indicate that a tail call has been emitted and no more Instructions @@ -6256,11 +5814,9 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, EVT RegisterVT = getRegisterType(RetTy->getContext(), VT); unsigned NumRegs = getNumRegisters(RetTy->getContext(), VT); - SDValue ReturnValue = - getCopyFromParts(DAG, dl, Order, &InVals[CurReg], NumRegs, - RegisterVT, VT, AssertOp); - ReturnValues.push_back(ReturnValue); - DAG.AssignOrdering(ReturnValue.getNode(), Order); + ReturnValues.push_back(getCopyFromParts(DAG, dl, Order, &InVals[CurReg], + NumRegs, RegisterVT, VT, + AssertOp)); CurReg += NumRegs; } @@ -6273,7 +5829,6 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, SDValue Res = DAG.getNode(ISD::MERGE_VALUES, dl, DAG.getVTList(&RetTys[0], RetTys.size()), &ReturnValues[0], ReturnValues.size()); - DAG.AssignOrdering(Res.getNode(), Order); return std::make_pair(Res, Chain); } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index db656e3..bc4b33d 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -342,6 +342,11 @@ public: void CopyValueToVirtualRegister(Value *V, unsigned Reg); + /// AssignOrderingToNode - Assign an ordering to the node. The order is gotten + /// from how the code appeared in the source. The ordering is used by the + /// scheduler to effectively turn off scheduling. + void AssignOrderingToNode(const SDNode *Node); + void visit(Instruction &I); void visit(unsigned Opcode, User &I); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 2bec964..eead526 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -457,6 +457,21 @@ public: }; } +/// TrivialTruncElim - Eliminate some trivial nops that can result from +/// ShrinkDemandedOps: (trunc (ext n)) -> n. +static bool TrivialTruncElim(SDValue Op, + TargetLowering::TargetLoweringOpt &TLO) { + SDValue N0 = Op.getOperand(0); + EVT VT = Op.getValueType(); + if ((N0.getOpcode() == ISD::ZERO_EXTEND || + N0.getOpcode() == ISD::SIGN_EXTEND || + N0.getOpcode() == ISD::ANY_EXTEND) && + N0.getOperand(0).getValueType() == VT) { + return TLO.CombineTo(Op, N0.getOperand(0)); + } + return false; +} + /// ShrinkDemandedOps - A late transformation pass that shrink expressions /// using TargetLowering::TargetLoweringOpt::ShrinkDemandedOp. It converts /// x+y to (VT)((SmallVT)x+(SmallVT)y) if the casts are free. @@ -489,7 +504,9 @@ void SelectionDAGISel::ShrinkDemandedOps() { APInt Demanded = APInt::getAllOnesValue(BitWidth); APInt KnownZero, KnownOne; if (TLI.SimplifyDemandedBits(SDValue(N, 0), Demanded, - KnownZero, KnownOne, TLO)) { + KnownZero, KnownOne, TLO) || + (N->getOpcode() == ISD::TRUNCATE && + TrivialTruncElim(SDValue(N, 0), TLO))) { // Revisit the node. Worklist.erase(std::remove(Worklist.begin(), Worklist.end(), N), Worklist.end()); @@ -801,7 +818,7 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, // landing pad can thus be detected via the MachineModuleInfo. unsigned LabelID = MMI->addLandingPad(BB); - const TargetInstrDesc &II = TII.get(TargetInstrInfo::EH_LABEL); + const TargetInstrDesc &II = TII.get(TargetOpcode::EH_LABEL); BuildMI(BB, SDB->getCurDebugLoc(), II).addImm(LabelID); // Mark exception register as live in. @@ -953,7 +970,7 @@ SelectionDAGISel::FinishBasicBlock() { SDB->BitTestCases.empty()) { for (unsigned i = 0, e = SDB->PHINodesToUpdate.size(); i != e; ++i) { MachineInstr *PHI = SDB->PHINodesToUpdate[i].first; - assert(PHI->getOpcode() == TargetInstrInfo::PHI && + assert(PHI->isPHI() && "This is not a machine PHI node that we are updating!"); PHI->addOperand(MachineOperand::CreateReg(SDB->PHINodesToUpdate[i].second, false)); @@ -1000,7 +1017,7 @@ SelectionDAGISel::FinishBasicBlock() { for (unsigned pi = 0, pe = SDB->PHINodesToUpdate.size(); pi != pe; ++pi) { MachineInstr *PHI = SDB->PHINodesToUpdate[pi].first; MachineBasicBlock *PHIBB = PHI->getParent(); - assert(PHI->getOpcode() == TargetInstrInfo::PHI && + assert(PHI->isPHI() && "This is not a machine PHI node that we are updating!"); // This is "default" BB. We have two jumps to it. From "header" BB and // from last "case" BB. @@ -1056,7 +1073,7 @@ SelectionDAGISel::FinishBasicBlock() { for (unsigned pi = 0, pe = SDB->PHINodesToUpdate.size(); pi != pe; ++pi) { MachineInstr *PHI = SDB->PHINodesToUpdate[pi].first; MachineBasicBlock *PHIBB = PHI->getParent(); - assert(PHI->getOpcode() == TargetInstrInfo::PHI && + assert(PHI->isPHI() && "This is not a machine PHI node that we are updating!"); // "default" BB. We can go there only from header BB. if (PHIBB == SDB->JTCases[i].second.Default) { @@ -1079,7 +1096,7 @@ SelectionDAGISel::FinishBasicBlock() { // need to update PHI nodes in that block. for (unsigned i = 0, e = SDB->PHINodesToUpdate.size(); i != e; ++i) { MachineInstr *PHI = SDB->PHINodesToUpdate[i].first; - assert(PHI->getOpcode() == TargetInstrInfo::PHI && + assert(PHI->isPHI() && "This is not a machine PHI node that we are updating!"); if (BB->isSuccessor(PHI->getParent())) { PHI->addOperand(MachineOperand::CreateReg(SDB->PHINodesToUpdate[i].second, @@ -1116,7 +1133,7 @@ SelectionDAGISel::FinishBasicBlock() { // BB may have been removed from the CFG if a branch was constant folded. if (ThisBB->isSuccessor(BB)) { for (MachineBasicBlock::iterator Phi = BB->begin(); - Phi != BB->end() && Phi->getOpcode() == TargetInstrInfo::PHI; + Phi != BB->end() && Phi->isPHI(); ++Phi) { // This value for this PHI node is recorded in PHINodesToUpdate. for (unsigned pn = 0; ; ++pn) { @@ -1324,8 +1341,7 @@ static bool findNonImmUse(SDNode *Use, SDNode* Def, SDNode *ImmedUse, /// isNonImmUse - Start searching from Root up the DAG to check is Def can /// be reached. Return true if that's the case. However, ignore direct uses /// by ImmedUse (which would be U in the example illustrated in -/// IsLegalAndProfitableToFold) and by Root (which can happen in the store -/// case). +/// IsLegalToFold) and by Root (which can happen in the store case). /// FIXME: to be really generic, we should allow direct use by any node /// that is being folded. But realisticly since we only fold loads which /// have one non-chain use, we only need to watch out for load/op/store @@ -1336,11 +1352,17 @@ static inline bool isNonImmUse(SDNode *Root, SDNode *Def, SDNode *ImmedUse) { return findNonImmUse(Root, Def, ImmedUse, Root, Visited); } -/// IsLegalAndProfitableToFold - Returns true if the specific operand node N of -/// U can be folded during instruction selection that starts at Root and -/// folding N is profitable. -bool SelectionDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U, - SDNode *Root) const { +/// IsProfitableToFold - Returns true if it's profitable to fold the specific +/// operand node N of U during instruction selection that starts at Root. +bool SelectionDAGISel::IsProfitableToFold(SDValue N, SDNode *U, + SDNode *Root) const { + if (OptLevel == CodeGenOpt::None) return false; + return N.hasOneUse(); +} + +/// IsLegalToFold - Returns true if the specific operand node N of +/// U can be folded during instruction selection that starts at Root. +bool SelectionDAGISel::IsLegalToFold(SDValue N, SDNode *U, SDNode *Root) const { if (OptLevel == CodeGenOpt::None) return false; // If Root use can somehow reach N through a path that that doesn't contain @@ -1394,7 +1416,7 @@ bool SelectionDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U, VT = Root->getValueType(Root->getNumValues()-1); } - return !isNonImmUse(Root, N, U); + return !isNonImmUse(Root, N.getNode(), U); } SDNode *SelectionDAGISel::Select_INLINEASM(SDNode *N) { @@ -1410,15 +1432,14 @@ SDNode *SelectionDAGISel::Select_INLINEASM(SDNode *N) { } SDNode *SelectionDAGISel::Select_UNDEF(SDNode *N) { - return CurDAG->SelectNodeTo(N, TargetInstrInfo::IMPLICIT_DEF, - N->getValueType(0)); + return CurDAG->SelectNodeTo(N, TargetOpcode::IMPLICIT_DEF,N->getValueType(0)); } SDNode *SelectionDAGISel::Select_EH_LABEL(SDNode *N) { SDValue Chain = N->getOperand(0); unsigned C = cast<LabelSDNode>(N)->getLabelID(); SDValue Tmp = CurDAG->getTargetConstant(C, MVT::i32); - return CurDAG->SelectNodeTo(N, TargetInstrInfo::EH_LABEL, + return CurDAG->SelectNodeTo(N, TargetOpcode::EH_LABEL, MVT::Other, Tmp, Chain); } diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 81c51c4..e88af4f 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -13,6 +13,7 @@ #include "llvm/Target/TargetLowering.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCExpr.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" @@ -21,6 +22,8 @@ #include "llvm/GlobalVariable.h" #include "llvm/DerivedTypes.h" #include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" @@ -507,7 +510,6 @@ TargetLowering::TargetLowering(TargetMachine &tm,TargetLoweringObjectFile *tlof) setOperationAction(ISD::TRAP, MVT::Other, Expand); IsLittleEndian = TD->isLittleEndian(); - UsesGlobalOffsetTable = false; ShiftAmountTy = PointerTy = MVT::getIntegerVT(8*TD->getPointerSize()); memset(RegClassForVT, 0,MVT::LAST_VALUETYPE*sizeof(TargetRegisterClass*)); memset(TargetDAGCombineArray, 0, array_lengthof(TargetDAGCombineArray)); @@ -538,6 +540,24 @@ TargetLowering::~TargetLowering() { delete &TLOF; } +/// canOpTrap - Returns true if the operation can trap for the value type. +/// VT must be a legal type. +bool TargetLowering::canOpTrap(unsigned Op, EVT VT) const { + assert(isTypeLegal(VT)); + switch (Op) { + default: + return false; + case ISD::FDIV: + case ISD::FREM: + case ISD::SDIV: + case ISD::UDIV: + case ISD::SREM: + case ISD::UREM: + return true; + } +} + + static unsigned getVectorTypeBreakdownMVT(MVT VT, MVT &IntermediateVT, unsigned &NumIntermediates, EVT &RegisterVT, @@ -682,7 +702,7 @@ void TargetLowering::computeRegisterProperties() { for (unsigned nVT = i+1; nVT <= MVT::LAST_VECTOR_VALUETYPE; ++nVT) { EVT SVT = (MVT::SimpleValueType)nVT; if (isTypeLegal(SVT) && SVT.getVectorElementType() == EltVT && - SVT.getVectorNumElements() > NElts) { + SVT.getVectorNumElements() > NElts && NElts != 1) { TransformToType[i] = SVT; ValueTypeActions.setTypeAction(VT, Promote); IsLegalWiderType = true; @@ -793,13 +813,40 @@ unsigned TargetLowering::getByValTypeAlignment(const Type *Ty) const { return TD->getCallFrameTypeAlignment(Ty); } +/// getJumpTableEncoding - Return the entry encoding for a jump table in the +/// current function. The returned value is a member of the +/// MachineJumpTableInfo::JTEntryKind enum. +unsigned TargetLowering::getJumpTableEncoding() const { + // In non-pic modes, just use the address of a block. + if (getTargetMachine().getRelocationModel() != Reloc::PIC_) + return MachineJumpTableInfo::EK_BlockAddress; + + // In PIC mode, if the target supports a GPRel32 directive, use it. + if (getTargetMachine().getMCAsmInfo()->getGPRel32Directive() != 0) + return MachineJumpTableInfo::EK_GPRel32BlockAddress; + + // Otherwise, use a label difference. + return MachineJumpTableInfo::EK_LabelDifference32; +} + SDValue TargetLowering::getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG) const { - if (usesGlobalOffsetTable()) + // If our PIC model is GP relative, use the global offset table as the base. + if (getJumpTableEncoding() == MachineJumpTableInfo::EK_GPRel32BlockAddress) return DAG.getGLOBAL_OFFSET_TABLE(getPointerTy()); return Table; } +/// getPICJumpTableRelocBaseExpr - This returns the relocation base for the +/// given PIC jumptable, the same as getPICJumpTableRelocBase, but as an +/// MCExpr. +const MCExpr * +TargetLowering::getPICJumpTableRelocBaseExpr(const MachineFunction *MF, + unsigned JTI,MCContext &Ctx) const{ + // The normal PIC reloc base is the label at the start of the jump table. + return MCSymbolRefExpr::Create(MF->getJTISymbol(JTI, Ctx), Ctx); +} + bool TargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { // Assume that everything is safe in static mode. @@ -1669,7 +1716,7 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, SDValue NewLoad = DAG.getLoad(newVT, dl, Lod->getChain(), Ptr, Lod->getSrcValue(), Lod->getSrcValueOffset() + bestOffset, - false, NewAlign); + false, false, NewAlign); return DAG.getSetCC(dl, VT, DAG.getNode(ISD::AND, dl, newVT, NewLoad, DAG.getConstant(bestMask.trunc(bestWidth), @@ -2337,7 +2384,7 @@ getRegForInlineAsmConstraint(const std::string &Constraint, E = RI->regclass_end(); RCI != E; ++RCI) { const TargetRegisterClass *RC = *RCI; - // If none of the the value types for this register class are valid, we + // If none of the value types for this register class are valid, we // can't use it. For example, 64-bit reg classes on 32-bit targets. bool isLegal = false; for (TargetRegisterClass::vt_iterator I = RC->vt_begin(), E = RC->vt_end(); diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index 27d429b..e7b0cff 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -197,7 +197,7 @@ bool SimpleRegisterCoalescing::AdjustCopiesBackFrom(LiveInterval &IntA, SlotIndex FillerStart = ValLR->end, FillerEnd = BLR->start; // We are about to delete CopyMI, so need to remove it as the 'instruction - // that defines this value #'. Update the the valnum with the new defining + // that defines this value #'. Update the valnum with the new defining // instruction #. BValNo->def = FillerStart; BValNo->setCopy(0); @@ -375,8 +375,9 @@ bool SimpleRegisterCoalescing::RemoveCopyByCommutingDef(LiveInterval &IntA, // If some of the uses of IntA.reg is already coalesced away, return false. // It's not possible to determine whether it's safe to perform the coalescing. - for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(IntA.reg), - UE = mri_->use_end(); UI != UE; ++UI) { + for (MachineRegisterInfo::use_nodbg_iterator UI = + mri_->use_nodbg_begin(IntA.reg), + UE = mri_->use_nodbg_end(); UI != UE; ++UI) { MachineInstr *UseMI = &*UI; SlotIndex UseIdx = li_->getInstructionIndex(UseMI); LiveInterval::iterator ULR = IntA.FindLiveRangeContaining(UseIdx); @@ -430,6 +431,12 @@ bool SimpleRegisterCoalescing::RemoveCopyByCommutingDef(LiveInterval &IntA, ++UI; if (JoinedCopies.count(UseMI)) continue; + if (UseMI->isDebugValue()) { + // FIXME These don't have an instruction index. Not clear we have enough + // info to decide whether to do this replacement or not. For now do it. + UseMO.setReg(NewReg); + continue; + } SlotIndex UseIdx = li_->getInstructionIndex(UseMI).getUseIndex(); LiveInterval::iterator ULR = IntA.FindLiveRangeContaining(UseIdx); if (ULR == IntA.end() || ULR->valno != AValNo) @@ -659,7 +666,7 @@ bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt, return false; if (TID.getNumDefs() != 1) return false; - if (DefMI->getOpcode() != TargetInstrInfo::IMPLICIT_DEF) { + if (!DefMI->isImplicitDef()) { // Make sure the copy destination register class fits the instruction // definition register class. The mismatch can happen as a result of earlier // extract_subreg, insert_subreg, subreg_to_reg coalescing. @@ -764,11 +771,16 @@ SimpleRegisterCoalescing::UpdateRegDefsUses(unsigned SrcReg, unsigned DstReg, SubIdx = 0; } + // Copy the register use-list before traversing it. We may be adding operands + // and invalidating pointers. + SmallVector<std::pair<MachineInstr*, unsigned>, 32> reglist; for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(SrcReg), - E = mri_->reg_end(); I != E; ) { - MachineOperand &O = I.getOperand(); - MachineInstr *UseMI = &*I; - ++I; + E = mri_->reg_end(); I != E; ++I) + reglist.push_back(std::make_pair(&*I, I.getOperandNo())); + + for (unsigned N=0; N != reglist.size(); ++N) { + MachineInstr *UseMI = reglist[N].first; + MachineOperand &O = UseMI->getOperand(reglist[N].second); unsigned OldSubIdx = O.getSubReg(); if (DstIsPhys) { unsigned UseDstReg = DstReg; @@ -789,6 +801,19 @@ SimpleRegisterCoalescing::UpdateRegDefsUses(unsigned SrcReg, unsigned DstReg, O.setReg(UseDstReg); O.setSubReg(0); + if (OldSubIdx) { + // Def and kill of subregister of a virtual register actually defs and + // kills the whole register. Add imp-defs and imp-kills as needed. + if (O.isDef()) { + if(O.isDead()) + UseMI->addRegisterDead(DstReg, tri_, true); + else + UseMI->addRegisterDefined(DstReg, tri_); + } else if (!O.isUndef() && + (O.isKill() || + UseMI->isRegTiedToDefOperand(&O-&UseMI->getOperand(0)))) + UseMI->addRegisterKilled(DstReg, tri_, true); + } continue; } @@ -1029,8 +1054,9 @@ SimpleRegisterCoalescing::isWinToJoinVRWithSrcPhysReg(MachineInstr *CopyMI, unsigned Threshold = allocatableRCRegs_[RC].count() * 2; unsigned Length = li_->getApproximateInstructionCount(DstInt); if (Length > Threshold && - (((float)std::distance(mri_->use_begin(DstInt.reg), - mri_->use_end()) / Length) < (1.0 / Threshold))) + (((float)std::distance(mri_->use_nodbg_begin(DstInt.reg), + mri_->use_nodbg_end()) / Length) < + (1.0 / Threshold))) return false; // If the virtual register live interval extends into a loop, turn down @@ -1079,15 +1105,16 @@ SimpleRegisterCoalescing::isWinToJoinVRWithDstPhysReg(MachineInstr *CopyMI, MachineBasicBlock *CopyMBB, LiveInterval &DstInt, LiveInterval &SrcInt) { - // If the virtual register live interval is long but it has low use desity, + // If the virtual register live interval is long but it has low use density, // do not join them, instead mark the physical register as its allocation // preference. const TargetRegisterClass *RC = mri_->getRegClass(SrcInt.reg); unsigned Threshold = allocatableRCRegs_[RC].count() * 2; unsigned Length = li_->getApproximateInstructionCount(SrcInt); if (Length > Threshold && - (((float)std::distance(mri_->use_begin(SrcInt.reg), - mri_->use_end()) / Length) < (1.0 / Threshold))) + (((float)std::distance(mri_->use_nodbg_begin(SrcInt.reg), + mri_->use_nodbg_end()) / Length) < + (1.0 / Threshold))) return false; if (SrcInt.empty()) @@ -1139,12 +1166,14 @@ SimpleRegisterCoalescing::isWinToJoinCrossClass(unsigned LargeReg, LiveInterval &SmallInt = li_->getInterval(SmallReg); unsigned LargeSize = li_->getApproximateInstructionCount(LargeInt); unsigned SmallSize = li_->getApproximateInstructionCount(SmallInt); - if (SmallSize > Threshold || LargeSize > Threshold) - if ((float)std::distance(mri_->use_begin(SmallReg), - mri_->use_end()) / SmallSize < - (float)std::distance(mri_->use_begin(LargeReg), - mri_->use_end()) / LargeSize) + if (LargeSize > Threshold) { + unsigned SmallUses = std::distance(mri_->use_nodbg_begin(SmallReg), + mri_->use_nodbg_end()); + unsigned LargeUses = std::distance(mri_->use_nodbg_begin(LargeReg), + mri_->use_nodbg_end()); + if (SmallUses*LargeSize < LargeUses*SmallSize) return false; + } return true; } @@ -1164,13 +1193,15 @@ SimpleRegisterCoalescing::HasIncompatibleSubRegDefUse(MachineInstr *CopyMI, for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(VirtReg), E = mri_->reg_end(); I != E; ++I) { MachineOperand &O = I.getOperand(); + if (O.isDebug()) + continue; MachineInstr *MI = &*I; if (MI == CopyMI || JoinedCopies.count(MI)) continue; unsigned SubIdx = O.getSubReg(); if (SubIdx && !tri_->getSubReg(PhysReg, SubIdx)) return true; - if (MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) { + if (MI->isExtractSubreg()) { SubIdx = MI->getOperand(2).getImm(); if (O.isUse() && !tri_->getSubReg(PhysReg, SubIdx)) return true; @@ -1184,8 +1215,7 @@ SimpleRegisterCoalescing::HasIncompatibleSubRegDefUse(MachineInstr *CopyMI, return true; } } - if (MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG || - MI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG) { + if (MI->isInsertSubreg() || MI->isSubregToReg()) { SubIdx = MI->getOperand(3).getImm(); if (VirtReg == MI->getOperand(0).getReg()) { if (!tri_->getSubReg(PhysReg, SubIdx)) @@ -1296,9 +1326,9 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { DEBUG(dbgs() << li_->getInstructionIndex(CopyMI) << '\t' << *CopyMI); unsigned SrcReg, DstReg, SrcSubIdx = 0, DstSubIdx = 0; - bool isExtSubReg = CopyMI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG; - bool isInsSubReg = CopyMI->getOpcode() == TargetInstrInfo::INSERT_SUBREG; - bool isSubRegToReg = CopyMI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG; + bool isExtSubReg = CopyMI->isExtractSubreg(); + bool isInsSubReg = CopyMI->isInsertSubreg(); + bool isSubRegToReg = CopyMI->isSubregToReg(); unsigned SubIdx = 0; if (isExtSubReg) { DstReg = CopyMI->getOperand(0).getReg(); @@ -1551,7 +1581,10 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { (isExtSubReg || DstRC->isASubClass()) && !isWinToJoinCrossClass(LargeReg, SmallReg, allocatableRCRegs_[NewRC].count())) { - DEBUG(dbgs() << "\tSrc/Dest are different register classes.\n"); + DEBUG(dbgs() << "\tSrc/Dest are different register classes: " + << SrcRC->getName() << "/" + << DstRC->getName() << " -> " + << NewRC->getName() << ".\n"); // Allow the coalescer to try again in case either side gets coalesced to // a physical register that's compatible with the other side. e.g. // r1024 = MOV32to32_ r1025 @@ -1631,8 +1664,8 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { unsigned Length = li_->getApproximateInstructionCount(JoinVInt); float Ratio = 1.0 / Threshold; if (Length > Threshold && - (((float)std::distance(mri_->use_begin(JoinVReg), - mri_->use_end()) / Length) < Ratio)) { + (((float)std::distance(mri_->use_nodbg_begin(JoinVReg), + mri_->use_nodbg_end()) / Length) < Ratio)) { mri_->setRegAllocationHint(JoinVInt.reg, 0, JoinPReg); ++numAborts; DEBUG(dbgs() << "\tMay tie down a physical register, abort!\n"); @@ -1755,6 +1788,23 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { UpdateRegDefsUses(SrcReg, DstReg, SubIdx); + // If we have extended the live range of a physical register, make sure we + // update live-in lists as well. + if (TargetRegisterInfo::isPhysicalRegister(DstReg)) { + const LiveInterval &VRegInterval = li_->getInterval(SrcReg); + SmallVector<MachineBasicBlock*, 16> BlockSeq; + for (LiveInterval::const_iterator I = VRegInterval.begin(), + E = VRegInterval.end(); I != E; ++I ) { + li_->findLiveInMBBs(I->start, I->end, BlockSeq); + for (unsigned idx = 0, size = BlockSeq.size(); idx != size; ++idx) { + MachineBasicBlock &block = *BlockSeq[idx]; + if (!block.isLiveIn(DstReg)) + block.addLiveIn(DstReg); + } + BlockSeq.clear(); + } + } + // SrcReg is guarateed to be the register whose live interval that is // being merged. li_->removeInterval(SrcReg); @@ -1849,11 +1899,11 @@ static bool isValNoDefMove(const MachineInstr *MI, unsigned DR, unsigned SR, unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; if (TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx)) ; - else if (MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) { + else if (MI->isExtractSubreg()) { DstReg = MI->getOperand(0).getReg(); SrcReg = MI->getOperand(1).getReg(); - } else if (MI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG || - MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG) { + } else if (MI->isSubregToReg() || + MI->isInsertSubreg()) { DstReg = MI->getOperand(0).getReg(); SrcReg = MI->getOperand(2).getReg(); } else @@ -2425,16 +2475,15 @@ void SimpleRegisterCoalescing::CopyCoalesceInMBB(MachineBasicBlock *MBB, // If this isn't a copy nor a extract_subreg, we can't join intervals. unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; bool isInsUndef = false; - if (Inst->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) { + if (Inst->isExtractSubreg()) { DstReg = Inst->getOperand(0).getReg(); SrcReg = Inst->getOperand(1).getReg(); - } else if (Inst->getOpcode() == TargetInstrInfo::INSERT_SUBREG) { + } else if (Inst->isInsertSubreg()) { DstReg = Inst->getOperand(0).getReg(); SrcReg = Inst->getOperand(2).getReg(); if (Inst->getOperand(1).isUndef()) isInsUndef = true; - } else if (Inst->getOpcode() == TargetInstrInfo::INSERT_SUBREG || - Inst->getOpcode() == TargetInstrInfo::SUBREG_TO_REG) { + } else if (Inst->isInsertSubreg() || Inst->isSubregToReg()) { DstReg = Inst->getOperand(0).getReg(); SrcReg = Inst->getOperand(2).getReg(); } else if (!tii_->isMoveInstr(*Inst, SrcReg, DstReg, SrcSubIdx, DstSubIdx)) @@ -2549,8 +2598,8 @@ SimpleRegisterCoalescing::differingRegisterClasses(unsigned RegA, return !RegClassA->contains(RegB); } -/// lastRegisterUse - Returns the last use of the specific register between -/// cycles Start and End or NULL if there are no uses. +/// lastRegisterUse - Returns the last (non-debug) use of the specific register +/// between cycles Start and End or NULL if there are no uses. MachineOperand * SimpleRegisterCoalescing::lastRegisterUse(SlotIndex Start, SlotIndex End, @@ -2559,8 +2608,8 @@ SimpleRegisterCoalescing::lastRegisterUse(SlotIndex Start, UseIdx = SlotIndex(); if (TargetRegisterInfo::isVirtualRegister(Reg)) { MachineOperand *LastUse = NULL; - for (MachineRegisterInfo::use_iterator I = mri_->use_begin(Reg), - E = mri_->use_end(); I != E; ++I) { + for (MachineRegisterInfo::use_nodbg_iterator I = mri_->use_nodbg_begin(Reg), + E = mri_->use_nodbg_end(); I != E; ++I) { MachineOperand &Use = I.getOperand(); MachineInstr *UseMI = Use.getParent(); unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; @@ -2670,10 +2719,8 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { // Delete all coalesced copies. bool DoDelete = true; if (!tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx)) { - assert((MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG || - MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG || - MI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG) && - "Unrecognized copy instruction"); + assert((MI->isExtractSubreg() || MI->isInsertSubreg() || + MI->isSubregToReg()) && "Unrecognized copy instruction"); DstReg = MI->getOperand(0).getReg(); if (TargetRegisterInfo::isPhysicalRegister(DstReg)) // Do not delete extract_subreg, insert_subreg of physical diff --git a/lib/CodeGen/SjLjEHPrepare.cpp b/lib/CodeGen/SjLjEHPrepare.cpp index 9558933..8d4d1b2 100644 --- a/lib/CodeGen/SjLjEHPrepare.cpp +++ b/lib/CodeGen/SjLjEHPrepare.cpp @@ -51,6 +51,7 @@ namespace { Value *PersonalityFn; Constant *SelectorFn; Constant *ExceptionFn; + Constant *CallSiteFn; Value *CallSite; public: @@ -116,6 +117,7 @@ bool SjLjEHPass::doInitialization(Module &M) { LSDAAddrFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_lsda); SelectorFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_selector); ExceptionFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_exception); + CallSiteFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_callsite); PersonalityFn = 0; return true; @@ -143,15 +145,14 @@ void SjLjEHPass::markInvokeCallSite(InvokeInst *II, unsigned InvokeNo, } } - // Insert a store of the invoke num before the invoke and store zero into the - // location afterward. + // Insert a store of the invoke num before the invoke new StoreInst(CallSiteNoC, CallSite, true, II); // volatile + CallInst::Create(CallSiteFn, CallSiteNoC, "", II); // Add a switch case to our unwind block. CatchSwitch->addCase(SwitchValC, II->getUnwindDest()); - // We still want this to look like an invoke so we emit the LSDA properly - // FIXME: ??? Or will this cause strangeness with mis-matched IDs like - // when it was in the front end? + // We still want this to look like an invoke so we emit the LSDA properly, + // so we don't transform the invoke into a call here. } /// MarkBlocksLiveIn - Insert BB and all of its predescessors into LiveBBs until diff --git a/lib/CodeGen/SlotIndexes.cpp b/lib/CodeGen/SlotIndexes.cpp index a23efb2..6110ef5 100644 --- a/lib/CodeGen/SlotIndexes.cpp +++ b/lib/CodeGen/SlotIndexes.cpp @@ -95,7 +95,7 @@ bool SlotIndexes::runOnMachineFunction(MachineFunction &fn) { push_back(createEntry(0, index)); - // Iterate over the the function. + // Iterate over the function. for (MachineFunction::iterator mbbItr = mf->begin(), mbbEnd = mf->end(); mbbItr != mbbEnd; ++mbbItr) { MachineBasicBlock *mbb = &*mbbItr; @@ -107,8 +107,8 @@ bool SlotIndexes::runOnMachineFunction(MachineFunction &fn) { for (MachineBasicBlock::iterator miItr = mbb->begin(), miEnd = mbb->end(); miItr != miEnd; ++miItr) { - MachineInstr *mi = &*miItr; - if (mi->getOpcode()==TargetInstrInfo::DEBUG_VALUE) + MachineInstr *mi = miItr; + if (mi->isDebugValue()) continue; if (miItr == mbb->getFirstTerminator()) { diff --git a/lib/CodeGen/StackProtector.cpp b/lib/CodeGen/StackProtector.cpp index 48bb5af..8a6a727 100644 --- a/lib/CodeGen/StackProtector.cpp +++ b/lib/CodeGen/StackProtector.cpp @@ -113,7 +113,7 @@ bool StackProtector::RequiresStackProtector() const { if (const ArrayType *AT = dyn_cast<ArrayType>(AI->getAllocatedType())) { // We apparently only care about character arrays. - if (!AT->getElementType()->isInteger(8)) + if (!AT->getElementType()->isIntegerTy(8)) continue; // If an array has more than SSPBufferSize bytes of allocated space, diff --git a/lib/CodeGen/StackSlotColoring.cpp b/lib/CodeGen/StackSlotColoring.cpp index 2170703..12d38f0 100644 --- a/lib/CodeGen/StackSlotColoring.cpp +++ b/lib/CodeGen/StackSlotColoring.cpp @@ -504,10 +504,8 @@ bool StackSlotColoring::PropagateBackward(MachineBasicBlock::iterator MII, // Abort the use is actually a sub-register def. We don't have enough // information to figure out if it is really legal. - if (MO.getSubReg() || - TID.getOpcode() == TargetInstrInfo::EXTRACT_SUBREG || - TID.getOpcode() == TargetInstrInfo::INSERT_SUBREG || - TID.getOpcode() == TargetInstrInfo::SUBREG_TO_REG) + if (MO.getSubReg() || MII->isExtractSubreg() || + MII->isInsertSubreg() || MII->isSubregToReg()) return false; const TargetRegisterClass *RC = TID.OpInfo[i].getRegClass(TRI); @@ -569,8 +567,7 @@ bool StackSlotColoring::PropagateForward(MachineBasicBlock::iterator MII, // Abort the use is actually a sub-register use. We don't have enough // information to figure out if it is really legal. - if (MO.getSubReg() || - TID.getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) + if (MO.getSubReg() || MII->isExtractSubreg()) return false; const TargetRegisterClass *RC = TID.OpInfo[i].getRegClass(TRI); diff --git a/lib/CodeGen/StrongPHIElimination.cpp b/lib/CodeGen/StrongPHIElimination.cpp index bd7cb75..f8f6a55 100644 --- a/lib/CodeGen/StrongPHIElimination.cpp +++ b/lib/CodeGen/StrongPHIElimination.cpp @@ -49,7 +49,7 @@ namespace { std::map<unsigned, std::vector<unsigned> > Stacks; // Registers in UsedByAnother are PHI nodes that are themselves - // used as operands to another another PHI node + // used as operands to another PHI node std::set<unsigned> UsedByAnother; // RenameSets are the is a map from a PHI-defined register @@ -419,7 +419,7 @@ void StrongPHIElimination::processBlock(MachineBasicBlock* MBB) { // Iterate over all the PHI nodes in this block MachineBasicBlock::iterator P = MBB->begin(); - while (P != MBB->end() && P->getOpcode() == TargetInstrInfo::PHI) { + while (P != MBB->end() && P->isPHI()) { unsigned DestReg = P->getOperand(0).getReg(); // Don't both doing PHI elimination for dead PHI's. @@ -452,7 +452,7 @@ void StrongPHIElimination::processBlock(MachineBasicBlock* MBB) { // We don't need to insert copies for implicit_defs. MachineInstr* DefMI = MRI.getVRegDef(SrcReg); - if (DefMI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) + if (DefMI->isImplicitDef()) ProcessedNames.insert(SrcReg); // Check for trivial interferences via liveness information, allowing us @@ -470,7 +470,7 @@ void StrongPHIElimination::processBlock(MachineBasicBlock* MBB) { if (isLiveIn(SrcReg, P->getParent(), LI) || isLiveOut(P->getOperand(0).getReg(), MRI.getVRegDef(SrcReg)->getParent(), LI) || - ( MRI.getVRegDef(SrcReg)->getOpcode() == TargetInstrInfo::PHI && + ( MRI.getVRegDef(SrcReg)->isPHI() && isLiveIn(P->getOperand(0).getReg(), MRI.getVRegDef(SrcReg)->getParent(), LI) ) || ProcessedNames.count(SrcReg) || @@ -810,7 +810,7 @@ void StrongPHIElimination::InsertCopies(MachineDomTreeNode* MDTN, // Rewrite register uses from Stacks for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; ++I) { - if (I->getOpcode() == TargetInstrInfo::PHI) + if (I->isPHI()) continue; for (unsigned i = 0; i < I->getNumOperands(); ++i) @@ -907,8 +907,7 @@ bool StrongPHIElimination::runOnMachineFunction(MachineFunction &Fn) { // Determine which phi node operands need copies for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) - if (!I->empty() && - I->begin()->getOpcode() == TargetInstrInfo::PHI) + if (!I->empty() && I->begin()->isPHI()) processBlock(I); // Break interferences where two different phis want to coalesce @@ -996,7 +995,7 @@ bool StrongPHIElimination::runOnMachineFunction(MachineFunction &Fn) { for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) { for (MachineBasicBlock::iterator BI = I->begin(), BE = I->end(); BI != BE; ++BI) - if (BI->getOpcode() == TargetInstrInfo::PHI) + if (BI->isPHI()) phis.push_back(BI); } diff --git a/lib/CodeGen/TailDuplication.cpp b/lib/CodeGen/TailDuplication.cpp index d6860bc..3223e53 100644 --- a/lib/CodeGen/TailDuplication.cpp +++ b/lib/CodeGen/TailDuplication.cpp @@ -121,7 +121,7 @@ static void VerifyPHIs(MachineFunction &MF, bool CheckExtra) { MBB->pred_end()); MachineBasicBlock::iterator MI = MBB->begin(); while (MI != MBB->end()) { - if (MI->getOpcode() != TargetInstrInfo::PHI) + if (!MI->isPHI()) break; for (SmallSetVector<MachineBasicBlock *, 8>::iterator PI = Preds.begin(), PE = Preds.end(); PI != PE; ++PI) { @@ -378,7 +378,7 @@ TailDuplicatePass::UpdateSuccessorsPHIs(MachineBasicBlock *FromBB, bool isDead, MachineBasicBlock *SuccBB = *SI; for (MachineBasicBlock::iterator II = SuccBB->begin(), EE = SuccBB->end(); II != EE; ++II) { - if (II->getOpcode() != TargetInstrInfo::PHI) + if (!II->isPHI()) break; unsigned Idx = 0; for (unsigned i = 1, e = II->getNumOperands(); i != e; i += 2) { @@ -403,26 +403,45 @@ TailDuplicatePass::UpdateSuccessorsPHIs(MachineBasicBlock *FromBB, bool isDead, II->RemoveOperand(i); } } - II->RemoveOperand(Idx+1); - II->RemoveOperand(Idx); - } + } else + Idx = 0; + + // If Idx is set, the operands at Idx and Idx+1 must be removed. + // We reuse the location to avoid expensive RemoveOperand calls. + DenseMap<unsigned,AvailableValsTy>::iterator LI=SSAUpdateVals.find(Reg); if (LI != SSAUpdateVals.end()) { // This register is defined in the tail block. for (unsigned j = 0, ee = LI->second.size(); j != ee; ++j) { MachineBasicBlock *SrcBB = LI->second[j].first; unsigned SrcReg = LI->second[j].second; - II->addOperand(MachineOperand::CreateReg(SrcReg, false)); - II->addOperand(MachineOperand::CreateMBB(SrcBB)); + if (Idx != 0) { + II->getOperand(Idx).setReg(SrcReg); + II->getOperand(Idx+1).setMBB(SrcBB); + Idx = 0; + } else { + II->addOperand(MachineOperand::CreateReg(SrcReg, false)); + II->addOperand(MachineOperand::CreateMBB(SrcBB)); + } } } else { // Live in tail block, must also be live in predecessors. for (unsigned j = 0, ee = TDBBs.size(); j != ee; ++j) { MachineBasicBlock *SrcBB = TDBBs[j]; - II->addOperand(MachineOperand::CreateReg(Reg, false)); - II->addOperand(MachineOperand::CreateMBB(SrcBB)); + if (Idx != 0) { + II->getOperand(Idx).setReg(Reg); + II->getOperand(Idx+1).setMBB(SrcBB); + Idx = 0; + } else { + II->addOperand(MachineOperand::CreateReg(Reg, false)); + II->addOperand(MachineOperand::CreateMBB(SrcBB)); + } } } + if (Idx != 0) { + II->RemoveOperand(Idx+1); + II->RemoveOperand(Idx); + } } } } @@ -476,7 +495,7 @@ TailDuplicatePass::TailDuplicate(MachineBasicBlock *TailBB, MachineFunction &MF, if (InstrCount == MaxDuplicateCount) return false; // Remember if we saw a call. if (I->getDesc().isCall()) HasCall = true; - if (I->getOpcode() != TargetInstrInfo::PHI) + if (!I->isPHI()) InstrCount += 1; } // Heuristically, don't tail-duplicate calls if it would expand code size, @@ -528,7 +547,7 @@ TailDuplicatePass::TailDuplicate(MachineBasicBlock *TailBB, MachineFunction &MF, while (I != TailBB->end()) { MachineInstr *MI = &*I; ++I; - if (MI->getOpcode() == TargetInstrInfo::PHI) { + if (MI->isPHI()) { // Replace the uses of the def of the PHI with the register coming // from PredBB. ProcessPHI(MI, TailBB, PredBB, LocalVRMap, CopyInfos); @@ -580,7 +599,7 @@ TailDuplicatePass::TailDuplicate(MachineBasicBlock *TailBB, MachineFunction &MF, SmallVector<std::pair<unsigned,unsigned>, 4> CopyInfos; MachineBasicBlock::iterator I = TailBB->begin(); // Process PHI instructions first. - while (I != TailBB->end() && I->getOpcode() == TargetInstrInfo::PHI) { + while (I != TailBB->end() && I->isPHI()) { // Replace the uses of the def of the PHI with the register coming // from PredBB. MachineInstr *MI = &*I++; diff --git a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp new file mode 100644 index 0000000..190b533 --- /dev/null +++ b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -0,0 +1,874 @@ +//===-- llvm/CodeGen/TargetLoweringObjectFileImpl.cpp - Object File Info --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements classes used to handle lowerings specific to common +// object file formats. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// ELF +//===----------------------------------------------------------------------===// +typedef StringMap<const MCSectionELF*> ELFUniqueMapTy; + +TargetLoweringObjectFileELF::~TargetLoweringObjectFileELF() { + // If we have the section uniquing map, free it. + delete (ELFUniqueMapTy*)UniquingMap; +} + +const MCSection *TargetLoweringObjectFileELF:: +getELFSection(StringRef Section, unsigned Type, unsigned Flags, + SectionKind Kind, bool IsExplicit) const { + if (UniquingMap == 0) + UniquingMap = new ELFUniqueMapTy(); + ELFUniqueMapTy &Map = *(ELFUniqueMapTy*)UniquingMap; + + // Do the lookup, if we have a hit, return it. + const MCSectionELF *&Entry = Map[Section]; + if (Entry) return Entry; + + return Entry = MCSectionELF::Create(Section, Type, Flags, Kind, IsExplicit, + getContext()); +} + +void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx, + const TargetMachine &TM) { + if (UniquingMap != 0) + ((ELFUniqueMapTy*)UniquingMap)->clear(); + TargetLoweringObjectFile::Initialize(Ctx, TM); + + BSSSection = + getELFSection(".bss", MCSectionELF::SHT_NOBITS, + MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, + SectionKind::getBSS()); + + TextSection = + getELFSection(".text", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_EXECINSTR | MCSectionELF::SHF_ALLOC, + SectionKind::getText()); + + DataSection = + getELFSection(".data", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, + SectionKind::getDataRel()); + + ReadOnlySection = + getELFSection(".rodata", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC, + SectionKind::getReadOnly()); + + TLSDataSection = + getELFSection(".tdata", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_TLS | + MCSectionELF::SHF_WRITE, SectionKind::getThreadData()); + + TLSBSSSection = + getELFSection(".tbss", MCSectionELF::SHT_NOBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_TLS | + MCSectionELF::SHF_WRITE, SectionKind::getThreadBSS()); + + DataRelSection = + getELFSection(".data.rel", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRel()); + + DataRelLocalSection = + getELFSection(".data.rel.local", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRelLocal()); + + DataRelROSection = + getELFSection(".data.rel.ro", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getReadOnlyWithRel()); + + DataRelROLocalSection = + getELFSection(".data.rel.ro.local", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getReadOnlyWithRelLocal()); + + MergeableConst4Section = + getELFSection(".rodata.cst4", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_MERGE, + SectionKind::getMergeableConst4()); + + MergeableConst8Section = + getELFSection(".rodata.cst8", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_MERGE, + SectionKind::getMergeableConst8()); + + MergeableConst16Section = + getELFSection(".rodata.cst16", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_MERGE, + SectionKind::getMergeableConst16()); + + StaticCtorSection = + getELFSection(".ctors", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRel()); + + StaticDtorSection = + getELFSection(".dtors", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRel()); + + // Exception Handling Sections. + + // FIXME: We're emitting LSDA info into a readonly section on ELF, even though + // it contains relocatable pointers. In PIC mode, this is probably a big + // runtime hit for C++ apps. Either the contents of the LSDA need to be + // adjusted or this should be a data section. + LSDASection = + getELFSection(".gcc_except_table", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC, SectionKind::getReadOnly()); + EHFrameSection = + getELFSection(".eh_frame", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRel()); + + // Debug Info Sections. + DwarfAbbrevSection = + getELFSection(".debug_abbrev", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfInfoSection = + getELFSection(".debug_info", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfLineSection = + getELFSection(".debug_line", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfFrameSection = + getELFSection(".debug_frame", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfPubNamesSection = + getELFSection(".debug_pubnames", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfPubTypesSection = + getELFSection(".debug_pubtypes", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfStrSection = + getELFSection(".debug_str", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfLocSection = + getELFSection(".debug_loc", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfARangesSection = + getELFSection(".debug_aranges", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfRangesSection = + getELFSection(".debug_ranges", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfMacroInfoSection = + getELFSection(".debug_macinfo", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); +} + + +static SectionKind +getELFKindForNamedSection(StringRef Name, SectionKind K) { + if (Name.empty() || Name[0] != '.') return K; + + // Some lame default implementation based on some magic section names. + if (Name == ".bss" || + Name.startswith(".bss.") || + Name.startswith(".gnu.linkonce.b.") || + Name.startswith(".llvm.linkonce.b.") || + Name == ".sbss" || + Name.startswith(".sbss.") || + Name.startswith(".gnu.linkonce.sb.") || + Name.startswith(".llvm.linkonce.sb.")) + return SectionKind::getBSS(); + + if (Name == ".tdata" || + Name.startswith(".tdata.") || + Name.startswith(".gnu.linkonce.td.") || + Name.startswith(".llvm.linkonce.td.")) + return SectionKind::getThreadData(); + + if (Name == ".tbss" || + Name.startswith(".tbss.") || + Name.startswith(".gnu.linkonce.tb.") || + Name.startswith(".llvm.linkonce.tb.")) + return SectionKind::getThreadBSS(); + + return K; +} + + +static unsigned getELFSectionType(StringRef Name, SectionKind K) { + + if (Name == ".init_array") + return MCSectionELF::SHT_INIT_ARRAY; + + if (Name == ".fini_array") + return MCSectionELF::SHT_FINI_ARRAY; + + if (Name == ".preinit_array") + return MCSectionELF::SHT_PREINIT_ARRAY; + + if (K.isBSS() || K.isThreadBSS()) + return MCSectionELF::SHT_NOBITS; + + return MCSectionELF::SHT_PROGBITS; +} + + +static unsigned +getELFSectionFlags(SectionKind K) { + unsigned Flags = 0; + + if (!K.isMetadata()) + Flags |= MCSectionELF::SHF_ALLOC; + + if (K.isText()) + Flags |= MCSectionELF::SHF_EXECINSTR; + + if (K.isWriteable()) + Flags |= MCSectionELF::SHF_WRITE; + + if (K.isThreadLocal()) + Flags |= MCSectionELF::SHF_TLS; + + // K.isMergeableConst() is left out to honour PR4650 + if (K.isMergeableCString() || K.isMergeableConst4() || + K.isMergeableConst8() || K.isMergeableConst16()) + Flags |= MCSectionELF::SHF_MERGE; + + if (K.isMergeableCString()) + Flags |= MCSectionELF::SHF_STRINGS; + + return Flags; +} + + +const MCSection *TargetLoweringObjectFileELF:: +getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + StringRef SectionName = GV->getSection(); + + // Infer section flags from the section name if we can. + Kind = getELFKindForNamedSection(SectionName, Kind); + + return getELFSection(SectionName, + getELFSectionType(SectionName, Kind), + getELFSectionFlags(Kind), Kind, true); +} + +static const char *getSectionPrefixForUniqueGlobal(SectionKind Kind) { + if (Kind.isText()) return ".gnu.linkonce.t."; + if (Kind.isReadOnly()) return ".gnu.linkonce.r."; + + if (Kind.isThreadData()) return ".gnu.linkonce.td."; + if (Kind.isThreadBSS()) return ".gnu.linkonce.tb."; + + if (Kind.isDataNoRel()) return ".gnu.linkonce.d."; + if (Kind.isDataRelLocal()) return ".gnu.linkonce.d.rel.local."; + if (Kind.isDataRel()) return ".gnu.linkonce.d.rel."; + if (Kind.isReadOnlyWithRelLocal()) return ".gnu.linkonce.d.rel.ro.local."; + + assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); + return ".gnu.linkonce.d.rel.ro."; +} + +const MCSection *TargetLoweringObjectFileELF:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + + // If this global is linkonce/weak and the target handles this by emitting it + // into a 'uniqued' section name, create and return the section now. + if (GV->isWeakForLinker() && !Kind.isCommon() && !Kind.isBSS()) { + const char *Prefix = getSectionPrefixForUniqueGlobal(Kind); + SmallString<128> Name; + Name.append(Prefix, Prefix+strlen(Prefix)); + Mang->getNameWithPrefix(Name, GV, false); + return getELFSection(Name.str(), getELFSectionType(Name.str(), Kind), + getELFSectionFlags(Kind), Kind); + } + + if (Kind.isText()) return TextSection; + + if (Kind.isMergeable1ByteCString() || + Kind.isMergeable2ByteCString() || + Kind.isMergeable4ByteCString()) { + + // We also need alignment here. + // FIXME: this is getting the alignment of the character, not the + // alignment of the global! + unsigned Align = + TM.getTargetData()->getPreferredAlignment(cast<GlobalVariable>(GV)); + + const char *SizeSpec = ".rodata.str1."; + if (Kind.isMergeable2ByteCString()) + SizeSpec = ".rodata.str2."; + else if (Kind.isMergeable4ByteCString()) + SizeSpec = ".rodata.str4."; + else + assert(Kind.isMergeable1ByteCString() && "unknown string width"); + + + std::string Name = SizeSpec + utostr(Align); + return getELFSection(Name, MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | + MCSectionELF::SHF_MERGE | + MCSectionELF::SHF_STRINGS, + Kind); + } + + if (Kind.isMergeableConst()) { + if (Kind.isMergeableConst4() && MergeableConst4Section) + return MergeableConst4Section; + if (Kind.isMergeableConst8() && MergeableConst8Section) + return MergeableConst8Section; + if (Kind.isMergeableConst16() && MergeableConst16Section) + return MergeableConst16Section; + return ReadOnlySection; // .const + } + + if (Kind.isReadOnly()) return ReadOnlySection; + + if (Kind.isThreadData()) return TLSDataSection; + if (Kind.isThreadBSS()) return TLSBSSSection; + + // Note: we claim that common symbols are put in BSSSection, but they are + // really emitted with the magic .comm directive, which creates a symbol table + // entry but not a section. + if (Kind.isBSS() || Kind.isCommon()) return BSSSection; + + if (Kind.isDataNoRel()) return DataSection; + if (Kind.isDataRelLocal()) return DataRelLocalSection; + if (Kind.isDataRel()) return DataRelSection; + if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection; + + assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); + return DataRelROSection; +} + +/// getSectionForConstant - Given a mergeable constant with the +/// specified size and relocation information, return a section that it +/// should be placed in. +const MCSection *TargetLoweringObjectFileELF:: +getSectionForConstant(SectionKind Kind) const { + if (Kind.isMergeableConst4() && MergeableConst4Section) + return MergeableConst4Section; + if (Kind.isMergeableConst8() && MergeableConst8Section) + return MergeableConst8Section; + if (Kind.isMergeableConst16() && MergeableConst16Section) + return MergeableConst16Section; + if (Kind.isReadOnly()) + return ReadOnlySection; + + if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection; + assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); + return DataRelROSection; +} + +const MCExpr *TargetLoweringObjectFileELF:: +getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, unsigned Encoding) const { + + if (Encoding & dwarf::DW_EH_PE_indirect) { + MachineModuleInfoELF &ELFMMI = MMI->getObjFileInfo<MachineModuleInfoELF>(); + + SmallString<128> Name; + Mang->getNameWithPrefix(Name, GV, true); + Name += ".DW.stub"; + + // Add information about the stub reference to ELFMMI so that the stub + // gets emitted by the asmprinter. + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name.str()); + MCSymbol *&StubSym = ELFMMI.getGVStubEntry(Sym); + if (StubSym == 0) { + Name.clear(); + Mang->getNameWithPrefix(Name, GV, false); + StubSym = getContext().GetOrCreateSymbol(Name.str()); + } + + return TargetLoweringObjectFile:: + getSymbolForDwarfReference(Sym, MMI, + Encoding & ~dwarf::DW_EH_PE_indirect); + } + + return TargetLoweringObjectFile:: + getSymbolForDwarfGlobalReference(GV, Mang, MMI, Encoding); +} + +//===----------------------------------------------------------------------===// +// MachO +//===----------------------------------------------------------------------===// + +typedef StringMap<const MCSectionMachO*> MachOUniqueMapTy; + +TargetLoweringObjectFileMachO::~TargetLoweringObjectFileMachO() { + // If we have the MachO uniquing map, free it. + delete (MachOUniqueMapTy*)UniquingMap; +} + + +const MCSectionMachO *TargetLoweringObjectFileMachO:: +getMachOSection(StringRef Segment, StringRef Section, + unsigned TypeAndAttributes, + unsigned Reserved2, SectionKind Kind) const { + // We unique sections by their segment/section pair. The returned section + // may not have the same flags as the requested section, if so this should be + // diagnosed by the client as an error. + + // Create the map if it doesn't already exist. + if (UniquingMap == 0) + UniquingMap = new MachOUniqueMapTy(); + MachOUniqueMapTy &Map = *(MachOUniqueMapTy*)UniquingMap; + + // Form the name to look up. + SmallString<64> Name; + Name += Segment; + Name.push_back(','); + Name += Section; + + // Do the lookup, if we have a hit, return it. + const MCSectionMachO *&Entry = Map[Name.str()]; + if (Entry) return Entry; + + // Otherwise, return a new section. + return Entry = MCSectionMachO::Create(Segment, Section, TypeAndAttributes, + Reserved2, Kind, getContext()); +} + + +void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx, + const TargetMachine &TM) { + if (UniquingMap != 0) + ((MachOUniqueMapTy*)UniquingMap)->clear(); + TargetLoweringObjectFile::Initialize(Ctx, TM); + + TextSection // .text + = getMachOSection("__TEXT", "__text", + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + SectionKind::getText()); + DataSection // .data + = getMachOSection("__DATA", "__data", 0, SectionKind::getDataRel()); + + CStringSection // .cstring + = getMachOSection("__TEXT", "__cstring", MCSectionMachO::S_CSTRING_LITERALS, + SectionKind::getMergeable1ByteCString()); + UStringSection + = getMachOSection("__TEXT","__ustring", 0, + SectionKind::getMergeable2ByteCString()); + FourByteConstantSection // .literal4 + = getMachOSection("__TEXT", "__literal4", MCSectionMachO::S_4BYTE_LITERALS, + SectionKind::getMergeableConst4()); + EightByteConstantSection // .literal8 + = getMachOSection("__TEXT", "__literal8", MCSectionMachO::S_8BYTE_LITERALS, + SectionKind::getMergeableConst8()); + + // ld_classic doesn't support .literal16 in 32-bit mode, and ld64 falls back + // to using it in -static mode. + SixteenByteConstantSection = 0; + if (TM.getRelocationModel() != Reloc::Static && + TM.getTargetData()->getPointerSize() == 32) + SixteenByteConstantSection = // .literal16 + getMachOSection("__TEXT", "__literal16",MCSectionMachO::S_16BYTE_LITERALS, + SectionKind::getMergeableConst16()); + + ReadOnlySection // .const + = getMachOSection("__TEXT", "__const", 0, SectionKind::getReadOnly()); + + TextCoalSection + = getMachOSection("__TEXT", "__textcoal_nt", + MCSectionMachO::S_COALESCED | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + SectionKind::getText()); + ConstTextCoalSection + = getMachOSection("__TEXT", "__const_coal", MCSectionMachO::S_COALESCED, + SectionKind::getText()); + ConstDataCoalSection + = getMachOSection("__DATA","__const_coal", MCSectionMachO::S_COALESCED, + SectionKind::getText()); + ConstDataSection // .const_data + = getMachOSection("__DATA", "__const", 0, + SectionKind::getReadOnlyWithRel()); + DataCoalSection + = getMachOSection("__DATA","__datacoal_nt", MCSectionMachO::S_COALESCED, + SectionKind::getDataRel()); + DataCommonSection + = getMachOSection("__DATA","__common", MCSectionMachO::S_ZEROFILL, + SectionKind::getBSS()); + DataBSSSection + = getMachOSection("__DATA","__bss", MCSectionMachO::S_ZEROFILL, + SectionKind::getBSS()); + + + LazySymbolPointerSection + = getMachOSection("__DATA", "__la_symbol_ptr", + MCSectionMachO::S_LAZY_SYMBOL_POINTERS, + SectionKind::getMetadata()); + NonLazySymbolPointerSection + = getMachOSection("__DATA", "__nl_symbol_ptr", + MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, + SectionKind::getMetadata()); + + if (TM.getRelocationModel() == Reloc::Static) { + StaticCtorSection + = getMachOSection("__TEXT", "__constructor", 0,SectionKind::getDataRel()); + StaticDtorSection + = getMachOSection("__TEXT", "__destructor", 0, SectionKind::getDataRel()); + } else { + StaticCtorSection + = getMachOSection("__DATA", "__mod_init_func", + MCSectionMachO::S_MOD_INIT_FUNC_POINTERS, + SectionKind::getDataRel()); + StaticDtorSection + = getMachOSection("__DATA", "__mod_term_func", + MCSectionMachO::S_MOD_TERM_FUNC_POINTERS, + SectionKind::getDataRel()); + } + + // Exception Handling. + LSDASection = getMachOSection("__DATA", "__gcc_except_tab", 0, + SectionKind::getDataRel()); + EHFrameSection = + getMachOSection("__TEXT", "__eh_frame", + MCSectionMachO::S_COALESCED | + MCSectionMachO::S_ATTR_NO_TOC | + MCSectionMachO::S_ATTR_STRIP_STATIC_SYMS | + MCSectionMachO::S_ATTR_LIVE_SUPPORT, + SectionKind::getReadOnly()); + + // Debug Information. + DwarfAbbrevSection = + getMachOSection("__DWARF", "__debug_abbrev", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfInfoSection = + getMachOSection("__DWARF", "__debug_info", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfLineSection = + getMachOSection("__DWARF", "__debug_line", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfFrameSection = + getMachOSection("__DWARF", "__debug_frame", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfPubNamesSection = + getMachOSection("__DWARF", "__debug_pubnames", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfPubTypesSection = + getMachOSection("__DWARF", "__debug_pubtypes", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfStrSection = + getMachOSection("__DWARF", "__debug_str", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfLocSection = + getMachOSection("__DWARF", "__debug_loc", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfARangesSection = + getMachOSection("__DWARF", "__debug_aranges", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfRangesSection = + getMachOSection("__DWARF", "__debug_ranges", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfMacroInfoSection = + getMachOSection("__DWARF", "__debug_macinfo", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfDebugInlineSection = + getMachOSection("__DWARF", "__debug_inlined", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); +} + +const MCSection *TargetLoweringObjectFileMachO:: +getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + // Parse the section specifier and create it if valid. + StringRef Segment, Section; + unsigned TAA, StubSize; + std::string ErrorCode = + MCSectionMachO::ParseSectionSpecifier(GV->getSection(), Segment, Section, + TAA, StubSize); + if (!ErrorCode.empty()) { + // If invalid, report the error with llvm_report_error. + llvm_report_error("Global variable '" + GV->getNameStr() + + "' has an invalid section specifier '" + GV->getSection()+ + "': " + ErrorCode + "."); + // Fall back to dropping it into the data section. + return DataSection; + } + + // Get the section. + const MCSectionMachO *S = + getMachOSection(Segment, Section, TAA, StubSize, Kind); + + // Okay, now that we got the section, verify that the TAA & StubSize agree. + // If the user declared multiple globals with different section flags, we need + // to reject it here. + if (S->getTypeAndAttributes() != TAA || S->getStubSize() != StubSize) { + // If invalid, report the error with llvm_report_error. + llvm_report_error("Global variable '" + GV->getNameStr() + + "' section type or attributes does not match previous" + " section specifier"); + } + + return S; +} + +const MCSection *TargetLoweringObjectFileMachO:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + assert(!Kind.isThreadLocal() && "Darwin doesn't support TLS"); + + if (Kind.isText()) + return GV->isWeakForLinker() ? TextCoalSection : TextSection; + + // If this is weak/linkonce, put this in a coalescable section, either in text + // or data depending on if it is writable. + if (GV->isWeakForLinker()) { + if (Kind.isReadOnly()) + return ConstTextCoalSection; + return DataCoalSection; + } + + // FIXME: Alignment check should be handled by section classifier. + if (Kind.isMergeable1ByteCString() || + Kind.isMergeable2ByteCString()) { + if (TM.getTargetData()->getPreferredAlignment( + cast<GlobalVariable>(GV)) < 32) { + if (Kind.isMergeable1ByteCString()) + return CStringSection; + assert(Kind.isMergeable2ByteCString()); + return UStringSection; + } + } + + if (Kind.isMergeableConst()) { + if (Kind.isMergeableConst4()) + return FourByteConstantSection; + if (Kind.isMergeableConst8()) + return EightByteConstantSection; + if (Kind.isMergeableConst16() && SixteenByteConstantSection) + return SixteenByteConstantSection; + } + + // Otherwise, if it is readonly, but not something we can specially optimize, + // just drop it in .const. + if (Kind.isReadOnly()) + return ReadOnlySection; + + // If this is marked const, put it into a const section. But if the dynamic + // linker needs to write to it, put it in the data segment. + if (Kind.isReadOnlyWithRel()) + return ConstDataSection; + + // Put zero initialized globals with strong external linkage in the + // DATA, __common section with the .zerofill directive. + if (Kind.isBSSExtern()) + return DataCommonSection; + + // Put zero initialized globals with local linkage in __DATA,__bss directive + // with the .zerofill directive (aka .lcomm). + if (Kind.isBSSLocal()) + return DataBSSSection; + + // Otherwise, just drop the variable in the normal data section. + return DataSection; +} + +const MCSection * +TargetLoweringObjectFileMachO::getSectionForConstant(SectionKind Kind) const { + // If this constant requires a relocation, we have to put it in the data + // segment, not in the text segment. + if (Kind.isDataRel() || Kind.isReadOnlyWithRel()) + return ConstDataSection; + + if (Kind.isMergeableConst4()) + return FourByteConstantSection; + if (Kind.isMergeableConst8()) + return EightByteConstantSection; + if (Kind.isMergeableConst16() && SixteenByteConstantSection) + return SixteenByteConstantSection; + return ReadOnlySection; // .const +} + +/// shouldEmitUsedDirectiveFor - This hook allows targets to selectively decide +/// not to emit the UsedDirective for some symbols in llvm.used. +// FIXME: REMOVE this (rdar://7071300) +bool TargetLoweringObjectFileMachO:: +shouldEmitUsedDirectiveFor(const GlobalValue *GV, Mangler *Mang) const { + /// On Darwin, internally linked data beginning with "L" or "l" does not have + /// the directive emitted (this occurs in ObjC metadata). + if (!GV) return false; + + // Check whether the mangled name has the "Private" or "LinkerPrivate" prefix. + if (GV->hasLocalLinkage() && !isa<Function>(GV)) { + // FIXME: ObjC metadata is currently emitted as internal symbols that have + // \1L and \0l prefixes on them. Fix them to be Private/LinkerPrivate and + // this horrible hack can go away. + SmallString<64> Name; + Mang->getNameWithPrefix(Name, GV, false); + if (Name[0] == 'L' || Name[0] == 'l') + return false; + } + + return true; +} + +const MCExpr *TargetLoweringObjectFileMachO:: +getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, unsigned Encoding) const { + // The mach-o version of this method defaults to returning a stub reference. + + if (Encoding & dwarf::DW_EH_PE_indirect) { + SmallString<128> Name; + Mang->getNameWithPrefix(Name, GV, true); + Name += "$non_lazy_ptr"; + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name.str()); + + return TargetLoweringObjectFile:: + getSymbolForDwarfReference(Sym, MMI, + Encoding & ~dwarf::DW_EH_PE_indirect); + } + + return TargetLoweringObjectFile:: + getSymbolForDwarfGlobalReference(GV, Mang, MMI, Encoding); +} + + +//===----------------------------------------------------------------------===// +// COFF +//===----------------------------------------------------------------------===// + +typedef StringMap<const MCSectionCOFF*> COFFUniqueMapTy; + +TargetLoweringObjectFileCOFF::~TargetLoweringObjectFileCOFF() { + delete (COFFUniqueMapTy*)UniquingMap; +} + + +const MCSection *TargetLoweringObjectFileCOFF:: +getCOFFSection(StringRef Name, bool isDirective, SectionKind Kind) const { + // Create the map if it doesn't already exist. + if (UniquingMap == 0) + UniquingMap = new MachOUniqueMapTy(); + COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)UniquingMap; + + // Do the lookup, if we have a hit, return it. + const MCSectionCOFF *&Entry = Map[Name]; + if (Entry) return Entry; + + return Entry = MCSectionCOFF::Create(Name, isDirective, Kind, getContext()); +} + +void TargetLoweringObjectFileCOFF::Initialize(MCContext &Ctx, + const TargetMachine &TM) { + if (UniquingMap != 0) + ((COFFUniqueMapTy*)UniquingMap)->clear(); + TargetLoweringObjectFile::Initialize(Ctx, TM); + TextSection = getCOFFSection("\t.text", true, SectionKind::getText()); + DataSection = getCOFFSection("\t.data", true, SectionKind::getDataRel()); + StaticCtorSection = + getCOFFSection(".ctors", false, SectionKind::getDataRel()); + StaticDtorSection = + getCOFFSection(".dtors", false, SectionKind::getDataRel()); + + // FIXME: We're emitting LSDA info into a readonly section on COFF, even + // though it contains relocatable pointers. In PIC mode, this is probably a + // big runtime hit for C++ apps. Either the contents of the LSDA need to be + // adjusted or this should be a data section. + LSDASection = + getCOFFSection(".gcc_except_table", false, SectionKind::getReadOnly()); + EHFrameSection = + getCOFFSection(".eh_frame", false, SectionKind::getDataRel()); + + // Debug info. + // FIXME: Don't use 'directive' mode here. + DwarfAbbrevSection = + getCOFFSection("\t.section\t.debug_abbrev,\"dr\"", + true, SectionKind::getMetadata()); + DwarfInfoSection = + getCOFFSection("\t.section\t.debug_info,\"dr\"", + true, SectionKind::getMetadata()); + DwarfLineSection = + getCOFFSection("\t.section\t.debug_line,\"dr\"", + true, SectionKind::getMetadata()); + DwarfFrameSection = + getCOFFSection("\t.section\t.debug_frame,\"dr\"", + true, SectionKind::getMetadata()); + DwarfPubNamesSection = + getCOFFSection("\t.section\t.debug_pubnames,\"dr\"", + true, SectionKind::getMetadata()); + DwarfPubTypesSection = + getCOFFSection("\t.section\t.debug_pubtypes,\"dr\"", + true, SectionKind::getMetadata()); + DwarfStrSection = + getCOFFSection("\t.section\t.debug_str,\"dr\"", + true, SectionKind::getMetadata()); + DwarfLocSection = + getCOFFSection("\t.section\t.debug_loc,\"dr\"", + true, SectionKind::getMetadata()); + DwarfARangesSection = + getCOFFSection("\t.section\t.debug_aranges,\"dr\"", + true, SectionKind::getMetadata()); + DwarfRangesSection = + getCOFFSection("\t.section\t.debug_ranges,\"dr\"", + true, SectionKind::getMetadata()); + DwarfMacroInfoSection = + getCOFFSection("\t.section\t.debug_macinfo,\"dr\"", + true, SectionKind::getMetadata()); +} + +const MCSection *TargetLoweringObjectFileCOFF:: +getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + return getCOFFSection(GV->getSection(), false, Kind); +} + +static const char *getCOFFSectionPrefixForUniqueGlobal(SectionKind Kind) { + if (Kind.isText()) + return ".text$linkonce"; + if (Kind.isWriteable()) + return ".data$linkonce"; + return ".rdata$linkonce"; +} + + +const MCSection *TargetLoweringObjectFileCOFF:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + assert(!Kind.isThreadLocal() && "Doesn't support TLS"); + + // If this global is linkonce/weak and the target handles this by emitting it + // into a 'uniqued' section name, create and return the section now. + if (GV->isWeakForLinker()) { + const char *Prefix = getCOFFSectionPrefixForUniqueGlobal(Kind); + SmallString<128> Name(Prefix, Prefix+strlen(Prefix)); + Mang->getNameWithPrefix(Name, GV, false); + return getCOFFSection(Name.str(), false, Kind); + } + + if (Kind.isText()) + return getTextSection(); + + return getDataSection(); +} + diff --git a/lib/CodeGen/TwoAddressInstructionPass.cpp b/lib/CodeGen/TwoAddressInstructionPass.cpp index a3f6364..6f4ca82 100644 --- a/lib/CodeGen/TwoAddressInstructionPass.cpp +++ b/lib/CodeGen/TwoAddressInstructionPass.cpp @@ -213,6 +213,9 @@ bool TwoAddressInstructionPass::Sink3AddrInstruction(MachineBasicBlock *MBB, unsigned NumVisited = 0; for (MachineBasicBlock::iterator I = llvm::next(OldPos); I != KillPos; ++I) { MachineInstr *OtherMI = I; + // DBG_VALUE cannot be counted against the limit. + if (OtherMI->isDebugValue()) + continue; if (NumVisited > 30) // FIXME: Arbitrary limit to reduce compile time cost. return false; ++NumVisited; @@ -316,7 +319,7 @@ bool TwoAddressInstructionPass::NoUseAfterLastDef(unsigned Reg, E = MRI->reg_end(); I != E; ++I) { MachineOperand &MO = I.getOperand(); MachineInstr *MI = MO.getParent(); - if (MI->getParent() != MBB) + if (MI->getParent() != MBB || MI->isDebugValue()) continue; DenseMap<MachineInstr*, unsigned>::iterator DI = DistanceMap.find(MI); if (DI == DistanceMap.end()) @@ -339,7 +342,7 @@ MachineInstr *TwoAddressInstructionPass::FindLastUseInMBB(unsigned Reg, E = MRI->reg_end(); I != E; ++I) { MachineOperand &MO = I.getOperand(); MachineInstr *MI = MO.getParent(); - if (MI->getParent() != MBB) + if (MI->getParent() != MBB || MI->isDebugValue()) continue; DenseMap<MachineInstr*, unsigned>::iterator DI = DistanceMap.find(MI); if (DI == DistanceMap.end()) @@ -365,13 +368,13 @@ static bool isCopyToReg(MachineInstr &MI, const TargetInstrInfo *TII, DstReg = 0; unsigned SrcSubIdx, DstSubIdx; if (!TII->isMoveInstr(MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx)) { - if (MI.getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) { + if (MI.isExtractSubreg()) { DstReg = MI.getOperand(0).getReg(); SrcReg = MI.getOperand(1).getReg(); - } else if (MI.getOpcode() == TargetInstrInfo::INSERT_SUBREG) { + } else if (MI.isInsertSubreg()) { DstReg = MI.getOperand(0).getReg(); SrcReg = MI.getOperand(2).getReg(); - } else if (MI.getOpcode() == TargetInstrInfo::SUBREG_TO_REG) { + } else if (MI.isSubregToReg()) { DstReg = MI.getOperand(0).getReg(); SrcReg = MI.getOperand(2).getReg(); } @@ -429,8 +432,7 @@ static bool isKilled(MachineInstr &MI, unsigned Reg, /// as a two-address use. If so, return the destination register by reference. static bool isTwoAddrUse(MachineInstr &MI, unsigned Reg, unsigned &DstReg) { const TargetInstrDesc &TID = MI.getDesc(); - unsigned NumOps = (MI.getOpcode() == TargetInstrInfo::INLINEASM) - ? MI.getNumOperands() : TID.getNumOperands(); + unsigned NumOps = MI.isInlineAsm() ? MI.getNumOperands():TID.getNumOperands(); for (unsigned i = 0; i != NumOps; ++i) { const MachineOperand &MO = MI.getOperand(i); if (!MO.isReg() || !MO.isUse() || MO.getReg() != Reg) @@ -452,11 +454,11 @@ MachineInstr *findOnlyInterestingUse(unsigned Reg, MachineBasicBlock *MBB, const TargetInstrInfo *TII, bool &IsCopy, unsigned &DstReg, bool &IsDstPhys) { - MachineRegisterInfo::use_iterator UI = MRI->use_begin(Reg); - if (UI == MRI->use_end()) + MachineRegisterInfo::use_nodbg_iterator UI = MRI->use_nodbg_begin(Reg); + if (UI == MRI->use_nodbg_end()) return 0; MachineInstr &UseMI = *UI; - if (++UI != MRI->use_end()) + if (++UI != MRI->use_nodbg_end()) // More than one use. return 0; if (UseMI.getParent() != MBB) @@ -924,6 +926,10 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) { for (MachineBasicBlock::iterator mi = mbbi->begin(), me = mbbi->end(); mi != me; ) { MachineBasicBlock::iterator nmi = llvm::next(mi); + if (mi->isDebugValue()) { + mi = nmi; + continue; + } const TargetInstrDesc &TID = mi->getDesc(); bool FirstTied = true; @@ -933,7 +939,7 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) { // First scan through all the tied register uses in this instruction // and record a list of pairs of tied operands for each register. - unsigned NumOps = (mi->getOpcode() == TargetInstrInfo::INLINEASM) + unsigned NumOps = mi->isInlineAsm() ? mi->getNumOperands() : TID.getNumOperands(); for (unsigned SrcIdx = 0; SrcIdx < NumOps; ++SrcIdx) { unsigned DstIdx = 0; diff --git a/lib/CodeGen/UnreachableBlockElim.cpp b/lib/CodeGen/UnreachableBlockElim.cpp index 6ab5db2..b0f0a07 100644 --- a/lib/CodeGen/UnreachableBlockElim.cpp +++ b/lib/CodeGen/UnreachableBlockElim.cpp @@ -148,8 +148,7 @@ bool UnreachableMachineBlockElim::runOnMachineFunction(MachineFunction &F) { MachineBasicBlock* succ = *BB->succ_begin(); MachineBasicBlock::iterator start = succ->begin(); - while (start != succ->end() && - start->getOpcode() == TargetInstrInfo::PHI) { + while (start != succ->end() && start->isPHI()) { for (unsigned i = start->getNumOperands() - 1; i >= 2; i-=2) if (start->getOperand(i).isMBB() && start->getOperand(i).getMBB() == BB) { @@ -188,8 +187,7 @@ bool UnreachableMachineBlockElim::runOnMachineFunction(MachineFunction &F) { SmallPtrSet<MachineBasicBlock*, 8> preds(BB->pred_begin(), BB->pred_end()); MachineBasicBlock::iterator phi = BB->begin(); - while (phi != BB->end() && - phi->getOpcode() == TargetInstrInfo::PHI) { + while (phi != BB->end() && phi->isPHI()) { for (unsigned i = phi->getNumOperands() - 1; i >= 2; i-=2) if (!preds.count(phi->getOperand(i).getMBB())) { phi->RemoveOperand(i); diff --git a/lib/CodeGen/VirtRegMap.cpp b/lib/CodeGen/VirtRegMap.cpp index d4fb2e4..5956b61 100644 --- a/lib/CodeGen/VirtRegMap.cpp +++ b/lib/CodeGen/VirtRegMap.cpp @@ -9,7 +9,7 @@ // // This file implements the VirtRegMap class. // -// It also contains implementations of the the Spiller interface, which, given a +// It also contains implementations of the Spiller interface, which, given a // virtual register map and a machine function, eliminates all virtual // references by replacing them with physical register references - adding spill // code as necessary. diff --git a/lib/CodeGen/VirtRegRewriter.cpp b/lib/CodeGen/VirtRegRewriter.cpp index df2b8d2..84e0398 100644 --- a/lib/CodeGen/VirtRegRewriter.cpp +++ b/lib/CodeGen/VirtRegRewriter.cpp @@ -62,6 +62,7 @@ VirtRegRewriter::~VirtRegRewriter() {} /// substitutePhysReg - Replace virtual register in MachineOperand with a /// physical register. Do the right thing with the sub-register index. +/// Note that operands may be added, so the MO reference is no longer valid. static void substitutePhysReg(MachineOperand &MO, unsigned Reg, const TargetRegisterInfo &TRI) { if (unsigned SubIdx = MO.getSubReg()) { @@ -123,14 +124,15 @@ struct TrivialRewriter : public VirtRegRewriter { continue; unsigned pReg = VRM.getPhys(reg); mri->setPhysRegUsed(pReg); - for (MachineRegisterInfo::reg_iterator regItr = mri->reg_begin(reg), - regEnd = mri->reg_end(); regItr != regEnd;) { - MachineOperand &mop = regItr.getOperand(); - assert(mop.isReg() && mop.getReg() == reg && "reg_iterator broken?"); - ++regItr; - substitutePhysReg(mop, pReg, *tri); - changed = true; - } + // Copy the register use-list before traversing it. + SmallVector<std::pair<MachineInstr*, unsigned>, 32> reglist; + for (MachineRegisterInfo::reg_iterator I = mri->reg_begin(reg), + E = mri->reg_end(); I != E; ++I) + reglist.push_back(std::make_pair(&*I, I.getOperandNo())); + for (unsigned N=0; N != reglist.size(); ++N) + substitutePhysReg(reglist[N].first->getOperand(reglist[N].second), + pReg, *tri); + changed |= !reglist.empty(); } } @@ -1759,7 +1761,7 @@ private: // Mark is killed. MachineInstr *CopyMI = prior(InsertLoc); - CopyMI->setAsmPrinterFlag(AsmPrinter::ReloadReuse); + CopyMI->setAsmPrinterFlag(MachineInstr::ReloadReuse); MachineOperand *KillOpnd = CopyMI->findRegisterUseOperand(InReg); KillOpnd->setIsKill(); UpdateKills(*CopyMI, TRI, RegKills, KillOps); @@ -1850,31 +1852,30 @@ private: KilledMIRegs.clear(); for (unsigned j = 0, e = VirtUseOps.size(); j != e; ++j) { unsigned i = VirtUseOps[j]; - MachineOperand &MO = MI.getOperand(i); - unsigned VirtReg = MO.getReg(); + unsigned VirtReg = MI.getOperand(i).getReg(); assert(TargetRegisterInfo::isVirtualRegister(VirtReg) && "Not a virtual register?"); - unsigned SubIdx = MO.getSubReg(); + unsigned SubIdx = MI.getOperand(i).getSubReg(); if (VRM.isAssignedReg(VirtReg)) { // This virtual register was assigned a physreg! unsigned Phys = VRM.getPhys(VirtReg); RegInfo->setPhysRegUsed(Phys); - if (MO.isDef()) + if (MI.getOperand(i).isDef()) ReusedOperands.markClobbered(Phys); - substitutePhysReg(MO, Phys, *TRI); + substitutePhysReg(MI.getOperand(i), Phys, *TRI); if (VRM.isImplicitlyDefined(VirtReg)) // FIXME: Is this needed? BuildMI(MBB, &MI, MI.getDebugLoc(), - TII->get(TargetInstrInfo::IMPLICIT_DEF), Phys); + TII->get(TargetOpcode::IMPLICIT_DEF), Phys); continue; } // This virtual register is now known to be a spilled value. - if (!MO.isUse()) + if (!MI.getOperand(i).isUse()) continue; // Handle defs in the loop below (handle use&def here though) - bool AvoidReload = MO.isUndef(); + bool AvoidReload = MI.getOperand(i).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 @@ -1902,8 +1903,7 @@ private: // = EXTRACT_SUBREG fi#1 // fi#1 is available in EDI, but it cannot be reused because it's not in // the right register file. - if (PhysReg && !AvoidReload && - (SubIdx || MI.getOpcode() == TargetInstrInfo::EXTRACT_SUBREG)) { + if (PhysReg && !AvoidReload && (SubIdx || MI.isExtractSubreg())) { const TargetRegisterClass* RC = RegInfo->getRegClass(VirtReg); if (!RC->contains(PhysReg)) PhysReg = 0; @@ -2038,7 +2038,7 @@ private: TII->copyRegToReg(MBB, InsertLoc, DesignatedReg, PhysReg, RC, RC); MachineInstr *CopyMI = prior(InsertLoc); - CopyMI->setAsmPrinterFlag(AsmPrinter::ReloadReuse); + CopyMI->setAsmPrinterFlag(MachineInstr::ReloadReuse); UpdateKills(*CopyMI, TRI, RegKills, KillOps); // This invalidates DesignatedReg. @@ -2167,7 +2167,7 @@ private: // virtual or needing to clobber any values if it's physical). NextMII = &MI; --NextMII; // backtrack to the copy. - NextMII->setAsmPrinterFlag(AsmPrinter::ReloadReuse); + NextMII->setAsmPrinterFlag(MachineInstr::ReloadReuse); // Propagate the sub-register index over. if (SubIdx) { DefMO = NextMII->findRegisterDefOperand(DestReg); |