示例#1
0
SSATmp* Simplifier::simplifyGuardType(IRInstruction* inst) {
  Type type    = inst->getTypeParam();
  SSATmp*   src     = inst->getSrc(0);
  Type srcType = src->getType();
  if (srcType == type || srcType.strictSubtypeOf(type)) {
    /*
     * the type of the src is the same or more refined than type, so the
     * guard is unnecessary.
     */
    return src;
  }
  if (type.strictSubtypeOf(srcType)) {
    if (hoistGuardToLoad(src, type)) {
      return src;
    }
  } else {
    /*
     * incompatible types!  We should just generate a jump here and
     * return null.
     *
     * For now, this case should currently be impossible, but it may
     * come up later due to other optimizations.  The assert is so
     * we'll remember this spot ...
     */
    assert(0);
  }
  return nullptr;
}
示例#2
0
/*
 * Looks for whether the value in tmp was defined by a load, and if
 * so, changes that load into a load that guards on the given
 * type. Returns true if it succeeds.
 */
static bool hoistGuardToLoad(SSATmp* tmp, Type type) {
  IRInstruction* inst = tmp->getInstruction();
  switch (inst->getOpcode()) {
    case Mov:
    case IncRef:
    {
      // if inst is an incref or move, then chase down its src
      if (hoistGuardToLoad(inst->getSrc(0), type)) {
        // guard was successfully attached to a load instruction
        // refine the type of this mov/incref
        // Note: We can also further simplify incref's here if type is not
        // ref-counted
        tmp->setType(type);
        inst->setTypeParam(type);
        return true;
      }
      break;
    }
    case LdLoc:
    case LdStack:
    case LdMem:
    case LdProp:
    case LdRef:
    case LdClsCns:
    {
      if (!inst->getTaken()) {
        // Not a control flow instruction, so can't give it check semantics
        break;
      }
      Type instType = tmp->getType();
      if (instType == Type::Gen ||
          (instType == Type::Cell && !type.isBoxed())) {
        tmp->setType(type);
        inst->setTypeParam(type);
        return true;
      }
      break;
    }
    default:
      break;
  }
  return false;
}
示例#3
0
SSATmp* Simplifier::simplifyGuardType(IRInstruction* inst) {
  Type type    = inst->getTypeParam();
  SSATmp* src  = inst->getSrc(0);
  Type srcType = src->getType();
  if (srcType.subtypeOf(type)) {
    /*
     * the type of the src is the same or more refined than type, so the
     * guard is unnecessary.
     */
    return src;
  }
  if (type.strictSubtypeOf(srcType)) {
    if (hoistGuardToLoad(src, type)) {
      return src;
    }
  } else {
    if (type.equals(Type::Str) && srcType.maybe(Type::Str)) {
      // If we're guarding against Str and srcType has StaticStr or CountedStr
      // in it, refine the output type. This can happen when we have a
      // KindOfString guard from Translator but internally we know a more
      // specific subtype of Str.
      FTRACE(1, "Guarding {} to {}\n", srcType.toString(), type.toString());
      inst->setTypeParam(type & srcType);
    } else {
      /*
       * incompatible types!  We should just generate a jump here and
       * return null.
       *
       * For now, this case should currently be impossible, but it may
       * come up later due to other optimizations.  The assert is so
       * we'll remember this spot ...
       */
      not_implemented();
    }
  }
  return nullptr;
}