Quick compiler, out of registers fix

It turns out that the register pool sanity checker was not
working as expected, leaving some inconsistencies unreported.
This could result in "out of registers" failures, as well
as other more subtle problems.

This CL fixes the sanity checker, adds a lot more check and cleans
up the previously undetected episodes of insanity.

Cherry-pick of internal change 468162

Change-Id: Id2da97e99105a4c272c5fd256205a94b904ecea8
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 3201b60..687c41d 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -339,23 +339,35 @@
       bool IsDead() { return (master_->liveness_ & storage_mask_) == 0; }
       // Liveness of this view matches.  Note: not equivalent to !IsDead().
       bool IsLive() { return (master_->liveness_ & storage_mask_) == storage_mask_; }
-      void MarkLive() { master_->liveness_ |= storage_mask_; }
+      void MarkLive(int s_reg) {
+        // TODO: Anything useful to assert here?
+        s_reg_ = s_reg;
+        master_->liveness_ |= storage_mask_;
+      }
       void MarkDead() {
-        master_->liveness_ &= ~storage_mask_;
-        SetSReg(INVALID_SREG);
+        if (SReg() != INVALID_SREG) {
+          s_reg_ = INVALID_SREG;
+          master_->liveness_ &= ~storage_mask_;
+          ResetDefBody();
+        }
       }
       RegStorage GetReg() { return reg_; }
       void SetReg(RegStorage reg) { reg_ = reg; }
       bool IsTemp() { return is_temp_; }
       void SetIsTemp(bool val) { is_temp_ = val; }
       bool IsWide() { return wide_value_; }
-      void SetIsWide(bool val) { wide_value_ = val; }
+      void SetIsWide(bool val) {
+        wide_value_ = val;
+        if (!val) {
+          // If not wide, reset partner to self.
+          SetPartner(GetReg());
+        }
+      }
       bool IsDirty() { return dirty_; }
       void SetIsDirty(bool val) { dirty_ = val; }
       RegStorage Partner() { return partner_; }
       void SetPartner(RegStorage partner) { partner_ = partner; }
-      int SReg() { return s_reg_; }
-      void SetSReg(int s_reg) { s_reg_ = s_reg; }
+      int SReg() { return (!IsTemp() || IsLive()) ? s_reg_ : INVALID_SREG; }
       uint64_t DefUseMask() { return def_use_mask_; }
       void SetDefUseMask(uint64_t def_use_mask) { def_use_mask_ = def_use_mask; }
       RegisterInfo* Master() { return master_; }
@@ -653,6 +665,7 @@
     RegStorage AllocLiveReg(int s_reg, int reg_class, bool wide);
     RegStorage FindLiveReg(GrowableArray<RegisterInfo*> &regs, int s_reg);
     void FreeTemp(RegStorage reg);
+    void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free);
     bool IsLive(RegStorage reg);
     bool IsTemp(RegStorage reg);
     bool IsPromoted(RegStorage reg);
@@ -671,10 +684,10 @@
     void FlushAllRegs();
     bool RegClassMatches(int reg_class, RegStorage reg);
     void MarkLive(RegLocation loc);
-    void MarkLiveReg(RegStorage reg, int s_reg);
     void MarkTemp(RegStorage reg);
     void UnmarkTemp(RegStorage reg);
     void MarkWide(RegStorage reg);
+    void MarkNarrow(RegStorage reg);
     void MarkClean(RegLocation loc);
     void MarkDirty(RegLocation loc);
     void MarkInUse(RegStorage reg);
@@ -1074,7 +1087,6 @@
     virtual void AdjustSpillMask() = 0;
     virtual void ClobberCallerSave() = 0;
     virtual void FreeCallTemps() = 0;
-    virtual void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) = 0;
     virtual void LockCallTemps() = 0;
     virtual void MarkPreservedSingle(int v_reg, RegStorage reg) = 0;
     virtual void MarkPreservedDouble(int v_reg, RegStorage reg) = 0;