/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * This file contains register alloction support and is intended to be
 * included by:
 *
 *        Codegen-$(TARGET_ARCH_VARIANT).c
 *
 */

#include "../CompilerUtility.h"
#include "../CompilerIR.h"
#include "../Dataflow.h"
#include "Ralloc.h"

namespace art {

/*
 * Free all allocated temps in the temp pools.  Note that this does
 * not affect the "liveness" of a temp register, which will stay
 * live until it is either explicitly killed or reallocated.
 */
extern void oatResetRegPool(CompilationUnit* cUnit)
{
  int i;
  for (i=0; i < cUnit->regPool->numCoreRegs; i++) {
    if (cUnit->regPool->coreRegs[i].isTemp)
      cUnit->regPool->coreRegs[i].inUse = false;
  }
  for (i=0; i < cUnit->regPool->numFPRegs; i++) {
    if (cUnit->regPool->FPRegs[i].isTemp)
      cUnit->regPool->FPRegs[i].inUse = false;
  }
}

 /*
  * Set up temp & preserved register pools specialized by target.
  * Note: numRegs may be zero.
  */
extern void oatInitPool(RegisterInfo* regs, int* regNums, int num)
{
  int i;
  for (i=0; i < num; i++) {
    regs[i].reg = regNums[i];
    regs[i].inUse = false;
    regs[i].isTemp = false;
    regs[i].pair = false;
    regs[i].live = false;
    regs[i].dirty = false;
    regs[i].sReg = INVALID_SREG;
  }
}

void dumpRegPool(RegisterInfo* p, int numRegs)
{
  LOG(INFO) << "================================================";
  for (int i = 0; i < numRegs; i++) {
    LOG(INFO) << StringPrintf(
        "R[%d]: T:%d, U:%d, P:%d, p:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x",
        p[i].reg, p[i].isTemp, p[i].inUse, p[i].pair, p[i].partner,
        p[i].live, p[i].dirty, p[i].sReg,(int)p[i].defStart,
        (int)p[i].defEnd);
  }
  LOG(INFO) << "================================================";
}

void oatDumpCoreRegPool(CompilationUnit* cUnit)
{
  dumpRegPool(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs);
}

void oatDumpFpRegPool(CompilationUnit* cUnit)
{
  dumpRegPool(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs);
}

/* Mark a temp register as dead.  Does not affect allocation state. */
static inline void clobberBody(CompilationUnit *cUnit, RegisterInfo* p)
{
  if (p->isTemp) {
    DCHECK(!(p->live && p->dirty))  << "Live & dirty temp in clobber";
    p->live = false;
    p->sReg = INVALID_SREG;
    p->defStart = NULL;
    p->defEnd = NULL;
    if (p->pair) {
      p->pair = false;
      oatClobber(cUnit, p->partner);
    }
  }
}

/* Mark a temp register as dead.  Does not affect allocation state. */
void oatClobber(CompilationUnit* cUnit, int reg)
{
  clobberBody(cUnit, oatGetRegInfo(cUnit, reg));
}

void clobberSRegBody(RegisterInfo* p, int numRegs, int sReg)
{
  int i;
  for (i=0; i< numRegs; i++) {
    if (p[i].sReg == sReg) {
      if (p[i].isTemp) {
        p[i].live = false;
      }
      p[i].defStart = NULL;
      p[i].defEnd = NULL;
    }
  }
}

/* Clobber any temp associated with an sReg.  Could be in either class */
extern void oatClobberSReg(CompilationUnit* cUnit, int sReg)
{
#ifndef NDEBUG
  /* Reset live temp tracking sanity checker */
  if (sReg == cUnit->liveSReg) {
    cUnit->liveSReg = INVALID_SREG;
  }
#endif
  clobberSRegBody(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs, sReg);
  clobberSRegBody(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs, sReg);
}

/*
 * SSA names associated with the initial definitions of Dalvik
 * registers are the same as the Dalvik register number (and
 * thus take the same position in the promotionMap.  However,
 * the special Method* and compiler temp resisters use negative
 * vReg numbers to distinguish them and can have an arbitrary
 * ssa name (above the last original Dalvik register).  This function
 * maps SSA names to positions in the promotionMap array.
 */
int SRegToPMap(CompilationUnit* cUnit, int sReg)
{
  DCHECK_LT(sReg, cUnit->numSSARegs);
  DCHECK_GE(sReg, 0);
  int vReg = SRegToVReg(cUnit, sReg);
  if (vReg >= 0) {
    DCHECK_LT(vReg, cUnit->numDalvikRegisters);
    return vReg;
  } else {
    int pos = std::abs(vReg) - std::abs(SSA_METHOD_BASEREG);
    DCHECK_LE(pos, cUnit->numCompilerTemps);
    return cUnit->numDalvikRegisters + pos;
  }
}

/* Reserve a callee-save register.  Return -1 if none available */
extern int oatAllocPreservedCoreReg(CompilationUnit* cUnit, int sReg)
{
  int res = -1;
  RegisterInfo* coreRegs = cUnit->regPool->coreRegs;
  for (int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
    if (!coreRegs[i].isTemp && !coreRegs[i].inUse) {
      int vReg = SRegToVReg(cUnit, sReg);
      int pMapIdx = SRegToPMap(cUnit, sReg);
      res = coreRegs[i].reg;
      coreRegs[i].inUse = true;
      cUnit->coreSpillMask |= (1 << res);
      cUnit->coreVmapTable.push_back(vReg);
      cUnit->numCoreSpills++;
      cUnit->promotionMap[pMapIdx].coreLocation = kLocPhysReg;
      cUnit->promotionMap[pMapIdx].coreReg = res;
      break;
    }
  }
  return res;
}

/*
 * Reserve a callee-save fp single register.  Try to fullfill request for
 * even/odd  allocation, but go ahead and allocate anything if not
 * available.  If nothing's available, return -1.
 */
int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
{
  int res = -1;
  RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
  for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
    if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
      ((FPRegs[i].reg & 0x1) == 0) == even) {
      int vReg = SRegToVReg(cUnit, sReg);
      int pMapIdx = SRegToPMap(cUnit, sReg);
      res = FPRegs[i].reg;
      FPRegs[i].inUse = true;
      oatMarkPreservedSingle(cUnit, vReg, res);
      cUnit->promotionMap[pMapIdx].fpLocation = kLocPhysReg;
      cUnit->promotionMap[pMapIdx].fpReg = res;
      break;
    }
  }
  return res;
}

/*
 * Somewhat messy code here.  We want to allocate a pair of contiguous
 * physical single-precision floating point registers starting with
 * an even numbered reg.  It is possible that the paired sReg (sReg+1)
 * has already been allocated - try to fit if possible.  Fail to
 * allocate if we can't meet the requirements for the pair of
 * sReg<=sX[even] & (sReg+1)<= sX+1.
 */
int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
{
  int res = -1; // Assume failure
  int vReg = SRegToVReg(cUnit, sReg);
  int pMapIdx = SRegToPMap(cUnit, sReg);
  if (cUnit->promotionMap[pMapIdx+1].fpLocation == kLocPhysReg) {
    // Upper reg is already allocated.  Can we fit?
    int highReg = cUnit->promotionMap[pMapIdx+1].fpReg;
    if ((highReg & 1) == 0) {
      // High reg is even - fail.
      return res;
    }
    // Is the low reg of the pair free?
    RegisterInfo* p = oatGetRegInfo(cUnit, highReg-1);
    if (p->inUse || p->isTemp) {
      // Already allocated or not preserved - fail.
      return res;
    }
    // OK - good to go.
    res = p->reg;
    p->inUse = true;
    DCHECK_EQ((res & 1), 0);
    oatMarkPreservedSingle(cUnit, vReg, res);
  } else {
    RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
    for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
      if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
        ((FPRegs[i].reg & 0x1) == 0x0) &&
        !FPRegs[i+1].isTemp && !FPRegs[i+1].inUse &&
        ((FPRegs[i+1].reg & 0x1) == 0x1) &&
        (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
        res = FPRegs[i].reg;
        FPRegs[i].inUse = true;
        oatMarkPreservedSingle(cUnit, vReg, res);
        FPRegs[i+1].inUse = true;
        DCHECK_EQ(res + 1, FPRegs[i+1].reg);
        oatMarkPreservedSingle(cUnit, vReg+1, res+1);
        break;
      }
    }
  }
  if (res != -1) {
    cUnit->promotionMap[pMapIdx].fpLocation = kLocPhysReg;
    cUnit->promotionMap[pMapIdx].fpReg = res;
    cUnit->promotionMap[pMapIdx+1].fpLocation = kLocPhysReg;
    cUnit->promotionMap[pMapIdx+1].fpReg = res + 1;
  }
  return res;
}


/*
 * Reserve a callee-save fp register.   If this register can be used
 * as the first of a double, attempt to allocate an even pair of fp
 * single regs (but if can't still attempt to allocate a single, preferring
 * first to allocate an odd register.
 */
extern int oatAllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
                  bool doubleStart)
{
  int res = -1;
  if (doubleStart) {
    res = allocPreservedDouble(cUnit, sReg);
  }
  if (res == -1) {
    res = allocPreservedSingle(cUnit, sReg, false /* try odd # */);
  }
  if (res == -1)
    res = allocPreservedSingle(cUnit, sReg, true /* try even # */);
  return res;
}

int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
          int* nextTemp, bool required)
{
  int i;
  int next = *nextTemp;
  for (i=0; i< numRegs; i++) {
    if (next >= numRegs)
      next = 0;
    if (p[next].isTemp && !p[next].inUse && !p[next].live) {
      oatClobber(cUnit, p[next].reg);
      p[next].inUse = true;
      p[next].pair = false;
      *nextTemp = next + 1;
      return p[next].reg;
    }
    next++;
  }
  next = *nextTemp;
  for (i=0; i< numRegs; i++) {
    if (next >= numRegs)
      next = 0;
    if (p[next].isTemp && !p[next].inUse) {
      oatClobber(cUnit, p[next].reg);
      p[next].inUse = true;
      p[next].pair = false;
      *nextTemp = next + 1;
      return p[next].reg;
    }
    next++;
  }
  if (required) {
    oatCodegenDump(cUnit);
    dumpRegPool(cUnit->regPool->coreRegs,
          cUnit->regPool->numCoreRegs);
    LOG(FATAL) << "No free temp registers";
  }
  return -1;  // No register available
}

//REDO: too many assumptions.
extern int oatAllocTempDouble(CompilationUnit* cUnit)
{
  RegisterInfo* p = cUnit->regPool->FPRegs;
  int numRegs = cUnit->regPool->numFPRegs;
  /* Start looking at an even reg */
  int next = cUnit->regPool->nextFPReg & ~0x1;

  // First try to avoid allocating live registers
  for (int i=0; i < numRegs; i+=2) {
    if (next >= numRegs)
      next = 0;
    if ((p[next].isTemp && !p[next].inUse && !p[next].live) &&
      (p[next+1].isTemp && !p[next+1].inUse && !p[next+1].live)) {
      oatClobber(cUnit, p[next].reg);
      oatClobber(cUnit, p[next+1].reg);
      p[next].inUse = true;
      p[next+1].inUse = true;
      DCHECK_EQ((p[next].reg+1), p[next+1].reg);
      DCHECK_EQ((p[next].reg & 0x1), 0);
      cUnit->regPool->nextFPReg = next + 2;
      if (cUnit->regPool->nextFPReg >= numRegs) {
        cUnit->regPool->nextFPReg = 0;
      }
      return p[next].reg;
    }
    next += 2;
  }
  next = cUnit->regPool->nextFPReg & ~0x1;

  // No choice - find a pair and kill it.
  for (int i=0; i < numRegs; i+=2) {
    if (next >= numRegs)
      next = 0;
    if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
      !p[next+1].inUse) {
      oatClobber(cUnit, p[next].reg);
      oatClobber(cUnit, p[next+1].reg);
      p[next].inUse = true;
      p[next+1].inUse = true;
      DCHECK_EQ((p[next].reg+1), p[next+1].reg);
      DCHECK_EQ((p[next].reg & 0x1), 0);
      cUnit->regPool->nextFPReg = next + 2;
      if (cUnit->regPool->nextFPReg >= numRegs) {
        cUnit->regPool->nextFPReg = 0;
      }
      return p[next].reg;
    }
    next += 2;
  }
  LOG(FATAL) << "No free temp registers (pair)";
  return -1;
}

/* Return a temp if one is available, -1 otherwise */
extern int oatAllocFreeTemp(CompilationUnit* cUnit)
{
  return allocTempBody(cUnit, cUnit->regPool->coreRegs,
             cUnit->regPool->numCoreRegs,
             &cUnit->regPool->nextCoreReg, true);
}

extern int oatAllocTemp(CompilationUnit* cUnit)
{
  return allocTempBody(cUnit, cUnit->regPool->coreRegs,
             cUnit->regPool->numCoreRegs,
             &cUnit->regPool->nextCoreReg, true);
}

extern int oatAllocTempFloat(CompilationUnit* cUnit)
{
  return allocTempBody(cUnit, cUnit->regPool->FPRegs,
             cUnit->regPool->numFPRegs,
             &cUnit->regPool->nextFPReg, true);
}

RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
{
  int i;
  if (sReg == -1)
    return NULL;
  for (i=0; i < numRegs; i++) {
    if (p[i].live && (p[i].sReg == sReg)) {
      if (p[i].isTemp)
        p[i].inUse = true;
      return &p[i];
    }
  }
  return NULL;
}

RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg, int regClass)
{
  RegisterInfo* res = NULL;
  switch (regClass) {
    case kAnyReg:
      res = allocLiveBody(cUnit->regPool->FPRegs,
                cUnit->regPool->numFPRegs, sReg);
      if (res)
        break;
      /* Intentional fallthrough */
    case kCoreReg:
      res = allocLiveBody(cUnit->regPool->coreRegs,
                cUnit->regPool->numCoreRegs, sReg);
      break;
    case kFPReg:
      res = allocLiveBody(cUnit->regPool->FPRegs,
                cUnit->regPool->numFPRegs, sReg);
      break;
    default:
      LOG(FATAL) << "Invalid register type";
  }
  return res;
}

extern void oatFreeTemp(CompilationUnit* cUnit, int reg)
{
  RegisterInfo* p = cUnit->regPool->coreRegs;
  int numRegs = cUnit->regPool->numCoreRegs;
  int i;
  for (i=0; i< numRegs; i++) {
    if (p[i].reg == reg) {
      if (p[i].isTemp) {
        p[i].inUse = false;
      }
      p[i].pair = false;
      return;
    }
  }
  p = cUnit->regPool->FPRegs;
  numRegs = cUnit->regPool->numFPRegs;
  for (i=0; i< numRegs; i++) {
    if (p[i].reg == reg) {
      if (p[i].isTemp) {
        p[i].inUse = false;
      }
      p[i].pair = false;
      return;
    }
  }
  LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
}

extern RegisterInfo* oatIsLive(CompilationUnit* cUnit, int reg)
{
  RegisterInfo* p = cUnit->regPool->coreRegs;
  int numRegs = cUnit->regPool->numCoreRegs;
  int i;
  for (i=0; i< numRegs; i++) {
    if (p[i].reg == reg) {
      return p[i].live ? &p[i] : NULL;
    }
  }
  p = cUnit->regPool->FPRegs;
  numRegs = cUnit->regPool->numFPRegs;
  for (i=0; i< numRegs; i++) {
    if (p[i].reg == reg) {
      return p[i].live ? &p[i] : NULL;
    }
  }
  return NULL;
}

extern RegisterInfo* oatIsTemp(CompilationUnit* cUnit, int reg)
{
  RegisterInfo* p = oatGetRegInfo(cUnit, reg);
  return (p->isTemp) ? p : NULL;
}

extern RegisterInfo* oatIsPromoted(CompilationUnit* cUnit, int reg)
{
  RegisterInfo* p = oatGetRegInfo(cUnit, reg);
  return (p->isTemp) ? NULL : p;
}

extern bool oatIsDirty(CompilationUnit* cUnit, int reg)
{
  RegisterInfo* p = oatGetRegInfo(cUnit, reg);
  return p->dirty;
}

/*
 * Similar to oatAllocTemp(), but forces the allocation of a specific
 * register.  No check is made to see if the register was previously
 * allocated.  Use with caution.
 */
extern void oatLockTemp(CompilationUnit* cUnit, int reg)
{
  RegisterInfo* p = cUnit->regPool->coreRegs;
  int numRegs = cUnit->regPool->numCoreRegs;
  int i;
  for (i=0; i< numRegs; i++) {
    if (p[i].reg == reg) {
      DCHECK(p[i].isTemp);
      p[i].inUse = true;
      p[i].live = false;
      return;
    }
  }
  p = cUnit->regPool->FPRegs;
  numRegs = cUnit->regPool->numFPRegs;
  for (i=0; i< numRegs; i++) {
    if (p[i].reg == reg) {
      DCHECK(p[i].isTemp);
      p[i].inUse = true;
      p[i].live = false;
      return;
    }
  }
  LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
}

static inline void resetDefBody(RegisterInfo* p)
{
  p->defStart = NULL;
  p->defEnd = NULL;
}

extern void oatResetDef(CompilationUnit* cUnit, int reg)
{
  resetDefBody(oatGetRegInfo(cUnit, reg));
}

void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
             int sReg1, int sReg2)
{
  if (start && finish) {
    LIR *p;
    DCHECK_EQ(sReg1, sReg2);
    for (p = start; ;p = p->next) {
      oatNopLIR(p);
      if (p == finish)
        break;
    }
  }
}

/*
 * Mark the beginning and end LIR of a def sequence.  Note that
 * on entry start points to the LIR prior to the beginning of the
 * sequence.
 */
extern void oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
             LIR *start, LIR *finish)
{
  DCHECK(!rl.wide);
  DCHECK(start && start->next);
  DCHECK(finish);
  RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
  p->defStart = start->next;
  p->defEnd = finish;
}

/*
 * Mark the beginning and end LIR of a def sequence.  Note that
 * on entry start points to the LIR prior to the beginning of the
 * sequence.
 */
extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
               LIR *start, LIR *finish)
{
  DCHECK(rl.wide);
  DCHECK(start && start->next);
  DCHECK(finish);
  RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
  oatResetDef(cUnit, rl.highReg);  // Only track low of pair
  p->defStart = start->next;
  p->defEnd = finish;
}

extern RegLocation oatWideToNarrow(CompilationUnit* cUnit, RegLocation rl)
{
  DCHECK(rl.wide);
  if (rl.location == kLocPhysReg) {
    RegisterInfo* infoLo = oatGetRegInfo(cUnit, rl.lowReg);
    RegisterInfo* infoHi = oatGetRegInfo(cUnit, rl.highReg);
    if (infoLo->isTemp) {
      infoLo->pair = false;
      infoLo->defStart = NULL;
      infoLo->defEnd = NULL;
    }
    if (infoHi->isTemp) {
      infoHi->pair = false;
      infoHi->defStart = NULL;
      infoHi->defEnd = NULL;
    }
  }
  rl.wide = false;
  return rl;
}

extern void oatResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
{
  DCHECK(!rl.wide);
  RegisterInfo* p = oatIsTemp(cUnit, rl.lowReg);
  if (p && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
    DCHECK(!p->pair);
    nullifyRange(cUnit, p->defStart, p->defEnd, p->sReg, rl.sRegLow);
  }
  oatResetDef(cUnit, rl.lowReg);
}

extern void oatResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
{
  DCHECK(rl.wide);
  RegisterInfo* pLow = oatIsTemp(cUnit, rl.lowReg);
  RegisterInfo* pHigh = oatIsTemp(cUnit, rl.highReg);
  if (pLow && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
    DCHECK(pLow->pair);
    nullifyRange(cUnit, pLow->defStart, pLow->defEnd, pLow->sReg, rl.sRegLow);
  }
  if (pHigh && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
    DCHECK(pHigh->pair);
  }
  oatResetDef(cUnit, rl.lowReg);
  oatResetDef(cUnit, rl.highReg);
}

extern void oatResetDefTracking(CompilationUnit* cUnit)
{
  int i;
  for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
    resetDefBody(&cUnit->regPool->coreRegs[i]);
  }
  for (i=0; i< cUnit->regPool->numFPRegs; i++) {
    resetDefBody(&cUnit->regPool->FPRegs[i]);
  }
}

extern void oatClobberAllRegs(CompilationUnit* cUnit)
{
  int i;
  for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
    clobberBody(cUnit, &cUnit->regPool->coreRegs[i]);
  }
  for (i=0; i< cUnit->regPool->numFPRegs; i++) {
    clobberBody(cUnit, &cUnit->regPool->FPRegs[i]);
  }
}

// Make sure nothing is live and dirty
void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
               int numRegs)
{
  int i;
  for (i=0; i < numRegs; i++) {
    if (info[i].live && info[i].dirty) {
      if (info[i].pair) {
        oatFlushRegWide(cUnit, info[i].reg, info[i].partner);
      } else {
        oatFlushReg(cUnit, info[i].reg);
      }
    }
  }
}

extern void oatFlushAllRegs(CompilationUnit* cUnit)
{
  flushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
           cUnit->regPool->numCoreRegs);
  flushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
           cUnit->regPool->numFPRegs);
  oatClobberAllRegs(cUnit);
}


//TUNING: rewrite all of this reg stuff.  Probably use an attribute table
bool regClassMatches(int regClass, int reg)
{
  if (regClass == kAnyReg) {
    return true;
  } else if (regClass == kCoreReg) {
    return !oatIsFpReg(reg);
  } else {
    return oatIsFpReg(reg);
  }
}

extern void oatMarkLive(CompilationUnit* cUnit, int reg, int sReg)
{
  RegisterInfo* info = oatGetRegInfo(cUnit, reg);
  if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
    return;  /* already live */
  } else if (sReg != INVALID_SREG) {
    oatClobberSReg(cUnit, sReg);
    if (info->isTemp) {
      info->live = true;
    }
  } else {
    /* Can't be live if no associated sReg */
    DCHECK(info->isTemp);
    info->live = false;
  }
  info->sReg = sReg;
}

extern void oatMarkTemp(CompilationUnit* cUnit, int reg)
{
  RegisterInfo* info = oatGetRegInfo(cUnit, reg);
  info->isTemp = true;
}

extern void oatUnmarkTemp(CompilationUnit* cUnit, int reg)
{
  RegisterInfo* info = oatGetRegInfo(cUnit, reg);
  info->isTemp = false;
}

extern void oatMarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
{
  RegisterInfo* infoLo = oatGetRegInfo(cUnit, lowReg);
  RegisterInfo* infoHi = oatGetRegInfo(cUnit, highReg);
  infoLo->pair = infoHi->pair = true;
  infoLo->partner = highReg;
  infoHi->partner = lowReg;
}

extern void oatMarkClean(CompilationUnit* cUnit, RegLocation loc)
{
  RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
  info->dirty = false;
  if (loc.wide) {
    info = oatGetRegInfo(cUnit, loc.highReg);
    info->dirty = false;
  }
}

extern void oatMarkDirty(CompilationUnit* cUnit, RegLocation loc)
{
  if (loc.home) {
    // If already home, can't be dirty
    return;
  }
  RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
  info->dirty = true;
  if (loc.wide) {
    info = oatGetRegInfo(cUnit, loc.highReg);
    info->dirty = true;
  }
}

extern void oatMarkInUse(CompilationUnit* cUnit, int reg)
{
    RegisterInfo* info = oatGetRegInfo(cUnit, reg);
    info->inUse = true;
}

void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
{
  RegisterInfo* newInfo = oatGetRegInfo(cUnit, newReg);
  RegisterInfo* oldInfo = oatGetRegInfo(cUnit, oldReg);
  // Target temp status must not change
  bool isTemp = newInfo->isTemp;
  *newInfo = *oldInfo;
  // Restore target's temp status
  newInfo->isTemp = isTemp;
  newInfo->reg = newReg;
}

/*
 * Return an updated location record with current in-register status.
 * If the value lives in live temps, reflect that fact.  No code
 * is generated.  If the live value is part of an older pair,
 * clobber both low and high.
 * TUNING: clobbering both is a bit heavy-handed, but the alternative
 * is a bit complex when dealing with FP regs.  Examine code to see
 * if it's worthwhile trying to be more clever here.
 */

extern RegLocation oatUpdateLoc(CompilationUnit* cUnit, RegLocation loc)
{
  DCHECK(!loc.wide);
  DCHECK(oatCheckCorePoolSanity(cUnit));
  if (loc.location != kLocPhysReg) {
    DCHECK((loc.location == kLocDalvikFrame) ||
         (loc.location == kLocCompilerTemp));
    RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
    if (infoLo) {
      if (infoLo->pair) {
        oatClobber(cUnit, infoLo->reg);
        oatClobber(cUnit, infoLo->partner);
        oatFreeTemp(cUnit, infoLo->reg);
      } else {
        loc.lowReg = infoLo->reg;
        loc.location = kLocPhysReg;
      }
    }
  }

  return loc;
}

bool oatCheckCorePoolSanity(CompilationUnit* cUnit)
{
   for (static int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
     if (cUnit->regPool->coreRegs[i].pair) {
       static int myReg = cUnit->regPool->coreRegs[i].reg;
       static int mySreg = cUnit->regPool->coreRegs[i].sReg;
       static int partnerReg = cUnit->regPool->coreRegs[i].partner;
       static RegisterInfo* partner = oatGetRegInfo(cUnit, partnerReg);
       DCHECK(partner != NULL);
       DCHECK(partner->pair);
       DCHECK_EQ(myReg, partner->partner);
       static int partnerSreg = partner->sReg;
       if (mySreg == INVALID_SREG) {
         DCHECK_EQ(partnerSreg, INVALID_SREG);
       } else {
         int diff = mySreg - partnerSreg;
         DCHECK((diff == -1) || (diff == 1));
       }
     }
     if (!cUnit->regPool->coreRegs[i].live) {
       DCHECK(cUnit->regPool->coreRegs[i].defStart == NULL);
       DCHECK(cUnit->regPool->coreRegs[i].defEnd == NULL);
     }
   }
   return true;
}

/* see comments for updateLoc */
extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit, RegLocation loc)
{
  DCHECK(loc.wide);
  DCHECK(oatCheckCorePoolSanity(cUnit));
  if (loc.location != kLocPhysReg) {
    DCHECK((loc.location == kLocDalvikFrame) ||
         (loc.location == kLocCompilerTemp));
    // Are the dalvik regs already live in physical registers?
    RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
    RegisterInfo* infoHi = allocLive(cUnit,
        oatSRegHi(loc.sRegLow), kAnyReg);
    bool match = true;
    match = match && (infoLo != NULL);
    match = match && (infoHi != NULL);
    // Are they both core or both FP?
    match = match && (oatIsFpReg(infoLo->reg) == oatIsFpReg(infoHi->reg));
    // If a pair of floating point singles, are they properly aligned?
    if (match && oatIsFpReg(infoLo->reg)) {
      match &= ((infoLo->reg & 0x1) == 0);
      match &= ((infoHi->reg - infoLo->reg) == 1);
    }
    // If previously used as a pair, it is the same pair?
    if (match && (infoLo->pair || infoHi->pair)) {
      match = (infoLo->pair == infoHi->pair);
      match &= ((infoLo->reg == infoHi->partner) &&
            (infoHi->reg == infoLo->partner));
    }
    if (match) {
      // Can reuse - update the register usage info
      loc.lowReg = infoLo->reg;
      loc.highReg = infoHi->reg;
      loc.location = kLocPhysReg;
      oatMarkPair(cUnit, loc.lowReg, loc.highReg);
      DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
      return loc;
    }
    // Can't easily reuse - clobber and free any overlaps
    if (infoLo) {
      oatClobber(cUnit, infoLo->reg);
      oatFreeTemp(cUnit, infoLo->reg);
      if (infoLo->pair)
        oatClobber(cUnit, infoLo->partner);
    }
    if (infoHi) {
      oatClobber(cUnit, infoHi->reg);
      oatFreeTemp(cUnit, infoHi->reg);
      if (infoHi->pair)
        oatClobber(cUnit, infoHi->partner);
    }
  }
  return loc;
}


/* For use in cases we don't know (or care) width */
extern RegLocation oatUpdateRawLoc(CompilationUnit* cUnit, RegLocation loc)
{
  if (loc.wide)
    return oatUpdateLocWide(cUnit, loc);
  else
    return oatUpdateLoc(cUnit, loc);
}

RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
            int regClass, bool update)
{
  DCHECK(loc.wide);
  int newRegs;
  int lowReg;
  int highReg;

  loc = oatUpdateLocWide(cUnit, loc);

  /* If already in registers, we can assume proper form.  Right reg class? */
  if (loc.location == kLocPhysReg) {
    DCHECK_EQ(oatIsFpReg(loc.lowReg), oatIsFpReg(loc.highReg));
    DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
    if (!regClassMatches(regClass, loc.lowReg)) {
      /* Wrong register class.  Reallocate and copy */
      newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
      lowReg = newRegs & 0xff;
      highReg = (newRegs >> 8) & 0xff;
      oatRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
                   loc.highReg);
      copyRegInfo(cUnit, lowReg, loc.lowReg);
      copyRegInfo(cUnit, highReg, loc.highReg);
      oatClobber(cUnit, loc.lowReg);
      oatClobber(cUnit, loc.highReg);
      loc.lowReg = lowReg;
      loc.highReg = highReg;
      oatMarkPair(cUnit, loc.lowReg, loc.highReg);
      DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
    }
    return loc;
  }

  DCHECK_NE(loc.sRegLow, INVALID_SREG);
  DCHECK_NE(oatSRegHi(loc.sRegLow), INVALID_SREG);

  newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
  loc.lowReg = newRegs & 0xff;
  loc.highReg = (newRegs >> 8) & 0xff;

  oatMarkPair(cUnit, loc.lowReg, loc.highReg);
  if (update) {
    loc.location = kLocPhysReg;
    oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
    oatMarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
  }
  DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
  return loc;
}

extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc,
                int regClass, bool update)
{
  int newReg;

  if (loc.wide)
    return evalLocWide(cUnit, loc, regClass, update);

  loc = oatUpdateLoc(cUnit, loc);

  if (loc.location == kLocPhysReg) {
    if (!regClassMatches(regClass, loc.lowReg)) {
      /* Wrong register class.  Realloc, copy and transfer ownership */
      newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
      oatRegCopy(cUnit, newReg, loc.lowReg);
      copyRegInfo(cUnit, newReg, loc.lowReg);
      oatClobber(cUnit, loc.lowReg);
      loc.lowReg = newReg;
    }
    return loc;
  }

  DCHECK_NE(loc.sRegLow, INVALID_SREG);

  newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
  loc.lowReg = newReg;

  if (update) {
    loc.location = kLocPhysReg;
    oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
  }
  return loc;
}

extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
{
  DCHECK(num < mir->ssaRep->numUses);
  RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
  return res;
}
extern RegLocation oatGetRawDest(CompilationUnit* cUnit, MIR* mir)
{
  DCHECK_GT(mir->ssaRep->numDefs, 0);
  RegLocation res = cUnit->regLocation[mir->ssaRep->defs[0]];
  return res;
}
extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir)
{
  RegLocation res = oatGetRawDest(cUnit, mir);
  DCHECK(!res.wide);
  return res;
}
extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num)
{
  RegLocation res = oatGetRawSrc(cUnit, mir, num);
  DCHECK(!res.wide);
  return res;
}
extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir)
{
  RegLocation res = oatGetRawDest(cUnit, mir);
  DCHECK(res.wide);
  return res;
}

extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir,
                 int low)
{
  RegLocation res = oatGetRawSrc(cUnit, mir, low);
  DCHECK(res.wide);
  return res;
}

/* USE SSA names to count references of base Dalvik vRegs. */
void oatCountRefs(CompilationUnit *cUnit, BasicBlock* bb,
          RefCounts* coreCounts, RefCounts* fpCounts)
{
  if ((cUnit->disableOpt & (1 << kPromoteRegs)) ||
    !((bb->blockType == kEntryBlock) || (bb->blockType == kExitBlock) ||
      (bb->blockType == kDalvikByteCode))) {
    return;
  }
  for (int i = 0; i < cUnit->numSSARegs;) {
    RegLocation loc = cUnit->regLocation[i];
    RefCounts* counts = loc.fp ? fpCounts : coreCounts;
    int pMapIdx = SRegToPMap(cUnit, loc.sRegLow);
    if (loc.defined) {
      counts[pMapIdx].count += cUnit->useCounts.elemList[i];
    }
    if (loc.wide) {
      if (loc.defined) {
        if (loc.fp) {
          counts[pMapIdx].doubleStart = true;
          counts[pMapIdx+1].count += cUnit->useCounts.elemList[i+1];
        }
      }
      i += 2;
    } else {
      i++;
    }
  }
}

/* qsort callback function, sort descending */
int oatSortCounts(const void *val1, const void *val2)
{
  const RefCounts* op1 = (const RefCounts*)val1;
  const RefCounts* op2 = (const RefCounts*)val2;
  return (op1->count == op2->count) ? 0 : (op1->count < op2->count ? 1 : -1);
}

void oatDumpCounts(const RefCounts* arr, int size, const char* msg)
{
  LOG(INFO) << msg;
  for (int i = 0; i < size; i++) {
    LOG(INFO) << "sReg[" << arr[i].sReg << "]: " << arr[i].count;
  }
}

/*
 * Note: some portions of this code required even if the kPromoteRegs
 * optimization is disabled.
 */
extern void oatDoPromotion(CompilationUnit* cUnit)
{
  int regBias = cUnit->numCompilerTemps + 1;
  int dalvikRegs = cUnit->numDalvikRegisters;
  int numRegs = dalvikRegs + regBias;
  const int promotionThreshold = 2;

  // Allow target code to add any special registers
  oatAdjustSpillMask(cUnit);

  /*
   * Simple register promotion. Just do a static count of the uses
   * of Dalvik registers.  Note that we examine the SSA names, but
   * count based on original Dalvik register name.  Count refs
   * separately based on type in order to give allocation
   * preference to fp doubles - which must be allocated sequential
   * physical single fp registers started with an even-numbered
   * reg.
   * TUNING: replace with linear scan once we have the ability
   * to describe register live ranges for GC.
   */
  RefCounts *coreRegs = (RefCounts *)
      oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
  RefCounts *fpRegs = (RefCounts *)
      oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
  // Set ssa names for original Dalvik registers
  for (int i = 0; i < dalvikRegs; i++) {
    coreRegs[i].sReg = fpRegs[i].sReg = i;
  }
  // Set ssa name for Method*
  coreRegs[dalvikRegs].sReg = cUnit->methodSReg;
  fpRegs[dalvikRegs].sReg = cUnit->methodSReg;  // For consistecy
  // Set ssa names for compilerTemps
  for (int i = 1; i <= cUnit->numCompilerTemps; i++) {
    CompilerTemp* ct = (CompilerTemp*)cUnit->compilerTemps.elemList[i];
    coreRegs[dalvikRegs + i].sReg = ct->sReg;
    fpRegs[dalvikRegs + i].sReg = ct->sReg;
  }

  GrowableListIterator iterator;
  oatGrowableListIteratorInit(&cUnit->blockList, &iterator);
  while (true) {
    BasicBlock* bb;
    bb = (BasicBlock*)oatGrowableListIteratorNext(&iterator);
    if (bb == NULL) break;
    oatCountRefs(cUnit, bb, coreRegs, fpRegs);
  }

  /*
   * Ideally, we'd allocate doubles starting with an even-numbered
   * register.  Bias the counts to try to allocate any vreg that's
   * used as the start of a pair first.
   */
  for (int i = 0; i < numRegs; i++) {
    if (fpRegs[i].doubleStart) {
      fpRegs[i].count *= 2;
    }
  }

  // Sort the count arrays
  qsort(coreRegs, numRegs, sizeof(RefCounts), oatSortCounts);
  qsort(fpRegs, numRegs, sizeof(RefCounts), oatSortCounts);

  if (cUnit->printMe) {
    oatDumpCounts(coreRegs, numRegs, "Core regs after sort");
    oatDumpCounts(fpRegs, numRegs, "Fp regs after sort");
  }

  if (!(cUnit->disableOpt & (1 << kPromoteRegs))) {
    // Promote fpRegs
    for (int i = 0; (i < numRegs) &&
            (fpRegs[i].count >= promotionThreshold ); i++) {
      int pMapIdx = SRegToPMap(cUnit, fpRegs[i].sReg);
      if (cUnit->promotionMap[pMapIdx].fpLocation != kLocPhysReg) {
        int reg = oatAllocPreservedFPReg(cUnit, fpRegs[i].sReg,
          fpRegs[i].doubleStart);
        if (reg < 0) {
          break;  // No more left
        }
      }
    }

    // Promote core regs
    for (int i = 0; (i < numRegs) &&
            (coreRegs[i].count > promotionThreshold); i++) {
      int pMapIdx = SRegToPMap(cUnit, coreRegs[i].sReg);
      if (cUnit->promotionMap[pMapIdx].coreLocation !=
          kLocPhysReg) {
        int reg = oatAllocPreservedCoreReg(cUnit, coreRegs[i].sReg);
        if (reg < 0) {
           break;  // No more left
        }
      }
    }
  } else if (cUnit->qdMode) {
    oatAllocPreservedCoreReg(cUnit, cUnit->methodSReg);
    for (int i = 0; i < numRegs; i++) {
      int reg = oatAllocPreservedCoreReg(cUnit, i);
      if (reg < 0) {
         break;  // No more left
      }
    }
  }


  // Now, update SSA names to new home locations
  for (int i = 0; i < cUnit->numSSARegs; i++) {
    RegLocation *curr = &cUnit->regLocation[i];
    int pMapIdx = SRegToPMap(cUnit, curr->sRegLow);
    if (!curr->wide) {
      if (curr->fp) {
        if (cUnit->promotionMap[pMapIdx].fpLocation == kLocPhysReg) {
          curr->location = kLocPhysReg;
          curr->lowReg = cUnit->promotionMap[pMapIdx].fpReg;
          curr->home = true;
        }
      } else {
        if (cUnit->promotionMap[pMapIdx].coreLocation == kLocPhysReg) {
          curr->location = kLocPhysReg;
          curr->lowReg = cUnit->promotionMap[pMapIdx].coreReg;
          curr->home = true;
        }
      }
      curr->highReg = INVALID_REG;
    } else {
      if (curr->highWord) {
        continue;
      }
      if (curr->fp) {
        if ((cUnit->promotionMap[pMapIdx].fpLocation == kLocPhysReg) &&
          (cUnit->promotionMap[pMapIdx+1].fpLocation ==
          kLocPhysReg)) {
          int lowReg = cUnit->promotionMap[pMapIdx].fpReg;
          int highReg = cUnit->promotionMap[pMapIdx+1].fpReg;
          // Doubles require pair of singles starting at even reg
          if (((lowReg & 0x1) == 0) && ((lowReg + 1) == highReg)) {
            curr->location = kLocPhysReg;
            curr->lowReg = lowReg;
            curr->highReg = highReg;
            curr->home = true;
          }
        }
      } else {
        if ((cUnit->promotionMap[pMapIdx].coreLocation == kLocPhysReg)
           && (cUnit->promotionMap[pMapIdx+1].coreLocation ==
           kLocPhysReg)) {
          curr->location = kLocPhysReg;
          curr->lowReg = cUnit->promotionMap[pMapIdx].coreReg;
          curr->highReg = cUnit->promotionMap[pMapIdx+1].coreReg;
          curr->home = true;
        }
      }
    }
  }
}

/* Returns sp-relative offset in bytes for a VReg */
extern int oatVRegOffset(CompilationUnit* cUnit, int vReg)
{
  return StackVisitor::GetVRegOffset(cUnit->code_item, cUnit->coreSpillMask,
                                     cUnit->fpSpillMask, cUnit->frameSize, vReg);
}

/* Returns sp-relative offset in bytes for a SReg */
extern int oatSRegOffset(CompilationUnit* cUnit, int sReg)
{
  return oatVRegOffset(cUnit, SRegToVReg(cUnit, sReg));
}

}  // namespace art
