Пример #1
0
/// isBlockOnlyReachableByFallthough - Return true if the basic block has
/// exactly one predecessor and the control transfer mechanism between
/// the predecessor and this block is a fall-through.
/// Override AsmPrinter implementation to handle delay slots
bool SparcAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) 
    const {
  // If this is a landing pad, it isn't a fall through.  If it has no preds,
  // then nothing falls through to it.
  if (MBB->isLandingPad() || MBB->pred_empty())
    return false;
  
  // If there isn't exactly one predecessor, it can't be a fall through.
  MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI;
  ++PI2;
  if (PI2 != MBB->pred_end())
    return false;
  
  // The predecessor has to be immediately before this block.
  const MachineBasicBlock *Pred = *PI;
  
  if (!Pred->isLayoutSuccessor(MBB))
    return false;
  
  // Check if the last terminator is an unconditional branch
  MachineBasicBlock::const_iterator I = Pred->end();
  while( I != Pred->begin() && !(--I)->getDesc().isTerminator() )
      ; /* Noop */
  return I == Pred->end() || !I->getDesc().isBarrier();
}
Пример #2
0
SlotIndex SplitAnalysis::computeLastSplitPoint(unsigned Num) {
  const MachineBasicBlock *MBB = MF.getBlockNumbered(Num);
  const MachineBasicBlock *LPad = MBB->getLandingPadSuccessor();
  std::pair<SlotIndex, SlotIndex> &LSP = LastSplitPoint[Num];

  // Compute split points on the first call. The pair is independent of the
  // current live interval.
  if (!LSP.first.isValid()) {
    MachineBasicBlock::const_iterator FirstTerm = MBB->getFirstTerminator();
    if (FirstTerm == MBB->end())
      LSP.first = LIS.getMBBEndIdx(MBB);
    else
      LSP.first = LIS.getInstructionIndex(FirstTerm);

    // If there is a landing pad successor, also find the call instruction.
    if (!LPad)
      return LSP.first;
    // There may not be a call instruction (?) in which case we ignore LPad.
    LSP.second = LSP.first;
    for (MachineBasicBlock::const_iterator I = MBB->end(), E = MBB->begin();
         I != E;) {
      --I;
      if (I->getDesc().isCall()) {
        LSP.second = LIS.getInstructionIndex(I);
        break;
      }
    }
  }

  // If CurLI is live into a landing pad successor, move the last split point
  // back to the call that may throw.
  if (LPad && LSP.second.isValid() && LIS.isLiveInToMBB(*CurLI, LPad))
    return LSP.second;
  else
    return LSP.first;
}
Пример #3
0
/// shouldTailDuplicate - Determine if it is profitable to duplicate this block.
bool
TailDuplicatePass::shouldTailDuplicate(const MachineFunction &MF,
                                       MachineBasicBlock &TailBB) {
  // Only duplicate blocks that end with unconditional branches.
  if (TailBB.canFallThrough())
    return false;

  // Don't try to tail-duplicate single-block loops.
  if (TailBB.isSuccessor(&TailBB))
    return false;

  // Set the limit on the cost to duplicate. When optimizing for size,
  // duplicate only one, because one branch instruction can be eliminated to
  // compensate for the duplication.
  unsigned MaxDuplicateCount;
  if (TailDuplicateSize.getNumOccurrences() == 0 &&
      MF.getFunction()->hasFnAttr(Attribute::OptimizeForSize))
    MaxDuplicateCount = 1;
  else
    MaxDuplicateCount = TailDuplicateSize;

  // If the target has hardware branch prediction that can handle indirect
  // branches, duplicating them can often make them predictable when there
  // are common paths through the code.  The limit needs to be high enough
  // to allow undoing the effects of tail merging and other optimizations
  // that rearrange the predecessors of the indirect branch.

  if (PreRegAlloc && !TailBB.empty()) {
    const TargetInstrDesc &TID = TailBB.back().getDesc();
    if (TID.isIndirectBranch())
      MaxDuplicateCount = 20;
  }

  // Check the instructions in the block to determine whether tail-duplication
  // is invalid or unlikely to be profitable.
  unsigned InstrCount = 0;
  for (MachineBasicBlock::const_iterator I = TailBB.begin(); I != TailBB.end();
       ++I) {
    // Non-duplicable things shouldn't be tail-duplicated.
    if (I->getDesc().isNotDuplicable())
      return false;

    // Do not duplicate 'return' instructions if this is a pre-regalloc run.
    // A return may expand into a lot more instructions (e.g. reload of callee
    // saved registers) after PEI.
    if (PreRegAlloc && I->getDesc().isReturn())
      return false;

    // Avoid duplicating calls before register allocation. Calls presents a
    // barrier to register allocation so duplicating them may end up increasing
    // spills.
    if (PreRegAlloc && I->getDesc().isCall())
      return false;

    if (!I->isPHI() && !I->isDebugValue())
      InstrCount += 1;

    if (InstrCount > MaxDuplicateCount)
      return false;
  }

  return true;
}
Пример #4
0
unsigned char* JITDwarfEmitter::EmitExceptionTable(MachineFunction* MF,
                                         unsigned char* StartFunction,
                                         unsigned char* EndFunction) const {
  assert(MMI && "MachineModuleInfo not registered!");

  // Map all labels and get rid of any dead landing pads.
  MMI->TidyLandingPads(JCE->getLabelLocations());

  const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos();
  const std::vector<unsigned> &FilterIds = MMI->getFilterIds();
  const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
  if (PadInfos.empty()) return 0;

  // Sort the landing pads in order of their type ids.  This is used to fold
  // duplicate actions.
  SmallVector<const LandingPadInfo *, 64> LandingPads;
  LandingPads.reserve(PadInfos.size());
  for (unsigned i = 0, N = PadInfos.size(); i != N; ++i)
    LandingPads.push_back(&PadInfos[i]);
  std::sort(LandingPads.begin(), LandingPads.end(), PadLT);

  // Negative type ids index into FilterIds, positive type ids index into
  // TypeInfos.  The value written for a positive type id is just the type
  // id itself.  For a negative type id, however, the value written is the
  // (negative) byte offset of the corresponding FilterIds entry.  The byte
  // offset is usually equal to the type id, because the FilterIds entries
  // are written using a variable width encoding which outputs one byte per
  // entry as long as the value written is not too large, but can differ.
  // This kind of complication does not occur for positive type ids because
  // type infos are output using a fixed width encoding.
  // FilterOffsets[i] holds the byte offset corresponding to FilterIds[i].
  SmallVector<int, 16> FilterOffsets;
  FilterOffsets.reserve(FilterIds.size());
  int Offset = -1;
  for(std::vector<unsigned>::const_iterator I = FilterIds.begin(),
    E = FilterIds.end(); I != E; ++I) {
    FilterOffsets.push_back(Offset);
    Offset -= MCAsmInfo::getULEB128Size(*I);
  }

  // Compute the actions table and gather the first action index for each
  // landing pad site.
  SmallVector<ActionEntry, 32> Actions;
  SmallVector<unsigned, 64> FirstActions;
  FirstActions.reserve(LandingPads.size());

  int FirstAction = 0;
  unsigned SizeActions = 0;
  for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
    const LandingPadInfo *LP = LandingPads[i];
    const std::vector<int> &TypeIds = LP->TypeIds;
    const unsigned NumShared = i ? SharedTypeIds(LP, LandingPads[i-1]) : 0;
    unsigned SizeSiteActions = 0;

    if (NumShared < TypeIds.size()) {
      unsigned SizeAction = 0;
      ActionEntry *PrevAction = 0;

      if (NumShared) {
        const unsigned SizePrevIds = LandingPads[i-1]->TypeIds.size();
        assert(Actions.size());
        PrevAction = &Actions.back();
        SizeAction = MCAsmInfo::getSLEB128Size(PrevAction->NextAction) +
          MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID);
        for (unsigned j = NumShared; j != SizePrevIds; ++j) {
          SizeAction -= MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID);
          SizeAction += -PrevAction->NextAction;
          PrevAction = PrevAction->Previous;
        }
      }

      // Compute the actions.
      for (unsigned I = NumShared, M = TypeIds.size(); I != M; ++I) {
        int TypeID = TypeIds[I];
        assert(-1-TypeID < (int)FilterOffsets.size() && "Unknown filter id!");
        int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID;
        unsigned SizeTypeID = MCAsmInfo::getSLEB128Size(ValueForTypeID);

        int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0;
        SizeAction = SizeTypeID + MCAsmInfo::getSLEB128Size(NextAction);
        SizeSiteActions += SizeAction;

        ActionEntry Action = {ValueForTypeID, NextAction, PrevAction};
        Actions.push_back(Action);

        PrevAction = &Actions.back();
      }

      // Record the first action of the landing pad site.
      FirstAction = SizeActions + SizeSiteActions - SizeAction + 1;
    } // else identical - re-use previous FirstAction

    FirstActions.push_back(FirstAction);

    // Compute this sites contribution to size.
    SizeActions += SizeSiteActions;
  }

  // Compute the call-site table.  Entries must be ordered by address.
  SmallVector<CallSiteEntry, 64> CallSites;

  RangeMapType PadMap;
  for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
    const LandingPadInfo *LandingPad = LandingPads[i];
    for (unsigned j=0, E = LandingPad->BeginLabels.size(); j != E; ++j) {
      MCSymbol *BeginLabel = LandingPad->BeginLabels[j];
      assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!");
      PadRange P = { i, j };
      PadMap[BeginLabel] = P;
    }
  }

  bool MayThrow = false;
  MCSymbol *LastLabel = 0;
  for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
        I != E; ++I) {
    for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end();
          MI != E; ++MI) {
      if (!MI->isLabel()) {
        MayThrow |= MI->getDesc().isCall();
        continue;
      }

      MCSymbol *BeginLabel = MI->getOperand(0).getMCSymbol();
      assert(BeginLabel && "Invalid label!");

      if (BeginLabel == LastLabel)
        MayThrow = false;

      RangeMapType::iterator L = PadMap.find(BeginLabel);

      if (L == PadMap.end())
        continue;

      PadRange P = L->second;
      const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];

      assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
              "Inconsistent landing pad map!");

      // If some instruction between the previous try-range and this one may
      // throw, create a call-site entry with no landing pad for the region
      // between the try-ranges.
      if (MayThrow) {
        CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0};
        CallSites.push_back(Site);
      }

      LastLabel = LandingPad->EndLabels[P.RangeIndex];
      CallSiteEntry Site = {BeginLabel, LastLabel,
        LandingPad->LandingPadLabel, FirstActions[P.PadIndex]};

      assert(Site.BeginLabel && Site.EndLabel && Site.PadLabel &&
              "Invalid landing pad!");

      // Try to merge with the previous call-site.
      if (CallSites.size()) {
        CallSiteEntry &Prev = CallSites.back();
        if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) {
          // Extend the range of the previous entry.
          Prev.EndLabel = Site.EndLabel;
          continue;
        }
      }

      // Otherwise, create a new call-site.
      CallSites.push_back(Site);
    }
  }
  // If some instruction between the previous try-range and the end of the
  // function may throw, create a call-site entry with no landing pad for the
  // region following the try-range.
  if (MayThrow) {
    CallSiteEntry Site = {LastLabel, 0, 0, 0};
    CallSites.push_back(Site);
  }

  // Final tallies.
  unsigned SizeSites = CallSites.size() * (sizeof(int32_t) + // Site start.
                                            sizeof(int32_t) + // Site length.
                                            sizeof(int32_t)); // Landing pad.
  for (unsigned i = 0, e = CallSites.size(); i < e; ++i)
    SizeSites += MCAsmInfo::getULEB128Size(CallSites[i].Action);

  unsigned SizeTypes = TypeInfos.size() * TD->getPointerSize();

  unsigned TypeOffset = sizeof(int8_t) + // Call site format
                        // Call-site table length
                        MCAsmInfo::getULEB128Size(SizeSites) + 
                        SizeSites + SizeActions + SizeTypes;

  // Begin the exception table.
  JCE->emitAlignmentWithFill(4, 0);
  // Asm->EOL("Padding");

  unsigned char* DwarfExceptionTable = (unsigned char*)JCE->getCurrentPCValue();

  // Emit the header.
  JCE->emitByte(dwarf::DW_EH_PE_omit);
  // Asm->EOL("LPStart format (DW_EH_PE_omit)");
  JCE->emitByte(dwarf::DW_EH_PE_absptr);
  // Asm->EOL("TType format (DW_EH_PE_absptr)");
  JCE->emitULEB128Bytes(TypeOffset);
  // Asm->EOL("TType base offset");
  JCE->emitByte(dwarf::DW_EH_PE_udata4);
  // Asm->EOL("Call site format (DW_EH_PE_udata4)");
  JCE->emitULEB128Bytes(SizeSites);
  // Asm->EOL("Call-site table length");

  // Emit the landing pad site information.
  for (unsigned i = 0; i < CallSites.size(); ++i) {
    CallSiteEntry &S = CallSites[i];
    intptr_t BeginLabelPtr = 0;
    intptr_t EndLabelPtr = 0;

    if (!S.BeginLabel) {
      BeginLabelPtr = (intptr_t)StartFunction;
      JCE->emitInt32(0);
    } else {
      BeginLabelPtr = JCE->getLabelAddress(S.BeginLabel);
      JCE->emitInt32(BeginLabelPtr - (intptr_t)StartFunction);
    }

    // Asm->EOL("Region start");

    if (!S.EndLabel)
      EndLabelPtr = (intptr_t)EndFunction;
    else
      EndLabelPtr = JCE->getLabelAddress(S.EndLabel);

    JCE->emitInt32(EndLabelPtr - BeginLabelPtr);
    //Asm->EOL("Region length");

    if (!S.PadLabel) {
      JCE->emitInt32(0);
    } else {
      unsigned PadLabelPtr = JCE->getLabelAddress(S.PadLabel);
      JCE->emitInt32(PadLabelPtr - (intptr_t)StartFunction);
    }
    // Asm->EOL("Landing pad");

    JCE->emitULEB128Bytes(S.Action);
    // Asm->EOL("Action");
  }

  // Emit the actions.
  for (unsigned I = 0, N = Actions.size(); I != N; ++I) {
    ActionEntry &Action = Actions[I];

    JCE->emitSLEB128Bytes(Action.ValueForTypeID);
    //Asm->EOL("TypeInfo index");
    JCE->emitSLEB128Bytes(Action.NextAction);
    //Asm->EOL("Next action");
  }

  // Emit the type ids.
  for (unsigned M = TypeInfos.size(); M; --M) {
    const GlobalVariable *GV = TypeInfos[M - 1];
    
    if (GV) {
      if (TD->getPointerSize() == sizeof(int32_t))
        JCE->emitInt32((intptr_t)Jit.getOrEmitGlobalVariable(GV));
      else
        JCE->emitInt64((intptr_t)Jit.getOrEmitGlobalVariable(GV));
    } else {
      if (TD->getPointerSize() == sizeof(int32_t))
        JCE->emitInt32(0);
      else
        JCE->emitInt64(0);
    }
    // Asm->EOL("TypeInfo");
  }

  // Emit the filter typeids.
  for (unsigned j = 0, M = FilterIds.size(); j < M; ++j) {
    unsigned TypeID = FilterIds[j];
    JCE->emitULEB128Bytes(TypeID);
    //Asm->EOL("Filter TypeInfo index");
  }

  JCE->emitAlignmentWithFill(4, 0);

  return DwarfExceptionTable;
}
Пример #5
0
/// ComputeCallSiteTable - Compute the call-site table.  The entry for an invoke
/// has a try-range containing the call, a non-zero landing pad, and an
/// appropriate action.  The entry for an ordinary call has a try-range
/// containing the call and zero for the landing pad and the action.  Calls
/// marked 'nounwind' have no entry and must not be contained in the try-range
/// of any entry - they form gaps in the table.  Entries must be ordered by
/// try-range address.
void DwarfException::
ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
                     const RangeMapType &PadMap,
                     const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
                     const SmallVectorImpl<unsigned> &FirstActions) {
    // The end label of the previous invoke or nounwind try-range.
    unsigned LastLabel = 0;

    // Whether there is a potentially throwing instruction (currently this means
    // an ordinary call) between the end of the previous try-range and now.
    bool SawPotentiallyThrowing = false;

    // Whether the last CallSite entry was for an invoke.
    bool PreviousIsInvoke = false;

    // Visit all instructions in order of address.
    for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
            I != E; ++I) {
        for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end();
                MI != E; ++MI) {
            if (!MI->isLabel()) {
                SawPotentiallyThrowing |= MI->getDesc().isCall();
                continue;
            }

            unsigned BeginLabel = MI->getOperand(0).getImm();
            assert(BeginLabel && "Invalid label!");

            // End of the previous try-range?
            if (BeginLabel == LastLabel)
                SawPotentiallyThrowing = false;

            // Beginning of a new try-range?
            RangeMapType::iterator L = PadMap.find(BeginLabel);
            if (L == PadMap.end())
                // Nope, it was just some random label.
                continue;

            const PadRange &P = L->second;
            const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
            assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
                   "Inconsistent landing pad map!");

            // For Dwarf exception handling (SjLj handling doesn't use this). If some
            // instruction between the previous try-range and this one may throw,
            // create a call-site entry with no landing pad for the region between the
            // try-ranges.
            if (SawPotentiallyThrowing &&
                    TAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) {
                CallSiteEntry Site = { LastLabel, BeginLabel, 0, 0 };
                CallSites.push_back(Site);
                PreviousIsInvoke = false;
            }

            LastLabel = LandingPad->EndLabels[P.RangeIndex];
            assert(BeginLabel && LastLabel && "Invalid landing pad!");

            if (LandingPad->LandingPadLabel) {
                // This try-range is for an invoke.
                CallSiteEntry Site = {
                    BeginLabel,
                    LastLabel,
                    LandingPad->LandingPadLabel,
                    FirstActions[P.PadIndex]
                };

                // Try to merge with the previous call-site.
                if (PreviousIsInvoke) {
                    CallSiteEntry &Prev = CallSites.back();
                    if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) {
                        // Extend the range of the previous entry.
                        Prev.EndLabel = Site.EndLabel;
                        continue;
                    }
                }

                // Otherwise, create a new call-site.
                CallSites.push_back(Site);
                PreviousIsInvoke = true;
            } else {
                // Create a gap.
                PreviousIsInvoke = false;
            }
        }
    }

    // If some instruction between the previous try-range and the end of the
    // function may throw, create a call-site entry with no landing pad for the
    // region following the try-range.
    if (SawPotentiallyThrowing &&
            TAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) {
        CallSiteEntry Site = { LastLabel, 0, 0, 0 };
        CallSites.push_back(Site);
    }
}
Пример #6
0
bool VirtRegReduction::runOnMachineFunction(MachineFunction &MF)
{
  bool Changed = false;

#if VRRPROF
  const Function *F = MF.getFunction();
  std::string FN = F->getName().str();
  llog("starting vrr... %s (%d)\n", FN.c_str(), (int)time(NULL));
  llog("starting immRegs finder... (%d)\n", (int)time(NULL));
#endif
  std::auto_ptr<std::unordered_set<unsigned> > immRegsHolder;
  std::unordered_set<unsigned> *immRegs = NULL;
  
  // single-def regs defined by a MoveImm shouldn't coalesce as we may be
  // able to fold them later
  {
    std::unordered_map<unsigned, const MachineInstr *> singleDef;

    MachineFunction::const_iterator I = MF.begin(), E = MF.end();

    // find all registers w/ a single def
    for(; I != E; I++)
    {
      MachineBasicBlock::const_iterator BI = I->begin(), BE = I->end();

     for(; BI != BE; BI++)
     {
       MachineInstr::const_mop_iterator II, IE;
       II = BI->operands_begin();
       IE = BI->operands_end();
       for(; II != IE; II++)
         if(II->isReg() && II->isDef())
         {
           unsigned R = II->getReg();
           std::unordered_map<unsigned, const MachineInstr *>::iterator SI = singleDef.find(R);

           if(SI == singleDef.end())
             singleDef[R] = BI; // first seen! insert
           else
             SI->second = NULL; // second seen -- replace w/ NULL
         }
      }
    }

    std::unordered_map<unsigned, const MachineInstr *>::const_iterator SI = singleDef.begin(), SE = singleDef.end();

    for(; SI != SE; SI++)
    {
      if(SI->second && SI->second->getDesc().isMoveImmediate()) // single def imm?
      {
        if(!immRegs)
          immRegsHolder.reset(immRegs = new std::unordered_set<unsigned>);
        immRegs->insert(SI->first); // don't coalesce
      }
    }
  }

#if VRRPROF
  llog("starting tdkRegs finder... (%d)\n", (int)time(NULL));
#endif

  std::auto_ptr<std::unordered_set<unsigned> > tdkRegsHolder;
  std::unordered_set<unsigned> *tdkRegs = NULL;
  
  bool setjmpSafe = !MF.callsSetJmp() && MF.getFunction()->doesNotThrow();

  {
    tdkRegsHolder.reset(tdkRegs = new std::unordered_set<unsigned>);

    std::unordered_map<unsigned, unsigned> trivialDefKills;

    MachineFunction::const_iterator I = MF.begin(), E = MF.end();

    // find all registers defed and killed in the same block w/ no intervening
    // unsafe (due to setjmp) calls + side-effecty operations
    for(; I != E; I++)
    {
      std::unordered_set<unsigned> defs;

      MachineBasicBlock::const_iterator BI = I->begin(), BE = I->end();

     for(; BI != BE; BI++)
     {
       // TODO need to add || BI->getDesc().isInlineAsm() here to help stackification?
       if((!setjmpSafe && BI->getDesc().isCall()) || BI->getDesc().hasUnmodeledSideEffects()) { 
         // invalidate on a call instruction if setjmp present, or instr with side effects regardless
         defs.clear();
       }

       MachineInstr::const_mop_iterator II, IE;
     
       // uses when we're not tracking a reg it make it unsafe
       II = BI->operands_begin();
       IE = BI->operands_end();
       for(; II != IE; II++)
         if(II->isReg() && II->isUse())
         {
           unsigned R = II->getReg();
           std::unordered_set<unsigned>::const_iterator DI = defs.find(R);

           if(DI == defs.end())
             trivialDefKills[R] = 100;
         }
       // kills of tracked defs are trivial def/kills
       II = BI->operands_begin();
       IE = BI->operands_end();
       for(; II != IE; II++)
         if(II->isReg() && II->isKill())
         {
           unsigned R = II->getReg();
           std::unordered_set<unsigned>::const_iterator DI = defs.find(R);

           if(DI != defs.end())
           {
             defs.erase(DI);
             trivialDefKills[R]++;
           }
           else
             trivialDefKills[R] = 100; // don't use
         }
       // record all defs in this instruction
       II = BI->operands_begin();
       IE = BI->operands_end();
       for(; II != IE; II++)
         if(II->isReg() && II->isDef())
           defs.insert(II->getReg());
      }
    }

    std::unordered_map<unsigned, unsigned>::const_iterator DKI = trivialDefKills.begin(),
        DKE = trivialDefKills.end();

    for(; DKI != DKE; DKI++)
      if(DKI->second == 1)
        tdkRegs->insert(DKI->first);
  }

#if VRRPROF
  llog("starting conflict graph construction... (%d)\n", (int)time(NULL));
#endif

  std::unordered_set<unsigned>::const_iterator tdkE = tdkRegs->end();

  std::unordered_set<unsigned> *okRegs = NULL;

  if(!setjmpSafe)
    okRegs = tdkRegs;

  MachineRegisterInfo *RI = &(MF.getRegInfo());
  // will eventually hold a virt register coloring for this function
  ConflictGraph::Coloring coloring;

  {
    ConflictGraph cg;
    LiveIntervals &LIS = getAnalysis<LiveIntervals>();
    LiveIntervals::const_iterator I = LIS.begin(), E = LIS.end();

    // check every possible LiveInterval, LiveInterval pair of the same
    // register class for overlap and add overlaps to the conflict graph
    // also, treat trivially def-kill-ed regs and not trivially def-kill-ed
    // regs as conflicting so they end up using different VRs -- this makes
    // stackification easier later in the toolchain
    for(; I != E; I++)
    {
      unsigned R = I->first;

      if(TargetRegisterInfo::isPhysicalRegister(R))
        continue;
      if(okRegs && okRegs->find(R) == okRegs->end())
        continue;
      // leave singly-defined MoveImm regs for later coalescing
      if(immRegs && immRegs->find(R) != immRegs->end())
        continue;

//      const TargetRegisterClass *RC = RI->getRegClass(R);
      const LiveInterval *LI = I->second;

      if(LI->empty())
        continue;

      cg.addVertex(R);

      bool notTDK = tdkRegs->find(R) == tdkE;
      LiveIntervals::const_iterator I1 = I;

      I1++;
					
      for(; I1 != E; I1++)
      {
        unsigned R1 = I1->first;

        if(TargetRegisterInfo::isPhysicalRegister(R1))
          continue;
        if(okRegs && okRegs->find(R1) == okRegs->end())
          continue;
        // leave singly-defined MoveImm regs for later coalescing
        if(immRegs && immRegs->find(R1) != immRegs->end())
          continue;

/* Don't bother checked RC -- even though it sounds like an opt, it doesn't speed us up in practice
        const TargetRegisterClass *RC1 = RI->getRegClass(R1);

        if(RC != RC1)
          continue; // different reg class... won't conflict
*/

	const LiveInterval *LI1 = I1->second;

        // conflict if intervals overlap OR they're not both TDK or both NOT TDK
        if(LI->overlaps(*LI1) || notTDK != (tdkRegs->find(R1) == tdkE))
          cg.addEdge(R, R1);
      }
    }

#if VRRPROF
  llog("starting coloring... (%d)\n", (int)time(NULL));
#endif

    cg.color(&coloring);

#if VRRPROF
  llog("starting vreg=>vreg construction... (%d)\n", (int)time(NULL));
#endif

	typedef std::unordered_map<unsigned, unsigned> VRegMap;
	VRegMap Regs;

	// build up map of vreg=>vreg
	{
		std::unordered_map<const TargetRegisterClass *, std::unordered_map<unsigned, unsigned> > RCColor2VReg;

		ConflictGraph::Coloring::const_iterator I = coloring.begin(), E = coloring.end();

		for(; I != E; I++)
		{
			unsigned R = I->first;
			unsigned Color = I->second;
			const TargetRegisterClass *RC = RI->getRegClass(R);
			std::unordered_map<unsigned, unsigned> &Color2VReg = RCColor2VReg[RC];

			VRegMap::const_iterator CI = Color2VReg.find(Color);

			if(CI != Color2VReg.end())
				Regs[R] = CI->second; // seen this color; map it
			else
				Regs[R] = Color2VReg[Color] = R; // first sighting of color; bind to this reg
		}
	}

#if VRRPROF
  llog("starting remap... (%d)\n", (int)time(NULL));
#endif


	// remap regs
	{
		VRegMap::const_iterator I = Regs.begin(), E = Regs.end();

		for(; I != E; I++)
			if(I->first != I->second)
			{
				RI->replaceRegWith(I->first, I->second);
				Changed = true;
			}
	}
  }

#if VRRPROF
  llog("done... (%d)\n", (int)time(NULL));
#endif

  return Changed;
}