void storeTV(Vout& v, Vptr dst, Vloc srcLoc, const SSATmp* src) {
  auto const type = src->type();

  if (srcLoc.isFullSIMD()) {
    // The whole TV is stored in a single SIMD reg.
    assertx(RuntimeOption::EvalHHIRAllocSIMDRegs);
    v << storeups{srcLoc.reg(), dst};
    return;
  }

  if (type.needsReg()) {
    assertx(srcLoc.hasReg(1));
    v << storeb{srcLoc.reg(1), dst + TVOFF(m_type)};
  } else {
    v << storeb{v.cns(type.toDataType()), dst + TVOFF(m_type)};
  }

  // We ignore the values of statically nullish types.
  if (src->isA(TNull) || src->isA(TNullptr)) return;

  // Store the value.
  if (src->hasConstVal()) {
    // Skip potential zero-extend if we know the value.
    v << store{v.cns(src->rawVal()), dst + TVOFF(m_data)};
  } else {
    assertx(srcLoc.hasReg(0));
    auto const extended = zeroExtendIfBool(v, src->type(), srcLoc.reg(0));
    v << store{extended, dst + TVOFF(m_data)};
  }
}
void loadTV(Vout& v, const SSATmp* dst, Vloc dstLoc, Vptr src,
            bool aux /* = false */) {
  auto const type = dst->type();

  if (dstLoc.isFullSIMD()) {
    // The whole TV is loaded into a single SIMD reg.
    assertx(RuntimeOption::EvalHHIRAllocSIMDRegs);
    v << loadups{src, dstLoc.reg()};
    return;
  }

  if (type.needsReg()) {
    assertx(dstLoc.hasReg(1));
    if (aux) {
      v << load{src + TVOFF(m_type), dstLoc.reg(1)};
    } else {
      v << loadb{src + TVOFF(m_type), dstLoc.reg(1)};
    }
  }

  if (type <= TBool) {
    v << loadtqb{src + TVOFF(m_data), dstLoc.reg(0)};
  } else {
    v << load{src + TVOFF(m_data), dstLoc.reg(0)};
  }
}
void copyTV(Vout& v, Vreg data, Vreg type, Vloc srcLoc, const SSATmp* src) {
  // SIMD register are not supported here.
  assertx(!srcLoc.isFullSIMD());

  if (src->type().needsReg()) {
    assertx(srcLoc.hasReg(1));
    v << copy{srcLoc.reg(1), type};
  } else {
    v << copy{v.cns(src->type().toDataType()), type};
  }

  // Ignore the values for nulls.
  if (src->isA(TNull)) return;

  if (src->hasConstVal()) {
    // Skip potential zero-extend if we know the value.
    v << copy{v.cns(src->rawVal()), data};
  } else {
    assertx(srcLoc.hasReg(0));
    auto const extended = zeroExtendIfBool(v, src->type(), srcLoc.reg(0));
    v << copy{extended, data};
  }
}