in hphp/runtime/vm/jit/gvn.cpp [171:350]
bool supportsGVN(const IRInstruction* inst) {
switch (inst->op()) {
case AssertType:
case AbsDbl:
case AddInt:
case SubInt:
case MulInt:
case AndInt:
case AddDbl:
case SubDbl:
case MulDbl:
case DivDbl:
case DivInt:
case Mod:
case Sqrt:
case OrInt:
case XorInt:
case Shl:
case Shr:
case Floor:
case Ceil:
case AddIntO:
case SubIntO:
case MulIntO:
case XorBool:
case ConvDblToBool:
case ConvIntToBool:
case ConvBoolToDbl:
case ConvIntToDbl:
case ConvBoolToInt:
case ConvDblToInt:
case ConvFuncPrologueFlagsToARFlags:
case DblAsBits:
case GtInt:
case GteInt:
case LtInt:
case LteInt:
case EqInt:
case NeqInt:
case CmpInt:
case GtDbl:
case GteDbl:
case LtDbl:
case LteDbl:
case EqDbl:
case NeqDbl:
case CmpDbl:
case GtStr:
case GteStr:
case LtStr:
case LteStr:
case EqStr:
case NeqStr:
case SameStr:
case NSameStr:
case CmpStr:
case GtBool:
case GteBool:
case LtBool:
case LteBool:
case EqBool:
case NeqBool:
case CmpBool:
case SameObj:
case NSameObj:
case SameArrLike:
case NSameArrLike:
case GtRes:
case GteRes:
case LtRes:
case LteRes:
case EqRes:
case NeqRes:
case CmpRes:
case EqCls:
case EqLazyCls:
case EqFunc:
case EqStrPtr:
case InstanceOf:
case InstanceOfIface:
case InstanceOfIfaceVtable:
case ExtendsClass:
case InstanceOfBitmask:
case NInstanceOfBitmask:
case InterfaceSupportsArrLike:
case InterfaceSupportsStr:
case InterfaceSupportsInt:
case InterfaceSupportsDbl:
case HasToString:
case IsType:
case IsNType:
case IsLegacyArrLike:
case IsWaitHandle:
case IsCol:
case LdRDSAddr:
case LdFrameThis:
case LdFrameCls:
case LdClsCtor:
case DefConst:
case LdCls:
case LdClsCached:
case LdClsInitData:
case LdClsFromClsMeth:
case LdSmashableFunc:
case LdFuncFromClsMeth:
case LdFuncInOutBits:
case LdFuncVecLen:
case LdClsMethod:
case LdIfaceMethod:
case LdPropAddr:
case LdClsPropAddrOrNull:
case LdClsPropAddrOrRaise:
case LdObjClass:
case LdClsName:
case LdLazyCls:
case LdLazyClsName:
case Mov:
case LdContActRec:
case LdAFWHActRec:
case LdVecElemAddr:
case OrdStr:
case ChrInt:
case CheckRange:
case CountVec:
case CountDict:
case CountKeyset:
case BespokeGet:
case BespokeGetThrow:
case BespokeIterEnd:
case LdMonotypeDictTombstones:
case LdMonotypeDictKey:
case LdMonotypeDictVal:
case LdMonotypeVecElem:
case Select:
case StrictlyIntegerConv:
case LookupSPropSlot:
case ConvPtrToLval:
case RaiseErrorOnInvalidIsAsExpressionType:
case LdUnitPerRequestFilepath:
case DirFromFilepath:
case AKExistsDict:
case AKExistsKeyset:
case DictGet:
case DictGetK:
case DictGetQuiet:
case DictIdx:
case DictIsset:
case KeysetGet:
case KeysetGetK:
case KeysetGetQuiet:
case KeysetIdx:
case KeysetIsset:
case CheckDictOffset:
case CheckKeysetOffset:
case CheckDictKeys:
case CheckArrayCOW:
case CheckMissingKeyInArrLike:
case LdFuncRequiredCoeffects:
case FuncHasAttr:
case ClassHasAttr:
case LdTVFromRDS:
case StructDictSlot:
case StructDictElemAddr:
return true;
case EqArrLike:
case NeqArrLike:
// Keyset equality comparisons never re-enter or throw
return inst->src(0)->type() <= TKeyset && inst->src(1)->type() <= TKeyset;
case IsTypeStruct:
// Resources can change type without generating a new SSATmp,
// so its not safe to GVN
return !opcodeMayRaise(IsTypeStruct) && !inst->src(1)->type().maybe(TRes);
default:
return false;
}
}