GlobOpt.h 90 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. class BackwardPass;
  6. enum class ValueStructureKind
  7. {
  8. Generic,
  9. IntConstant,
  10. IntRange,
  11. IntBounded,
  12. FloatConstant,
  13. VarConstant,
  14. JsType,
  15. Array
  16. };
  17. class IntConstantValueInfo;
  18. class IntRangeValueInfo;
  19. class IntBoundedValueInfo;
  20. class FloatConstantValueInfo;
  21. class VarConstantValueInfo;
  22. class JsTypeValueInfo;
  23. class EquivalentTypeSetValueInfo;
  24. class ArrayValueInfo;
  25. class LoopCount;
  26. class GlobOpt;
  27. class ValueInfo : protected ValueType
  28. {
  29. private:
  30. const ValueStructureKind structureKind;
  31. Sym * symStore;
  32. protected:
  33. ValueInfo(const ValueType type, const ValueStructureKind structureKind)
  34. : ValueType(type), structureKind(structureKind)
  35. {
  36. // We can only prove that the representation is a tagged int on a ToVar. Currently, we cannot have more than one value
  37. // info per value number in a block, so a value info specifying tagged int representation cannot be created for a
  38. // specific sym. Instead, a value info can be shared by multiple syms, and hence cannot specify tagged int
  39. // representation. Currently, the tagged int representation info can only be carried on the dst opnd of ToVar, and can't
  40. // even be propagated forward.
  41. Assert(!type.IsTaggedInt());
  42. SetSymStore(nullptr);
  43. }
  44. private:
  45. ValueInfo(const ValueInfo &other, const bool)
  46. : ValueType(other), structureKind(ValueStructureKind::Generic) // uses generic structure kind, as opposed to copying the structure kind
  47. {
  48. SetSymStore(other.GetSymStore());
  49. }
  50. public:
  51. static ValueInfo * New(JitArenaAllocator *const alloc, const ValueType type)
  52. {
  53. return JitAnew(alloc, ValueInfo, type, ValueStructureKind::Generic);
  54. }
  55. const ValueType & Type() const { return *this; }
  56. ValueType & Type() { return *this; }
  57. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  58. // ValueType imports. Only importing functions that are appropriate to be called on Value.
  59. public:
  60. using ValueType::IsUninitialized;
  61. using ValueType::IsDefinite;
  62. using ValueType::IsTaggedInt;
  63. using ValueType::IsIntAndLikelyTagged;
  64. using ValueType::IsLikelyTaggedInt;
  65. using ValueType::HasBeenUntaggedInt;
  66. using ValueType::IsIntAndLikelyUntagged;
  67. using ValueType::IsLikelyUntaggedInt;
  68. using ValueType::HasBeenInt;
  69. using ValueType::IsInt;
  70. using ValueType::IsLikelyInt;
  71. using ValueType::IsNotInt;
  72. using ValueType::IsNotNumber;
  73. using ValueType::HasBeenFloat;
  74. using ValueType::IsFloat;
  75. using ValueType::IsLikelyFloat;
  76. using ValueType::HasBeenNumber;
  77. using ValueType::IsNumber;
  78. using ValueType::IsLikelyNumber;
  79. using ValueType::HasBeenUnknownNumber;
  80. using ValueType::IsUnknownNumber;
  81. using ValueType::IsLikelyUnknownNumber;
  82. using ValueType::HasBeenUndefined;
  83. using ValueType::IsUndefined;
  84. using ValueType::IsLikelyUndefined;
  85. using ValueType::HasBeenNull;
  86. using ValueType::IsNull;
  87. using ValueType::IsLikelyNull;
  88. using ValueType::HasBeenBoolean;
  89. using ValueType::IsBoolean;
  90. using ValueType::IsLikelyBoolean;
  91. using ValueType::HasBeenString;
  92. using ValueType::IsString;
  93. using ValueType::IsLikelyString;
  94. using ValueType::IsNotString;
  95. using ValueType::HasBeenPrimitive;
  96. using ValueType::IsPrimitive;
  97. using ValueType::IsLikelyPrimitive;
  98. using ValueType::HasBeenObject;
  99. using ValueType::IsObject;
  100. using ValueType::IsLikelyObject;
  101. using ValueType::IsNotObject;
  102. using ValueType::CanMergeToObject;
  103. using ValueType::CanMergeToSpecificObjectType;
  104. using ValueType::IsRegExp;
  105. using ValueType::IsLikelyRegExp;
  106. using ValueType::IsArray;
  107. using ValueType::IsLikelyArray;
  108. using ValueType::IsNotArray;
  109. using ValueType::IsArrayOrObjectWithArray;
  110. using ValueType::IsLikelyArrayOrObjectWithArray;
  111. using ValueType::IsNotArrayOrObjectWithArray;
  112. using ValueType::IsNativeArray;
  113. using ValueType::IsLikelyNativeArray;
  114. using ValueType::IsNotNativeArray;
  115. using ValueType::IsNativeIntArray;
  116. using ValueType::IsLikelyNativeIntArray;
  117. using ValueType::IsNativeFloatArray;
  118. using ValueType::IsLikelyNativeFloatArray;
  119. using ValueType::IsTypedArray;
  120. using ValueType::IsLikelyTypedArray;
  121. using ValueType::IsOptimizedTypedArray;
  122. using ValueType::IsLikelyOptimizedTypedArray;
  123. using ValueType::IsLikelyOptimizedVirtualTypedArray;
  124. using ValueType::IsAnyArrayWithNativeFloatValues;
  125. using ValueType::IsLikelyAnyArrayWithNativeFloatValues;
  126. using ValueType::IsAnyArray;
  127. using ValueType::IsLikelyAnyArray;
  128. using ValueType::IsAnyOptimizedArray;
  129. using ValueType::IsLikelyAnyOptimizedArray;
  130. // The following apply to object types only
  131. using ValueType::GetObjectType;
  132. // The following apply to javascript array types only
  133. using ValueType::HasNoMissingValues;
  134. using ValueType::HasIntElements;
  135. using ValueType::HasFloatElements;
  136. using ValueType::HasVarElements;
  137. using ValueType::IsSimd128;
  138. using ValueType::IsSimd128Float32x4;
  139. using ValueType::IsSimd128Int32x4;
  140. using ValueType::IsSimd128Float64x2;
  141. using ValueType::IsLikelySimd128;
  142. using ValueType::IsLikelySimd128Float32x4;
  143. using ValueType::IsLikelySimd128Int32x4;
  144. using ValueType::IsLikelySimd128Float64x2;
  145. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  146. public:
  147. bool IsGeneric() const;
  148. private:
  149. bool IsIntConstant() const;
  150. const IntConstantValueInfo * AsIntConstant() const;
  151. bool IsIntRange() const;
  152. const IntRangeValueInfo * AsIntRange() const;
  153. public:
  154. bool IsIntBounded() const;
  155. const IntBoundedValueInfo * AsIntBounded() const;
  156. bool IsFloatConstant() const;
  157. FloatConstantValueInfo * AsFloatConstant();
  158. const FloatConstantValueInfo * AsFloatConstant() const;
  159. bool IsVarConstant() const;
  160. VarConstantValueInfo * AsVarConstant();
  161. bool IsJsType() const;
  162. JsTypeValueInfo * AsJsType();
  163. const JsTypeValueInfo * AsJsType() const;
  164. #if FALSE
  165. bool IsObjectType() const;
  166. JsTypeValueInfo * AsObjectType();
  167. bool IsEquivalentTypeSet() const;
  168. EquivalentTypeSetValueInfo * AsEquivalentTypeSet();
  169. #endif
  170. bool IsArrayValueInfo() const;
  171. const ArrayValueInfo * AsArrayValueInfo() const;
  172. ArrayValueInfo * AsArrayValueInfo();
  173. public:
  174. bool HasIntConstantValue(const bool includeLikelyInt = false) const;
  175. bool TryGetIntConstantValue(int32 *const intValueRef, const bool includeLikelyInt = false) const;
  176. bool TryGetIntConstantLowerBound(int32 *const intConstantBoundRef, const bool includeLikelyInt = false) const;
  177. bool TryGetIntConstantUpperBound(int32 *const intConstantBoundRef, const bool includeLikelyInt = false) const;
  178. bool TryGetIntConstantBounds(IntConstantBounds *const intConstantBoundsRef, const bool includeLikelyInt = false) const;
  179. bool WasNegativeZeroPreventedByBailout() const;
  180. public:
  181. static bool IsEqualTo(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
  182. static bool IsNotEqualTo(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
  183. private:
  184. static bool IsEqualTo_NoConverse(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
  185. static bool IsNotEqualTo_NoConverse(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
  186. public:
  187. static bool IsGreaterThanOrEqualTo(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
  188. static bool IsGreaterThan(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
  189. static bool IsLessThanOrEqualTo(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
  190. static bool IsLessThan(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2);
  191. public:
  192. static bool IsGreaterThanOrEqualTo(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2, const int src2Offset);
  193. static bool IsLessThanOrEqualTo(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2, const int src2Offset);
  194. private:
  195. static bool IsGreaterThanOrEqualTo_NoConverse(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2, const int src2Offset);
  196. static bool IsLessThanOrEqualTo_NoConverse(const Value *const src1Value, const int32 min1, const int32 max1, const Value *const src2Value, const int32 min2, const int32 max2, const int src2Offset);
  197. public:
  198. ValueInfo *SpecializeToInt32(JitArenaAllocator *const allocator, const bool isForLoopBackEdgeCompensation = false);
  199. ValueInfo *SpecializeToFloat64(JitArenaAllocator *const allocator);
  200. // SIMD_JS
  201. ValueInfo *SpecializeToSimd128(IRType type, JitArenaAllocator *const allocator);
  202. ValueInfo *SpecializeToSimd128F4(JitArenaAllocator *const allocator);
  203. ValueInfo *SpecializeToSimd128I4(JitArenaAllocator *const allocator);
  204. public:
  205. Sym * GetSymStore() const { return this->symStore; }
  206. void SetSymStore(Sym * sym)
  207. {
  208. // Sym store should always be a var sym
  209. Assert(sym == nullptr || sym->IsPropertySym() || !sym->AsStackSym()->IsTypeSpec()); // property syms always have a var stack sym
  210. this->symStore = sym;
  211. }
  212. bool GetIsShared() const;
  213. void SetIsShared();
  214. ValueInfo * Copy(JitArenaAllocator * allocator);
  215. ValueInfo * CopyWithGenericStructureKind(JitArenaAllocator * allocator) const
  216. {
  217. return JitAnew(allocator, ValueInfo, *this, false);
  218. }
  219. bool GetIntValMinMax(int *pMin, int *pMax, bool doAggressiveIntTypeSpec);
  220. #if DBG_DUMP
  221. void Dump();
  222. #endif
  223. #if DBG
  224. // Add a vtable in debug builds so that the actual can been inspected easily in the debugger without having to manually cast
  225. virtual void AddVtable() { Assert(false); }
  226. #endif
  227. };
  228. class Value
  229. {
  230. private:
  231. const ValueNumber valueNumber;
  232. ValueInfo *valueInfo;
  233. protected:
  234. Value(const ValueNumber valueNumber, ValueInfo *valueInfo)
  235. : valueNumber(valueNumber), valueInfo(valueInfo)
  236. {
  237. };
  238. public:
  239. static Value *New(JitArenaAllocator *const allocator, const ValueNumber valueNumber, ValueInfo *valueInfo)
  240. {
  241. return JitAnew(allocator, Value, valueNumber, valueInfo);
  242. }
  243. ValueNumber GetValueNumber() const { return this->valueNumber; }
  244. ValueInfo * GetValueInfo() const { return this->valueInfo; }
  245. ValueInfo * ShareValueInfo() const { this->valueInfo->SetIsShared(); return this->valueInfo; }
  246. void SetValueInfo(ValueInfo * newValueInfo) { Assert(newValueInfo); this->valueInfo = newValueInfo; }
  247. Value * Copy(JitArenaAllocator * allocator, ValueNumber newValueNumber) { return Value::New(allocator, newValueNumber, this->ShareValueInfo()); }
  248. #if DBG_DUMP
  249. __declspec(noinline) void Dump() const { Output::Print(L"0x%X ValueNumber: %3d, -> ", this, this->valueNumber); this->valueInfo->Dump(); }
  250. #endif
  251. };
  252. template<>
  253. ValueNumber JsUtil::ValueToKey<ValueNumber, Value *>::ToKey(Value *const &value)
  254. {
  255. Assert(value);
  256. return value->GetValueNumber();
  257. }
  258. class IntConstantValueInfo : public ValueInfo
  259. {
  260. private:
  261. const int32 intValue;
  262. protected:
  263. IntConstantValueInfo(const int32 intValue)
  264. : ValueInfo(GetInt(IsTaggable(intValue)), ValueStructureKind::IntConstant),
  265. intValue(intValue)
  266. {
  267. }
  268. public:
  269. static IntConstantValueInfo *New(JitArenaAllocator *const allocator, const int32 intValue)
  270. {
  271. return JitAnew(allocator, IntConstantValueInfo, intValue);
  272. }
  273. IntConstantValueInfo *Copy(JitArenaAllocator *const allocator) const
  274. {
  275. return JitAnew(allocator, IntConstantValueInfo, *this);
  276. }
  277. public:
  278. int32 IntValue() const
  279. {
  280. return intValue;
  281. }
  282. private:
  283. static bool IsTaggable(const int32 i)
  284. {
  285. #if INT32VAR
  286. // All 32-bit ints are taggable on 64-bit architectures
  287. return true;
  288. #else
  289. return i >= Js::Constants::Int31MinValue && i <= Js::Constants::Int31MaxValue;
  290. #endif
  291. }
  292. };
  293. class IntRangeValueInfo : public ValueInfo, public IntConstantBounds
  294. {
  295. private:
  296. // Definitely-int values are inherently not negative zero. This member variable, if true, indicates that this value was
  297. // produced by an int-specialized instruction that prevented a negative zero result using a negative zero bailout
  298. // (BailOutOnNegativeZero). Negative zero tracking in the dead-store phase tracks this information to see if some of these
  299. // negative zero bailout checks can be removed.
  300. bool wasNegativeZeroPreventedByBailout;
  301. protected:
  302. IntRangeValueInfo(
  303. const IntConstantBounds &constantBounds,
  304. const bool wasNegativeZeroPreventedByBailout,
  305. const ValueStructureKind structureKind = ValueStructureKind::IntRange)
  306. : ValueInfo(constantBounds.GetValueType(), structureKind),
  307. IntConstantBounds(constantBounds),
  308. wasNegativeZeroPreventedByBailout(wasNegativeZeroPreventedByBailout)
  309. {
  310. Assert(!wasNegativeZeroPreventedByBailout || constantBounds.LowerBound() <= 0 && constantBounds.UpperBound() >= 0);
  311. }
  312. public:
  313. static IntRangeValueInfo *New(
  314. JitArenaAllocator *const allocator,
  315. const int32 lowerBound,
  316. const int32 upperBound,
  317. const bool wasNegativeZeroPreventedByBailout)
  318. {
  319. return
  320. JitAnew(
  321. allocator,
  322. IntRangeValueInfo,
  323. IntConstantBounds(lowerBound, upperBound),
  324. wasNegativeZeroPreventedByBailout);
  325. }
  326. IntRangeValueInfo *Copy(JitArenaAllocator *const allocator) const
  327. {
  328. return JitAnew(allocator, IntRangeValueInfo, *this);
  329. }
  330. public:
  331. bool WasNegativeZeroPreventedByBailout() const
  332. {
  333. return wasNegativeZeroPreventedByBailout;
  334. }
  335. };
  336. class FloatConstantValueInfo : public ValueInfo
  337. {
  338. private:
  339. const FloatConstType floatValue;
  340. public:
  341. FloatConstantValueInfo(const FloatConstType floatValue)
  342. : ValueInfo(Float, ValueStructureKind::FloatConstant), floatValue(floatValue)
  343. {
  344. }
  345. static FloatConstantValueInfo *New(
  346. JitArenaAllocator *const allocator,
  347. const FloatConstType floatValue)
  348. {
  349. return JitAnew(allocator, FloatConstantValueInfo, floatValue);
  350. }
  351. FloatConstantValueInfo *Copy(JitArenaAllocator *const allocator) const
  352. {
  353. return JitAnew(allocator, FloatConstantValueInfo, *this);
  354. }
  355. public:
  356. FloatConstType FloatValue() const
  357. {
  358. return floatValue;
  359. }
  360. };
  361. class VarConstantValueInfo : public ValueInfo
  362. {
  363. private:
  364. Js::Var const varValue;
  365. bool isFunction;
  366. public:
  367. VarConstantValueInfo(Js::Var varValue, ValueType valueType, bool isFunction = false)
  368. : ValueInfo(valueType, ValueStructureKind::VarConstant),
  369. varValue(varValue), isFunction(isFunction)
  370. {
  371. }
  372. static VarConstantValueInfo *New(JitArenaAllocator *const allocator, Js::Var varValue, ValueType valueType, bool isFunction = false)
  373. {
  374. return JitAnew(allocator, VarConstantValueInfo, varValue, valueType, isFunction);
  375. }
  376. VarConstantValueInfo *Copy(JitArenaAllocator *const allocator) const
  377. {
  378. return JitAnew(allocator, VarConstantValueInfo, *this);
  379. }
  380. public:
  381. Js::Var VarValue() const
  382. {
  383. return this->varValue;
  384. }
  385. bool IsFunction() const
  386. {
  387. return this->isFunction;
  388. }
  389. };
  390. struct ObjectTypePropertyEntry
  391. {
  392. Js::ObjTypeSpecFldInfo* fldInfo;
  393. uint blockNumber;
  394. };
  395. typedef JsUtil::BaseDictionary<Js::PropertyId, ObjectTypePropertyEntry, JitArenaAllocator> ObjectTypePropertyMap;
  396. class JsTypeValueInfo : public ValueInfo
  397. {
  398. private:
  399. const Js::Type * jsType;
  400. Js::EquivalentTypeSet * jsTypeSet;
  401. bool isShared;
  402. public:
  403. JsTypeValueInfo(Js::Type * type)
  404. : ValueInfo(Uninitialized, ValueStructureKind::JsType),
  405. jsType(type), jsTypeSet(nullptr), isShared(false)
  406. {
  407. }
  408. JsTypeValueInfo(Js::EquivalentTypeSet * typeSet)
  409. : ValueInfo(Uninitialized, ValueStructureKind::JsType),
  410. jsType(nullptr), jsTypeSet(typeSet), isShared(false)
  411. {
  412. }
  413. JsTypeValueInfo(const JsTypeValueInfo& other)
  414. : ValueInfo(Uninitialized, ValueStructureKind::JsType),
  415. jsType(other.jsType), jsTypeSet(other.jsTypeSet)
  416. {
  417. }
  418. static JsTypeValueInfo * New(JitArenaAllocator *const allocator, Js::Type * typeSet)
  419. {
  420. return JitAnew(allocator, JsTypeValueInfo, typeSet);
  421. }
  422. static JsTypeValueInfo * New(JitArenaAllocator *const allocator, Js::EquivalentTypeSet * typeSet)
  423. {
  424. return JitAnew(allocator, JsTypeValueInfo, typeSet);
  425. }
  426. JsTypeValueInfo(const Js::Type* type, Js::EquivalentTypeSet * typeSet)
  427. : ValueInfo(Uninitialized, ValueStructureKind::JsType),
  428. jsType(type), jsTypeSet(typeSet), isShared(false)
  429. {
  430. }
  431. static JsTypeValueInfo * New(JitArenaAllocator *const allocator, const Js::Type* type, Js::EquivalentTypeSet * typeSet)
  432. {
  433. return JitAnew(allocator, JsTypeValueInfo, type, typeSet);
  434. }
  435. public:
  436. JsTypeValueInfo * Copy(JitArenaAllocator *const allocator) const
  437. {
  438. JsTypeValueInfo * newInfo = JitAnew(allocator, JsTypeValueInfo, *this);
  439. newInfo->isShared = false;
  440. return newInfo;
  441. }
  442. const Js::Type * GetJsType() const
  443. {
  444. return this->jsType;
  445. }
  446. void SetJsType(const Js::Type * value)
  447. {
  448. Assert(!this->isShared);
  449. this->jsType = value;
  450. }
  451. Js::EquivalentTypeSet * GetJsTypeSet() const
  452. {
  453. return this->jsTypeSet;
  454. }
  455. void SetJsTypeSet(Js::EquivalentTypeSet * value)
  456. {
  457. Assert(!this->isShared);
  458. this->jsTypeSet = value;
  459. }
  460. bool GetIsShared() const { return this->isShared; }
  461. void SetIsShared() { this->isShared = true; }
  462. };
  463. class ArrayValueInfo : public ValueInfo
  464. {
  465. private:
  466. StackSym *const headSegmentSym;
  467. StackSym *const headSegmentLengthSym;
  468. StackSym *const lengthSym;
  469. private:
  470. ArrayValueInfo(
  471. const ValueType valueType,
  472. StackSym *const headSegmentSym,
  473. StackSym *const headSegmentLengthSym,
  474. StackSym *const lengthSym,
  475. Sym *const symStore = nullptr)
  476. : ValueInfo(valueType, ValueStructureKind::Array),
  477. headSegmentSym(headSegmentSym),
  478. headSegmentLengthSym(headSegmentLengthSym),
  479. lengthSym(lengthSym)
  480. {
  481. Assert(valueType.IsAnyOptimizedArray());
  482. Assert(!(valueType.IsLikelyTypedArray() && !valueType.IsOptimizedTypedArray()));
  483. // For typed arrays, the head segment length is the same as the array length. For objects with internal arrays, the
  484. // length behaves like a regular object's property rather than like an array length.
  485. Assert(!lengthSym || valueType.IsLikelyArray());
  486. Assert(!lengthSym || lengthSym != headSegmentLengthSym);
  487. if(symStore)
  488. {
  489. SetSymStore(symStore);
  490. }
  491. }
  492. public:
  493. static ArrayValueInfo *New(
  494. JitArenaAllocator *const allocator,
  495. const ValueType valueType,
  496. StackSym *const headSegmentSym,
  497. StackSym *const headSegmentLengthSym,
  498. StackSym *const lengthSym,
  499. Sym *const symStore = nullptr)
  500. {
  501. Assert(allocator);
  502. return JitAnew(allocator, ArrayValueInfo, valueType, headSegmentSym, headSegmentLengthSym, lengthSym, symStore);
  503. }
  504. ValueInfo *Copy(
  505. JitArenaAllocator *const allocator,
  506. const bool copyHeadSegment = true,
  507. const bool copyHeadSegmentLength = true,
  508. const bool copyLength = true) const
  509. {
  510. Assert(allocator);
  511. return
  512. copyHeadSegment && headSegmentSym || copyHeadSegmentLength && headSegmentLengthSym || copyLength && lengthSym
  513. ? New(
  514. allocator,
  515. Type(),
  516. copyHeadSegment ? headSegmentSym : nullptr,
  517. copyHeadSegmentLength ? headSegmentLengthSym : nullptr,
  518. copyLength ? lengthSym : nullptr,
  519. GetSymStore())
  520. : CopyWithGenericStructureKind(allocator);
  521. }
  522. public:
  523. StackSym *HeadSegmentSym() const
  524. {
  525. return headSegmentSym;
  526. }
  527. StackSym *HeadSegmentLengthSym() const
  528. {
  529. return headSegmentLengthSym;
  530. }
  531. StackSym *LengthSym() const
  532. {
  533. return lengthSym;
  534. }
  535. IR::ArrayRegOpnd *CreateOpnd(
  536. IR::RegOpnd *const previousArrayOpnd,
  537. const bool needsHeadSegment,
  538. const bool needsHeadSegmentLength,
  539. const bool needsLength,
  540. const bool eliminatedLowerBoundCheck,
  541. const bool eliminatedUpperBoundCheck,
  542. Func *const func) const
  543. {
  544. Assert(previousArrayOpnd);
  545. Assert(func);
  546. return
  547. IR::ArrayRegOpnd::New(
  548. previousArrayOpnd,
  549. Type(),
  550. needsHeadSegment ? headSegmentSym : nullptr,
  551. needsHeadSegmentLength ? headSegmentLengthSym : nullptr,
  552. needsLength ? lengthSym : nullptr,
  553. eliminatedLowerBoundCheck,
  554. eliminatedUpperBoundCheck,
  555. func);
  556. }
  557. };
  558. class ExprAttributes
  559. {
  560. protected:
  561. uint32 attributes;
  562. public:
  563. ExprAttributes(const uint32 attributes = 0) : attributes(attributes)
  564. {
  565. }
  566. uint32 Attributes() const
  567. {
  568. return attributes;
  569. }
  570. private:
  571. static const uint32 BitMask(const uint index)
  572. {
  573. return 1u << index;
  574. }
  575. protected:
  576. void SetBitAttribute(const uint index, const bool bit)
  577. {
  578. if(bit)
  579. {
  580. attributes |= BitMask(index);
  581. }
  582. else
  583. {
  584. attributes &= ~BitMask(index);
  585. }
  586. }
  587. };
  588. class IntMathExprAttributes : public ExprAttributes
  589. {
  590. private:
  591. static const uint IgnoredIntOverflowIndex = 0;
  592. static const uint IgnoredNegativeZeroIndex = 1;
  593. public:
  594. IntMathExprAttributes(const ExprAttributes &exprAttributes) : ExprAttributes(exprAttributes)
  595. {
  596. }
  597. IntMathExprAttributes(const bool ignoredIntOverflow, const bool ignoredNegativeZero)
  598. {
  599. SetBitAttribute(IgnoredIntOverflowIndex, ignoredIntOverflow);
  600. SetBitAttribute(IgnoredNegativeZeroIndex, ignoredNegativeZero);
  601. }
  602. };
  603. class DstIsIntOrNumberAttributes : public ExprAttributes
  604. {
  605. private:
  606. static const uint DstIsIntOnlyIndex = 0;
  607. static const uint DstIsNumberOnlyIndex = 1;
  608. public:
  609. DstIsIntOrNumberAttributes(const ExprAttributes &exprAttributes) : ExprAttributes(exprAttributes)
  610. {
  611. }
  612. DstIsIntOrNumberAttributes(const bool dstIsIntOnly, const bool dstIsNumberOnly)
  613. {
  614. SetBitAttribute(DstIsIntOnlyIndex, dstIsIntOnly);
  615. SetBitAttribute(DstIsNumberOnlyIndex, dstIsNumberOnly);
  616. }
  617. };
  618. class ExprHash
  619. {
  620. public:
  621. ExprHash() { this->opcode = 0; }
  622. ExprHash(int init) { Assert(init == 0); this->opcode = 0; }
  623. void Init(Js::OpCode opcode, ValueNumber src1Val, ValueNumber src2Val, ExprAttributes exprAttributes)
  624. {
  625. extern uint8 OpCodeToHash[(int)Js::OpCode::Count];
  626. uint32 opCodeHash = OpCodeToHash[(int)opcode];
  627. this->opcode = opCodeHash;
  628. this->src1Val = src1Val;
  629. this->src2Val = src2Val;
  630. this->attributes = exprAttributes.Attributes();
  631. // Assert too many opcodes...
  632. AssertMsg(this->opcode == (uint32)opCodeHash, "Opcode value too large for CSEs");
  633. AssertMsg(this->attributes == exprAttributes.Attributes(), "Not enough bits for expr attributes");
  634. // If value numbers are too large, just give up
  635. if (this->src1Val != src1Val || this->src2Val != src2Val)
  636. {
  637. this->opcode = 0;
  638. this->src1Val = 0;
  639. this->src2Val = 0;
  640. this->attributes = 0;
  641. }
  642. }
  643. Js::OpCode GetOpcode() { return (Js::OpCode)this->opcode; }
  644. ValueNumber GetSrc1ValueNumber() { return this->src1Val; }
  645. ValueNumber GetSrc2ValueNumber() { return this->src2Val; }
  646. ExprAttributes GetExprAttributes() { return this->attributes; }
  647. bool IsValid() { return this->opcode != 0; }
  648. operator uint() { return *(uint*)this; }
  649. private:
  650. uint32 opcode: 8;
  651. uint32 src1Val: 11;
  652. uint32 src2Val: 11;
  653. uint32 attributes: 2;
  654. };
  655. enum class PathDependentRelationship : uint8
  656. {
  657. Equal,
  658. NotEqual,
  659. GreaterThanOrEqual,
  660. GreaterThan,
  661. LessThanOrEqual,
  662. LessThan
  663. };
  664. class PathDependentInfo
  665. {
  666. private:
  667. Value *leftValue, *rightValue;
  668. int32 rightConstantValue;
  669. PathDependentRelationship relationship;
  670. public:
  671. PathDependentInfo(const PathDependentRelationship relationship, Value *const leftValue, Value *const rightValue)
  672. : relationship(relationship), leftValue(leftValue), rightValue(rightValue)
  673. {
  674. Assert(leftValue);
  675. Assert(rightValue);
  676. }
  677. PathDependentInfo(
  678. const PathDependentRelationship relationship,
  679. Value *const leftValue,
  680. Value *const rightValue,
  681. const int32 rightConstantValue)
  682. : relationship(relationship), leftValue(leftValue), rightValue(rightValue), rightConstantValue(rightConstantValue)
  683. {
  684. Assert(leftValue);
  685. }
  686. public:
  687. bool HasInfo() const
  688. {
  689. return !!leftValue;
  690. }
  691. PathDependentRelationship Relationship() const
  692. {
  693. Assert(HasInfo());
  694. return relationship;
  695. }
  696. Value *LeftValue() const
  697. {
  698. Assert(HasInfo());
  699. return leftValue;
  700. }
  701. Value *RightValue() const
  702. {
  703. Assert(HasInfo());
  704. return rightValue;
  705. }
  706. int32 RightConstantValue() const
  707. {
  708. Assert(!RightValue());
  709. return rightConstantValue;
  710. }
  711. };
  712. class PathDependentInfoToRestore
  713. {
  714. private:
  715. ValueInfo *leftValueInfo, *rightValueInfo;
  716. public:
  717. PathDependentInfoToRestore() : leftValueInfo(nullptr), rightValueInfo(nullptr)
  718. {
  719. }
  720. PathDependentInfoToRestore(ValueInfo *const leftValueInfo, ValueInfo *const rightValueInfo)
  721. : leftValueInfo(leftValueInfo), rightValueInfo(rightValueInfo)
  722. {
  723. }
  724. public:
  725. ValueInfo *LeftValueInfo() const
  726. {
  727. return leftValueInfo;
  728. }
  729. ValueInfo *RightValueInfo() const
  730. {
  731. return rightValueInfo;
  732. }
  733. public:
  734. void Clear()
  735. {
  736. leftValueInfo = nullptr;
  737. rightValueInfo = nullptr;
  738. }
  739. };
  740. typedef JsUtil::List<IR::Opnd *, JitArenaAllocator> OpndList;
  741. typedef JsUtil::BaseDictionary<Sym *, ValueInfo *, JitArenaAllocator> SymToValueInfoMap;
  742. typedef JsUtil::BaseDictionary<SymID, IR::Instr *, JitArenaAllocator> SymIdToInstrMap;
  743. typedef JsUtil::BaseHashSet<Value *, JitArenaAllocator> ValueSet;
  744. typedef JsUtil::BaseHashSet<Value *, JitArenaAllocator, PowerOf2SizePolicy, ValueNumber> ValueSetByValueNumber;
  745. typedef JsUtil::BaseDictionary<SymID, StackSym *, JitArenaAllocator> SymIdToStackSymMap;
  746. typedef JsUtil::Pair<ValueNumber, ValueNumber> ValueNumberPair;
  747. typedef JsUtil::BaseDictionary<ValueNumberPair, Value *, JitArenaAllocator> ValueNumberPairToValueMap;
  748. #include "GlobHashTable.h"
  749. typedef ValueHashTable<Sym *, Value *> GlobHashTable;
  750. typedef HashBucket<Sym *, Value *> GlobHashBucket;
  751. typedef ValueHashTable<ExprHash, Value *> ExprHashTable;
  752. typedef HashBucket<ExprHash, Value *> ExprHashBucket;
  753. struct StackLiteralInitFldData
  754. {
  755. const Js::PropertyIdArray * propIds;
  756. uint currentInitFldCount;
  757. };
  758. namespace JsUtil
  759. {
  760. template <>
  761. class ValueEntry<StackLiteralInitFldData> : public BaseValueEntry<StackLiteralInitFldData>
  762. {
  763. public:
  764. void Clear()
  765. {
  766. #if DBG
  767. this->value.propIds = nullptr;
  768. this->value.currentInitFldCount = (uint)-1;
  769. #endif
  770. }
  771. };
  772. };
  773. typedef JsUtil::BaseDictionary<StackSym *, StackLiteralInitFldData, JitArenaAllocator> StackLiteralInitFldDataMap;
  774. typedef SList<GlobHashBucket*, JitArenaAllocator> PRECandidatesList;
  775. class GlobOptBlockData
  776. {
  777. public:
  778. GlobOptBlockData(Func *func) :
  779. symToValueMap(nullptr),
  780. exprToValueMap(nullptr),
  781. liveFields(nullptr),
  782. liveArrayValues(nullptr),
  783. maybeWrittenTypeSyms(nullptr),
  784. liveVarSyms(nullptr),
  785. liveInt32Syms(nullptr),
  786. liveLossyInt32Syms(nullptr),
  787. liveFloat64Syms(nullptr),
  788. liveSimd128F4Syms(nullptr),
  789. liveSimd128I4Syms(nullptr),
  790. hoistableFields(nullptr),
  791. argObjSyms(nullptr),
  792. maybeTempObjectSyms(nullptr),
  793. canStoreTempObjectSyms(nullptr),
  794. valuesToKillOnCalls(nullptr),
  795. inductionVariables(nullptr),
  796. availableIntBoundChecks(nullptr),
  797. startCallCount(0),
  798. argOutCount(0),
  799. totalOutParamCount(0),
  800. callSequence(nullptr),
  801. hasCSECandidates(false),
  802. curFunc(func),
  803. hasDataRef(nullptr),
  804. stackLiteralInitFldDataMap(nullptr)
  805. {
  806. }
  807. // Data
  808. GlobHashTable * symToValueMap;
  809. ExprHashTable * exprToValueMap;
  810. BVSparse<JitArenaAllocator> * liveFields;
  811. BVSparse<JitArenaAllocator> * liveArrayValues;
  812. BVSparse<JitArenaAllocator> * maybeWrittenTypeSyms;
  813. BVSparse<JitArenaAllocator> * isTempSrc;
  814. BVSparse<JitArenaAllocator> * liveVarSyms;
  815. BVSparse<JitArenaAllocator> * liveInt32Syms;
  816. // 'liveLossyInt32Syms' includes only syms that contain an int value that may not fully represent the value of the
  817. // equivalent var sym. The set (liveInt32Syms - liveLossyInt32Syms) includes only syms that contain an int value that fully
  818. // represents the value of the equivalent var sym, such as when (a + 1) is type-specialized. Among other things, this
  819. // bit-vector is used, based on the type of conversion that is needed, to determine whether conversion is necessary, and if
  820. // so, whether a bailout is needed. For instance, after type-specializing (a | 0), the int32 sym of 'a' cannot be reused in
  821. // (a + 1) during type-specialization. It needs to be converted again using a lossless conversion with a bailout.
  822. // Conversely, a lossless int32 sym can be reused to avoid a lossy conversion.
  823. BVSparse<JitArenaAllocator> * liveLossyInt32Syms;
  824. BVSparse<JitArenaAllocator> * liveFloat64Syms;
  825. // SIMD_JS
  826. BVSparse<JitArenaAllocator> * liveSimd128F4Syms;
  827. BVSparse<JitArenaAllocator> * liveSimd128I4Syms;
  828. BVSparse<JitArenaAllocator> * hoistableFields;
  829. BVSparse<JitArenaAllocator> * argObjSyms;
  830. BVSparse<JitArenaAllocator> * maybeTempObjectSyms;
  831. BVSparse<JitArenaAllocator> * canStoreTempObjectSyms;
  832. Func * curFunc;
  833. // 'valuesToKillOnCalls' includes values whose value types need to be killed upon a call. Upon a call, the value types of
  834. // values in the set are updated and removed from the set as appropriate.
  835. ValueSet * valuesToKillOnCalls;
  836. InductionVariableSet * inductionVariables;
  837. IntBoundCheckSet * availableIntBoundChecks;
  838. // Bailout data
  839. uint startCallCount;
  840. uint argOutCount;
  841. uint totalOutParamCount;
  842. SListBase<IR::Opnd *> * callSequence;
  843. StackLiteralInitFldDataMap * stackLiteralInitFldDataMap;
  844. uint inlinedArgOutCount;
  845. bool hasCSECandidates;
  846. private:
  847. bool * hasDataRef;
  848. public:
  849. void OnDataInitialized(JitArenaAllocator *const allocator)
  850. {
  851. Assert(allocator);
  852. hasDataRef = JitAnew(allocator, bool, true);
  853. }
  854. void OnDataReused(GlobOptBlockData *const fromData)
  855. {
  856. // If a block's data is deleted, *hasDataRef will be set to false. Since these two blocks are pointing to the same data,
  857. // they also need to point to the same has-data info.
  858. hasDataRef = fromData->hasDataRef;
  859. }
  860. void OnDataUnreferenced()
  861. {
  862. // Other blocks may still be using the data, we should only un-reference the previous data
  863. hasDataRef = nullptr;
  864. }
  865. void OnDataDeleted()
  866. {
  867. if(hasDataRef)
  868. *hasDataRef = false;
  869. OnDataUnreferenced();
  870. }
  871. bool HasData()
  872. {
  873. if(!hasDataRef)
  874. return false;
  875. if(*hasDataRef)
  876. return true;
  877. OnDataUnreferenced();
  878. return false;
  879. }
  880. // SIMD_JS
  881. BVSparse<JitArenaAllocator> * GetSimd128LivenessBV(IRType type)
  882. {
  883. switch (type)
  884. {
  885. case TySimd128F4:
  886. return liveSimd128F4Syms;
  887. case TySimd128I4:
  888. return liveSimd128I4Syms;
  889. default:
  890. Assert(UNREACHED);
  891. return nullptr;
  892. }
  893. }
  894. };
  895. typedef JsUtil::BaseDictionary<IntConstType, StackSym *, JitArenaAllocator> IntConstantToStackSymMap;
  896. typedef JsUtil::BaseDictionary<IntConstType, Value *, JitArenaAllocator> IntConstantToValueMap;
  897. typedef JsUtil::BaseDictionary<Js::Var, Value *, JitArenaAllocator> AddrConstantToValueMap;
  898. typedef JsUtil::BaseDictionary<Js::InternalString, Value *, JitArenaAllocator> StringConstantToValueMap;
  899. class JsArrayKills
  900. {
  901. private:
  902. union
  903. {
  904. struct
  905. {
  906. bool killsAllArrays : 1;
  907. bool killsArraysWithNoMissingValues : 1;
  908. bool killsNativeArrays : 1;
  909. bool killsArrayHeadSegments : 1;
  910. bool killsArrayHeadSegmentLengths : 1;
  911. bool killsArrayLengths : 1;
  912. };
  913. byte bits;
  914. };
  915. public:
  916. JsArrayKills() : bits(0)
  917. {
  918. }
  919. private:
  920. JsArrayKills(const byte bits) : bits(bits)
  921. {
  922. }
  923. public:
  924. bool KillsAllArrays() const { return killsAllArrays; }
  925. void SetKillsAllArrays() { killsAllArrays = true; }
  926. bool KillsArraysWithNoMissingValues() const { return killsArraysWithNoMissingValues; }
  927. void SetKillsArraysWithNoMissingValues() { killsArraysWithNoMissingValues = true; }
  928. bool KillsNativeArrays() const { return killsNativeArrays; }
  929. void SetKillsNativeArrays() { killsNativeArrays = true; }
  930. bool KillsArrayHeadSegments() const { return killsArrayHeadSegments; }
  931. void SetKillsArrayHeadSegments() { killsArrayHeadSegments = true; }
  932. bool KillsArrayHeadSegmentLengths() const { return killsArrayHeadSegmentLengths; }
  933. void SetKillsArrayHeadSegmentLengths() { killsArrayHeadSegmentLengths = true; }
  934. bool KillsTypedArrayHeadSegmentLengths() const { return KillsAllArrays(); }
  935. bool KillsArrayLengths() const { return killsArrayLengths; }
  936. void SetKillsArrayLengths() { killsArrayLengths = true; }
  937. public:
  938. bool KillsValueType(const ValueType valueType) const
  939. {
  940. Assert(valueType.IsArrayOrObjectWithArray());
  941. return
  942. killsAllArrays ||
  943. killsArraysWithNoMissingValues && valueType.HasNoMissingValues() ||
  944. killsNativeArrays && !valueType.HasVarElements();
  945. }
  946. bool AreSubsetOf(const JsArrayKills &other) const
  947. {
  948. return (bits & other.bits) == bits;
  949. }
  950. JsArrayKills Merge(const JsArrayKills &other)
  951. {
  952. return bits | other.bits;
  953. }
  954. };
  955. class InvariantBlockBackwardIterator
  956. {
  957. private:
  958. GlobOpt *const globOpt;
  959. BasicBlock *const exclusiveEndBlock;
  960. StackSym *const invariantSym;
  961. const ValueNumber invariantSymValueNumber;
  962. BasicBlock *block;
  963. Value *invariantSymValue;
  964. #if DBG
  965. BasicBlock *const inclusiveEndBlock;
  966. #endif
  967. public:
  968. InvariantBlockBackwardIterator(GlobOpt *const globOpt, BasicBlock *const exclusiveBeginBlock, BasicBlock *const inclusiveEndBlock, StackSym *const invariantSym, const ValueNumber invariantSymValueNumber = InvalidValueNumber);
  969. public:
  970. bool IsValid() const;
  971. void MoveNext();
  972. BasicBlock *Block() const;
  973. Value *InvariantSymValue() const;
  974. PREVENT_ASSIGN(InvariantBlockBackwardIterator);
  975. };
  976. class GlobOpt
  977. {
  978. private:
  979. class AddSubConstantInfo;
  980. class ArrayLowerBoundCheckHoistInfo;
  981. class ArrayUpperBoundCheckHoistInfo;
  982. friend BackwardPass;
  983. #if DBG
  984. friend class ObjectTempVerify;
  985. #endif
  986. private:
  987. SparseArray<Value> * byteCodeConstantValueArray;
  988. // Global bitvectors
  989. BVSparse<JitArenaAllocator> * byteCodeConstantValueNumbersBv;
  990. // Global bitvectors
  991. IntConstantToStackSymMap * intConstantToStackSymMap;
  992. IntConstantToValueMap* intConstantToValueMap;
  993. AddrConstantToValueMap * addrConstantToValueMap;
  994. StringConstantToValueMap * stringConstantToValueMap;
  995. #if DBG
  996. // We can still track the finished stack literal InitFld lexically.
  997. BVSparse<JitArenaAllocator> * finishedStackLiteralInitFld;
  998. #endif
  999. BVSparse<JitArenaAllocator> * byteCodeUses;
  1000. BVSparse<JitArenaAllocator> * tempBv; // Bit vector for temporary uses
  1001. BVSparse<JitArenaAllocator> * objectTypeSyms;
  1002. BVSparse<JitArenaAllocator> * prePassCopyPropSym; // Symbols that were copy prop'd during loop prepass
  1003. PropertySym * propertySymUse;
  1004. BVSparse<JitArenaAllocator> * lengthEquivBv;
  1005. BVSparse<JitArenaAllocator> * argumentsEquivBv;
  1006. GlobOptBlockData blockData;
  1007. JitArenaAllocator * alloc;
  1008. JitArenaAllocator * tempAlloc;
  1009. Func * func;
  1010. ValueNumber currentValue;
  1011. BasicBlock * currentBlock;
  1012. Region * currentRegion;
  1013. IntOverflowDoesNotMatterRange *intOverflowDoesNotMatterRange;
  1014. Loop * prePassLoop;
  1015. Loop * rootLoopPrePass;
  1016. uint instrCountSinceLastCleanUp;
  1017. SymIdToInstrMap * prePassInstrMap;
  1018. SymID maxInitialSymID;
  1019. bool isCallHelper: 1;
  1020. bool intOverflowCurrentlyMattersInRange : 1;
  1021. bool ignoredIntOverflowForCurrentInstr : 1;
  1022. bool ignoredNegativeZeroForCurrentInstr : 1;
  1023. bool inInlinedBuiltIn : 1;
  1024. bool isRecursiveCallOnLandingPad : 1;
  1025. bool updateInductionVariableValueNumber : 1;
  1026. bool isPerformingLoopBackEdgeCompensation : 1;
  1027. bool doTypeSpec : 1;
  1028. bool doAggressiveIntTypeSpec : 1;
  1029. bool doAggressiveMulIntTypeSpec : 1;
  1030. bool doDivIntTypeSpec : 1;
  1031. bool doLossyIntTypeSpec : 1;
  1032. bool doFloatTypeSpec : 1;
  1033. bool doArrayCheckHoist : 1;
  1034. bool doArrayMissingValueCheckHoist : 1;
  1035. bool doArraySegmentHoist : 1;
  1036. bool doJsArraySegmentHoist : 1;
  1037. bool doArrayLengthHoist : 1;
  1038. bool doEliminateArrayAccessHelperCall : 1;
  1039. bool doTrackRelativeIntBounds : 1;
  1040. bool doBoundCheckElimination : 1;
  1041. bool doBoundCheckHoist : 1;
  1042. bool doLoopCountBasedBoundCheckHoist : 1;
  1043. bool isAsmJSFunc : 1;
  1044. OpndList * noImplicitCallUsesToInsert;
  1045. ValueSetByValueNumber * valuesCreatedForClone;
  1046. ValueNumberPairToValueMap *valuesCreatedForMerge;
  1047. #if DBG
  1048. BVSparse<JitArenaAllocator> * byteCodeUsesBeforeOpt;
  1049. #endif
  1050. public:
  1051. GlobOpt(Func * func);
  1052. void Optimize();
  1053. // Return whether the instruction transfer value from the src to the dst for copy prop
  1054. static bool TransferSrcValue(IR::Instr * instr);
  1055. // Function used by the backward pass as well.
  1056. // GlobOptBailout.cpp
  1057. static void TrackByteCodeSymUsed(IR::Instr * instr, BVSparse<JitArenaAllocator> * instrByteCodeStackSymUsed, PropertySym **pPropertySym);
  1058. // GlobOptFields.cpp
  1059. void ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> * bv, bool inGlobOpt);
  1060. static bool DoFieldHoisting(Loop * loop);
  1061. IR::ByteCodeUsesInstr * ConvertToByteCodeUses(IR::Instr * isntr);
  1062. bool GetIsAsmJSFunc()const{ return isAsmJSFunc; };
  1063. private:
  1064. bool IsLoopPrePass() const { return this->prePassLoop != nullptr; }
  1065. void OptBlock(BasicBlock *block);
  1066. void BackwardPass(Js::Phase tag);
  1067. void ForwardPass();
  1068. void OptLoops(Loop *loop);
  1069. void TailDupPass();
  1070. bool TryTailDup(IR::BranchInstr *tailBranch);
  1071. void CleanUpValueMaps();
  1072. PRECandidatesList * FindBackEdgePRECandidates(BasicBlock *block, JitArenaAllocator *alloc);
  1073. PRECandidatesList * RemoveUnavailableCandidates(BasicBlock *block, PRECandidatesList *candidates, JitArenaAllocator *alloc);
  1074. PRECandidatesList * FindPossiblePRECandidates(Loop *loop, JitArenaAllocator *alloc);
  1075. void PreloadPRECandidates(Loop *loop, PRECandidatesList *candidates);
  1076. BOOL PreloadPRECandidate(Loop *loop, GlobHashBucket* candidate);
  1077. void SetLoopFieldInitialValue(Loop *loop, IR::Instr *instr, PropertySym *propertySym, PropertySym *originalPropertySym);
  1078. void FieldPRE(Loop *loop);
  1079. void MergePredBlocksValueMaps(BasicBlock *block);
  1080. void NulloutBlockData(GlobOptBlockData *data);
  1081. void InitBlockData();
  1082. void ReuseBlockData(GlobOptBlockData *toData, GlobOptBlockData *fromData);
  1083. void CopyBlockData(GlobOptBlockData *toData, GlobOptBlockData *fromData);
  1084. void CloneBlockData(BasicBlock *const toBlock, BasicBlock *const fromBlock);
  1085. void CloneBlockData(BasicBlock *const toBlock, GlobOptBlockData *const toData, BasicBlock *const fromBlock);
  1086. void CloneValues(BasicBlock *const toBlock, GlobOptBlockData *toData, GlobOptBlockData *fromData);
  1087. void MergeBlockData(GlobOptBlockData *toData, BasicBlock *toBlock, BasicBlock *fromBlock, BVSparse<JitArenaAllocator> *const symsRequiringCompensation, BVSparse<JitArenaAllocator> *const symsCreatedForMerge);
  1088. void DeleteBlockData(GlobOptBlockData *data);
  1089. IR::Instr * OptInstr(IR::Instr *&instr, bool* isInstrCleared);
  1090. Value* OptDst(IR::Instr **pInstr, Value *dstVal, Value *src1Val, Value *src2Val, Value *dstIndirIndexVal, Value *src1IndirIndexVal);
  1091. void CopyPropDstUses(IR::Opnd *opnd, IR::Instr *instr, Value *src1Val);
  1092. Value * OptSrc(IR::Opnd *opnd, IR::Instr * *pInstr, Value **indirIndexValRef = nullptr, IR::IndirOpnd *parentIndirOpnd = nullptr);
  1093. void MarkArgumentsUsedForBranch(IR::Instr *inst);
  1094. bool OptTagChecks(IR::Instr *instr);
  1095. void TryOptimizeInstrWithFixedDataProperty(IR::Instr * * const pInstr);
  1096. bool CheckIfPropOpEmitsTypeCheck(IR::Instr *instr, IR::PropertySymOpnd *opnd);
  1097. bool FinishOptPropOp(IR::Instr *instr, IR::PropertySymOpnd *opnd, BasicBlock* block = nullptr, bool updateExistingValue = false, bool* emitsTypeCheckOut = nullptr, bool* changesTypeValueOut = nullptr);
  1098. void FinishOptHoistedPropOps(Loop * loop);
  1099. IR::Instr * SetTypeCheckBailOut(IR::Opnd *opnd, IR::Instr *instr, BailOutInfo *bailOutInfo);
  1100. void OptArguments(IR::Instr *Instr);
  1101. BOOLEAN IsArgumentsOpnd(IR::Opnd* opnd);
  1102. bool AreFromSameBytecodeFunc(IR::RegOpnd* src1, IR::RegOpnd* dst);
  1103. void TrackArgumentsSym(IR::RegOpnd* opnd);
  1104. void ClearArgumentsSym(IR::RegOpnd* opnd);
  1105. BOOLEAN TestAnyArgumentsSym();
  1106. BOOLEAN IsArgumentsSymID(SymID id, const GlobOptBlockData& blockData);
  1107. Value * ValueNumberDst(IR::Instr **pInstr, Value *src1Val, Value *src2Val);
  1108. Value * ValueNumberLdElemDst(IR::Instr **pInstr, Value *srcVal);
  1109. ValueType GetPrepassValueTypeForDst(const ValueType desiredValueType, IR::Instr *const instr, Value *const src1Value, Value *const src2Value, bool *const isValueInfoPreciseRef = nullptr) const;
  1110. bool IsPrepassSrcValueInfoPrecise(IR::Opnd *const src, Value *const srcValue) const;
  1111. Value * CreateDstUntransferredIntValue(const int32 min, const int32 max, IR::Instr *const instr, Value *const src1Value, Value *const src2Value);
  1112. Value * CreateDstUntransferredValue(const ValueType desiredValueType, IR::Instr *const instr, Value *const src1Value, Value *const src2Value);
  1113. Value * ValueNumberTransferDst(IR::Instr *const instr, Value *src1Val);
  1114. bool IsSafeToTransferInPrePass(IR::Opnd *src, Value *srcValue);
  1115. Value * ValueNumberTransferDstInPrepass(IR::Instr *const instr, Value *const src1Val);
  1116. Value * FindValue(Sym *sym);
  1117. Value * FindValue(GlobHashTable *valueNumberMap, Sym *sym);
  1118. ValueNumber FindValueNumber(GlobHashTable *valueNumberMap, Sym *sym);
  1119. Value * FindValueFromHashTable(GlobHashTable *valueNumberMap, SymID symId);
  1120. ValueNumber FindPropertyValueNumber(GlobHashTable *valueNumberMap, SymID symId);
  1121. Value * FindPropertyValue(GlobHashTable *valueNumberMap, SymID symId);
  1122. Value * FindObjectTypeValue(StackSym* typeSym);
  1123. Value * FindObjectTypeValue(StackSym* typeSym, GlobHashTable *valueNumberMap);
  1124. Value * FindObjectTypeValue(SymID typeSymId, GlobHashTable *valueNumberMap);
  1125. Value * FindObjectTypeValue(StackSym* typeSym, BasicBlock* block);
  1126. Value* FindObjectTypeValue(SymID typeSymId, BasicBlock* block);
  1127. Value * FindObjectTypeValue(StackSym* typeSym, GlobHashTable *valueNumberMap, BVSparse<JitArenaAllocator>* liveFields);
  1128. Value * FindObjectTypeValue(SymID typeSymId, GlobHashTable *valueNumberMap, BVSparse<JitArenaAllocator>* liveFields);
  1129. Value * FindFuturePropertyValue(PropertySym *const propertySym);
  1130. IR::Opnd * CopyProp(IR::Opnd *opnd, IR::Instr *instr, Value *val, IR::IndirOpnd *parentIndirOpnd = nullptr);
  1131. IR::Opnd * CopyPropReplaceOpnd(IR::Instr * instr, IR::Opnd * opnd, StackSym * copySym, IR::IndirOpnd *parentIndirOpnd = nullptr);
  1132. StackSym * GetCopyPropSym(Sym * sym, Value * val);
  1133. StackSym * GetCopyPropSym(BasicBlock * block, Sym * sym, Value * val);
  1134. void MarkTempLastUse(IR::Instr *instr, IR::RegOpnd *regOpnd);
  1135. ValueNumber NewValueNumber();
  1136. Value * NewValue(ValueInfo *const valueInfo);
  1137. Value * NewValue(const ValueNumber valueNumber, ValueInfo *const valueInfo);
  1138. Value * CopyValue(Value *const value);
  1139. Value * CopyValue(Value *const value, const ValueNumber valueNumber);
  1140. Value * NewGenericValue(const ValueType valueType);
  1141. Value * NewGenericValue(const ValueType valueType, IR::Opnd *const opnd);
  1142. Value * NewGenericValue(const ValueType valueType, Sym *const sym);
  1143. Value * GetIntConstantValue(const int32 intConst, IR::Instr * instr, IR::Opnd *const opnd = nullptr);
  1144. Value * NewIntConstantValue(const int32 intConst, IR::Instr * instr, bool isTaggable);
  1145. ValueInfo * NewIntRangeValueInfo(const int32 min, const int32 max, const bool wasNegativeZeroPreventedByBailout);
  1146. ValueInfo * NewIntRangeValueInfo(const ValueInfo *const originalValueInfo, const int32 min, const int32 max) const;
  1147. Value * NewIntRangeValue(const int32 min, const int32 max, const bool wasNegativeZeroPreventedByBailout, IR::Opnd *const opnd = nullptr);
  1148. IntBoundedValueInfo * NewIntBoundedValueInfo(const ValueInfo *const originalValueInfo, const IntBounds *const bounds) const;
  1149. Value * NewIntBoundedValue(const ValueType valueType, const IntBounds *const bounds, const bool wasNegativeZeroPreventedByBailout, IR::Opnd *const opnd = nullptr);
  1150. Value * NewFloatConstantValue(const FloatConstType floatValue, IR::Opnd *const opnd = nullptr);
  1151. Value * GetVarConstantValue(IR::AddrOpnd *addrOpnd);
  1152. Value * NewVarConstantValue(IR::AddrOpnd *addrOpnd, bool isString);
  1153. Value * HoistConstantLoadAndPropagateValueBackward(Js::Var varConst, IR::Instr * origInstr, Value * value);
  1154. Value * NewFixedFunctionValue(Js::JavascriptFunction *functionValue, IR::AddrOpnd *addrOpnd);
  1155. StackSym * GetTaggedIntConstantStackSym(const int32 intConstantValue) const;
  1156. StackSym * GetOrCreateTaggedIntConstantStackSym(const int32 intConstantValue) const;
  1157. Sym * SetSymStore(ValueInfo *valueInfo, Sym *sym);
  1158. Value * InsertNewValue(Value *val, IR::Opnd *opnd);
  1159. Value * InsertNewValue(GlobOptBlockData * blockData, Value *val, IR::Opnd *opnd);
  1160. Value * SetValue(GlobOptBlockData * blockData, Value *val, IR::Opnd *opnd);
  1161. void SetValue(GlobOptBlockData * blockData, Value *val, Sym * sym);
  1162. void SetValueToHashTable(GlobHashTable * valueNumberMap, Value *val, Sym *sym);
  1163. IR::Instr * TypeSpecialization(IR::Instr *instr, Value **pSrc1Val, Value **pSrc2Val, Value **pDstVal, bool *redoTypeSpecRef, bool *const forceInvariantHoistingRef);
  1164. // SIMD_JS
  1165. bool TypeSpecializeSimd128(IR::Instr *instr, Value **pSrc1Val, Value **pSrc2Val, Value **pDstVal);
  1166. bool Simd128DoTypeSpec(IR::Instr *instr, const Value *src1Val, const Value *src2Val, const Value *dstVal);
  1167. bool Simd128CanTypeSpecOpnd(const ValueType opndType, const ValueType expectedType);
  1168. IRType GetIRTypeFromValueType(const ValueType &valueType);
  1169. ValueType GetValueTypeFromIRType(const IRType &type);
  1170. IR::BailOutKind GetBailOutKindFromValueType(const ValueType &valueType);
  1171. IR::Instr * GetExtendedArg(IR::Instr *instr);
  1172. IR::Instr * OptNewScObject(IR::Instr** instrPtr, Value* srcVal);
  1173. bool OptConstFoldBinary(IR::Instr * *pInstr, const IntConstantBounds &src1IntConstantBounds, const IntConstantBounds &src2IntConstantBounds, Value **pDstVal);
  1174. bool OptConstFoldUnary(IR::Instr * *pInstr, const int32 intConstantValue, const bool isUsingOriginalSrc1Value, Value **pDstVal);
  1175. bool OptConstPeep(IR::Instr *instr, IR::Opnd *constSrc, Value **pDstVal, ValueInfo *vInfo);
  1176. bool OptConstFoldBranch(IR::Instr *instr, Value *src1Val, Value*src2Val, Value **pDstVal);
  1177. Js::Var GetConstantVar(IR::Opnd *opnd, Value *val);
  1178. bool IsWorthSpecializingToInt32DueToSrc(IR::Opnd *const src, Value *const val);
  1179. bool IsWorthSpecializingToInt32DueToDst(IR::Opnd *const dst);
  1180. bool IsWorthSpecializingToInt32(IR::Instr *const instr, Value *const src1Val, Value *const src2Val = nullptr);
  1181. bool TypeSpecializeNumberUnary(IR::Instr *instr, Value *src1Val, Value **pDstVal);
  1182. bool TypeSpecializeIntUnary(IR::Instr **pInstr, Value **pSrc1Val, Value **pDstVal, int32 min, int32 max, Value *const src1OriginalVal, bool *redoTypeSpecRef, bool skipDst = false);
  1183. bool TypeSpecializeIntBinary(IR::Instr **pInstr, Value *src1Val, Value *src2Val, Value **pDstVal, int32 min, int32 max, bool skipDst = false);
  1184. void TypeSpecializeInlineBuiltInUnary(IR::Instr **pInstr, Value **pSrc1Val, Value **pDstVal, Value *const src1OriginalVal, bool *redoTypeSpecRef);
  1185. void TypeSpecializeInlineBuiltInBinary(IR::Instr **pInstr, Value *src1Val, Value* src2Val, Value **pDstVal, Value *const src1OriginalVal, Value *const src2OriginalVal);
  1186. void TypeSpecializeInlineBuiltInDst(IR::Instr **pInstr, Value **pDstVal);
  1187. bool TypeSpecializeUnary(IR::Instr **pInstr, Value **pSrc1Val, Value **pDstVal, Value *const src1OriginalVal, bool *redoTypeSpecRef, bool *const forceInvariantHoistingRef);
  1188. bool TypeSpecializeBinary(IR::Instr **pInstr, Value **pSrc1Val, Value **pSrc2Val, Value **pDstVal, Value *const src1OriginalVal, Value *const src2OriginalVal, bool *redoTypeSpecRef);
  1189. bool TypeSpecializeFloatUnary(IR::Instr **pInstr, Value *src1Val, Value **pDstVal, bool skipDst = false);
  1190. bool TypeSpecializeFloatBinary(IR::Instr *instr, Value *src1Val, Value *src2Val, Value **pDstVal);
  1191. void TypeSpecializeFloatDst(IR::Instr *instr, Value *valToTransfer, Value *const src1Value, Value *const src2Value, Value **pDstVal);
  1192. bool TypeSpecializeLdLen(IR::Instr * *const instrRef, Value * *const src1ValueRef, Value * *const dstValueRef, bool *const forceInvariantHoistingRef);
  1193. void TypeSpecializeIntDst(IR::Instr* instr, Js::OpCode originalOpCode, Value* valToTransfer, Value *const src1Value, Value *const src2Value, const IR::BailOutKind bailOutKind, int32 newMin, int32 newMax, Value** pDstVal, const AddSubConstantInfo *const addSubConstantInfo = nullptr);
  1194. void TypeSpecializeIntDst(IR::Instr* instr, Js::OpCode originalOpCode, Value* valToTransfer, Value *const src1Value, Value *const src2Value, const IR::BailOutKind bailOutKind, ValueType valueType, Value** pDstVal, const AddSubConstantInfo *const addSubConstantInfo = nullptr);
  1195. void TypeSpecializeIntDst(IR::Instr* instr, Js::OpCode originalOpCode, Value* valToTransfer, Value *const src1Value, Value *const src2Value, const IR::BailOutKind bailOutKind, ValueType valueType, int32 newMin, int32 newMax, Value** pDstVal, const AddSubConstantInfo *const addSubConstantInfo = nullptr);
  1196. bool TryTypeSpecializeUnaryToFloatHelper(IR::Instr** pInstr, Value** pSrc1Val, Value* const src1OriginalVal, Value **pDstVal);
  1197. bool TypeSpecializeBailoutExpectedInteger(IR::Instr* instr, Value* src1Val, Value** dstVal);
  1198. bool TypeSpecializeStElem(IR::Instr **pInstr, Value *src1Val, Value **pDstVal);
  1199. bool TryGetIntConstIndexValue(IR::Instr *instr, IR::IndirOpnd *indirOpnd, bool checkSym, int32 *pValue, bool *isNotInt);
  1200. bool ShouldExpectConventionalArrayIndexValue(IR::IndirOpnd *const indirOpnd);
  1201. ValueType GetDivValueType(IR::Instr* instr, Value* src1Val, Value* src2Val, bool specialize);
  1202. bool CollectMemOpInfo(IR::Instr *, Value *, Value *);
  1203. bool CollectMemOpStElementI(IR::Instr *, Loop *);
  1204. bool CollectMemsetStElementI(IR::Instr *, Loop *);
  1205. bool CollectMemcopyStElementI(IR::Instr *, Loop *);
  1206. bool CollectMemOpLdElementI(IR::Instr *, Loop *);
  1207. bool CollectMemcopyLdElementI(IR::Instr *, Loop *);
  1208. SymID GetVarSymID(StackSym *);
  1209. const InductionVariable* GetInductionVariable(SymID, Loop *);
  1210. bool IsSymIDInductionVariable(SymID, Loop *);
  1211. bool IsAllowedForMemOpt(IR::Instr* instr, bool isMemset, IR::RegOpnd *baseOpnd, IR::Opnd *indexOpnd);
  1212. void ProcessMemOp();
  1213. bool InspectInstrForMemSetCandidate(Loop* loop, IR::Instr* instr, struct MemSetEmitData* emitData, bool& errorInInstr);
  1214. bool InspectInstrForMemCopyCandidate(Loop* loop, IR::Instr* instr, struct MemCopyEmitData* emitData, bool& errorInInstr);
  1215. bool ValidateMemOpCandidates(Loop * loop, struct MemOpEmitData** emitData, int& iEmitData);
  1216. void HoistHeadSegmentForMemOp(IR::Instr *instr, IR::ArrayRegOpnd *arrayRegOpnd, IR::Instr *insertBeforeInstr);
  1217. void EmitMemop(Loop * loop, LoopCount *loopCount, const struct MemOpEmitData* emitData);
  1218. IR::Opnd* GenerateInductionVariableChangeForMemOp(Loop *loop, byte unroll, IR::Instr *insertBeforeInstr = nullptr);
  1219. IR::RegOpnd* GenerateStartIndexOpndForMemop(Loop *loop, IR::Opnd *indexOpnd, IR::Opnd *sizeOpnd, bool isInductionVariableChangeIncremental, bool bIndexAlreadyChanged, IR::Instr *insertBeforeInstr = nullptr);
  1220. LoopCount* GetOrGenerateLoopCountForMemOp(Loop *loop);
  1221. IR::Instr* FindUpperBoundsCheckInstr(IR::Instr* instr);
  1222. IR::Instr* FindArraySegmentLoadInstr(IR::Instr* instr);
  1223. void RemoveMemOpSrcInstr(IR::Instr* memopInstr, IR::Instr* srcInstr, BasicBlock* block);
  1224. void GetMemOpSrcInfo(Loop* loop, IR::Instr* instr, IR::RegOpnd*& base, IR::RegOpnd*& index, IRType& arrayType);
  1225. bool DoMemOp(Loop * loop);
  1226. private:
  1227. void ChangeValueType(BasicBlock *const block, Value *const value, const ValueType newValueType, const bool preserveSubclassInfo, const bool allowIncompatibleType = false) const;
  1228. void ChangeValueInfo(BasicBlock *const block, Value *const value, ValueInfo *const newValueInfo, const bool allowIncompatibleType = false) const;
  1229. bool AreValueInfosCompatible(const ValueInfo *const v0, const ValueInfo *const v1) const;
  1230. private:
  1231. void VerifyArrayValueInfoForTracking(const ValueInfo *const valueInfo, const bool isJsArray, const BasicBlock *const block, const bool ignoreKnownImplicitCalls = false) const;
  1232. void TrackNewValueForKills(Value *const value);
  1233. void DoTrackNewValueForKills(Value *const value);
  1234. void TrackCopiedValueForKills(Value *const value);
  1235. void DoTrackCopiedValueForKills(Value *const value);
  1236. void TrackMergedValueForKills(Value *const value, GlobOptBlockData *const blockData, BVSparse<JitArenaAllocator> *const mergedValueTypesTrackedForKills) const;
  1237. void DoTrackMergedValueForKills(Value *const value, GlobOptBlockData *const blockData, BVSparse<JitArenaAllocator> *const mergedValueTypesTrackedForKills) const;
  1238. void TrackValueInfoChangeForKills(BasicBlock *const block, Value *const value, ValueInfo *const newValueInfo) const;
  1239. void ProcessValueKills(IR::Instr *const instr);
  1240. void ProcessValueKills(BasicBlock *const block, GlobOptBlockData *const blockData);
  1241. void ProcessValueKillsForLoopHeaderAfterBackEdgeMerge(BasicBlock *const block, GlobOptBlockData *const blockData);
  1242. bool NeedBailOnImplicitCallForLiveValues(BasicBlock *const block, const bool isForwardPass) const;
  1243. IR::Instr* CreateBoundsCheckInstr(IR::Opnd* lowerBound, IR::Opnd* upperBound, int offset, Func* func);
  1244. IR::Instr* CreateBoundsCheckInstr(IR::Opnd* lowerBound, IR::Opnd* upperBound, int offset, IR::BailOutKind bailoutkind, BailOutInfo* bailoutInfo, Func* func);
  1245. IR::Instr* AttachBoundsCheckData(IR::Instr* instr, IR::Opnd* lowerBound, IR::Opnd* upperBound, int offset);
  1246. void OptArraySrc(IR::Instr * *const instrRef);
  1247. private:
  1248. void TrackIntSpecializedAddSubConstant(IR::Instr *const instr, const AddSubConstantInfo *const addSubConstantInfo, Value *const dstValue, const bool updateSourceBounds);
  1249. void CloneBoundCheckHoistBlockData(BasicBlock *const toBlock, GlobOptBlockData *const toData, BasicBlock *const fromBlock, GlobOptBlockData *const fromData);
  1250. void MergeBoundCheckHoistBlockData(BasicBlock *const toBlock, GlobOptBlockData *const toData, BasicBlock *const fromBlock, GlobOptBlockData *const fromData);
  1251. void DetectUnknownChangesToInductionVariables(GlobOptBlockData *const blockData);
  1252. void SetInductionVariableValueNumbers(GlobOptBlockData *const blockData);
  1253. void FinalizeInductionVariables(Loop *const loop, GlobOptBlockData *const headerData);
  1254. bool DetermineSymBoundOffsetOrValueRelativeToLandingPad(StackSym *const sym, const bool landingPadValueIsLowerBound, ValueInfo *const valueInfo, const IntBounds *const bounds, GlobHashTable *const landingPadSymToValueMap, int *const boundOffsetOrValueRef);
  1255. private:
  1256. void DetermineDominatingLoopCountableBlock(Loop *const loop, BasicBlock *const headerBlock);
  1257. void DetermineLoopCount(Loop *const loop);
  1258. void GenerateLoopCount(Loop *const loop, LoopCount *const loopCount);
  1259. void GenerateLoopCountPlusOne(Loop *const loop, LoopCount *const loopCount);
  1260. void GenerateSecondaryInductionVariableBound(Loop *const loop, StackSym *const inductionVariableSym, const LoopCount *const loopCount, const int maxMagnitudeChange, StackSym *const boundSym);
  1261. private:
  1262. void DetermineArrayBoundCheckHoistability(bool needLowerBoundCheck, bool needUpperBoundCheck, ArrayLowerBoundCheckHoistInfo &lowerHoistInfo, ArrayUpperBoundCheckHoistInfo &upperHoistInfo, const bool isJsArray, StackSym *const indexSym, Value *const indexValue, const IntConstantBounds &indexConstantBounds, StackSym *const headSegmentLengthSym, Value *const headSegmentLengthValue, const IntConstantBounds &headSegmentLengthConstantBounds, Loop *const headSegmentLengthInvariantLoop, bool &failedToUpdateCompatibleLowerBoundCheck, bool &failedToUpdateCompatibleUpperBoundCheck);
  1263. private:
  1264. void CaptureNoImplicitCallUses(IR::Opnd *opnd, const bool usesNoMissingValuesInfo, IR::Instr *const includeCurrentInstr = nullptr);
  1265. void InsertNoImplicitCallUses(IR::Instr *const instr);
  1266. void PrepareLoopArrayCheckHoist();
  1267. public:
  1268. JsArrayKills CheckJsArrayKills(IR::Instr *const instr);
  1269. private:
  1270. bool IsOperationThatLikelyKillsJsArraysWithNoMissingValues(IR::Instr *const instr);
  1271. bool NeedBailOnImplicitCallForArrayCheckHoist(BasicBlock *const block, const bool isForwardPass) const;
  1272. private:
  1273. bool PrepareForIgnoringIntOverflow(IR::Instr *const instr);
  1274. void VerifyIntSpecForIgnoringIntOverflow(IR::Instr *const instr);
  1275. void PreLowerCanonicalize(IR::Instr *instr, Value **pSrc1Val, Value **pSrc2Val);
  1276. void ProcessKills(IR::Instr *instr);
  1277. void MergeValueMaps(GlobOptBlockData *toData, BasicBlock *toBlock, BasicBlock *fromBlock, BVSparse<JitArenaAllocator> *const symsRequiringCompensation, BVSparse<JitArenaAllocator> *const symsCreatedForMerge);
  1278. Value * MergeValues(Value *toDataValueMap, Value *fromDataValueMap, Sym *fromDataSym, GlobOptBlockData *toData, GlobOptBlockData *fromData, bool isLoopBackEdge, BVSparse<JitArenaAllocator> *const symsRequiringCompensation, BVSparse<JitArenaAllocator> *const symsCreatedForMerge);
  1279. ValueInfo * MergeValueInfo(Value *toDataVal, Value *fromDataVal, Sym *fromDataSym, GlobOptBlockData *fromData, bool isLoopBackEdge, bool sameValueNumber, BVSparse<JitArenaAllocator> *const symsRequiringCompensation, BVSparse<JitArenaAllocator> *const symsCreatedForMerge);
  1280. ValueInfo * MergeLikelyIntValueInfo(Value *toDataVal, Value *fromDataVal, const ValueType newValueType);
  1281. JsTypeValueInfo * MergeJsTypeValueInfo(JsTypeValueInfo * toValueInfo, JsTypeValueInfo * fromValueInfo, bool isLoopBackEdge, bool sameValueNumber);
  1282. ValueInfo * MergeArrayValueInfo(const ValueType mergedValueType, const ArrayValueInfo *const toDataValueInfo, const ArrayValueInfo *const fromDataValueInfo, Sym *const arraySym, BVSparse<JitArenaAllocator> *const symsRequiringCompensation, BVSparse<JitArenaAllocator> *const symsCreatedForMerge);
  1283. void InsertCloneStrs(BasicBlock *toBlock, GlobOptBlockData *toData, GlobOptBlockData *fromData);
  1284. void InsertValueCompensation(BasicBlock *const predecessor, const SymToValueInfoMap &symsRequiringCompensationToMergedValueInfoMap);
  1285. IR::Instr * ToVarUses(IR::Instr *instr, IR::Opnd *opnd, bool isDst, Value *val);
  1286. void ToVar(BVSparse<JitArenaAllocator> *bv, BasicBlock *block);
  1287. IR::Instr * ToVar(IR::Instr *instr, IR::RegOpnd *regOpnd, BasicBlock *block, Value *val, bool needsUpdate);
  1288. void ToInt32(BVSparse<JitArenaAllocator> *bv, BasicBlock *block, bool lossy, IR::Instr *insertBeforeInstr = nullptr);
  1289. void ToFloat64(BVSparse<JitArenaAllocator> *bv, BasicBlock *block);
  1290. void ToTypeSpec(BVSparse<JitArenaAllocator> *bv, BasicBlock *block, IRType toType, IR::BailOutKind bailOutKind = IR::BailOutInvalid, bool lossy = false, IR::Instr *insertBeforeInstr = nullptr);
  1291. IR::Instr * ToInt32(IR::Instr *instr, IR::Opnd *opnd, BasicBlock *block, Value *val, IR::IndirOpnd *indir, bool lossy);
  1292. IR::Instr * ToFloat64(IR::Instr *instr, IR::Opnd *opnd, BasicBlock *block, Value *val, IR::IndirOpnd *indir, IR::BailOutKind bailOutKind);
  1293. IR::Instr * ToTypeSpecUse(IR::Instr *instr, IR::Opnd *opnd, BasicBlock *block, Value *val, IR::IndirOpnd *indir,
  1294. IRType toType, IR::BailOutKind bailOutKind, bool lossy = false, IR::Instr *insertBeforeInstr = nullptr);
  1295. void ToVarRegOpnd(IR::RegOpnd *dst, BasicBlock *block);
  1296. void ToVarStackSym(StackSym *varSym, BasicBlock *block);
  1297. void ToInt32Dst(IR::Instr *instr, IR::RegOpnd *dst, BasicBlock *block);
  1298. void ToUInt32Dst(IR::Instr *instr, IR::RegOpnd *dst, BasicBlock *block);
  1299. void ToFloat64Dst(IR::Instr *instr, IR::RegOpnd *dst, BasicBlock *block);
  1300. // SIMD_JS
  1301. void TypeSpecializeSimd128Dst(IRType type, IR::Instr *instr, Value *valToTransfer, Value *const src1Value, Value **pDstVal);
  1302. void ToSimd128Dst(IRType toType, IR::Instr *instr, IR::RegOpnd *dst, BasicBlock *block);
  1303. static BOOL IsInt32TypeSpecialized(Sym *sym, BasicBlock *block);
  1304. static BOOL IsInt32TypeSpecialized(Sym *sym, GlobOptBlockData *data);
  1305. static BOOL IsSwitchInt32TypeSpecialized(IR::Instr * instr, BasicBlock * block);
  1306. static BOOL IsFloat64TypeSpecialized(Sym *sym, BasicBlock *block);
  1307. static BOOL IsFloat64TypeSpecialized(Sym *sym, GlobOptBlockData *data);
  1308. // SIMD_JS
  1309. static BOOL IsSimd128TypeSpecialized(Sym *sym, BasicBlock *block);
  1310. static BOOL IsSimd128TypeSpecialized(Sym *sym, GlobOptBlockData *data);
  1311. static BOOL IsSimd128TypeSpecialized(IRType type, Sym *sym, BasicBlock *block);
  1312. static BOOL IsSimd128TypeSpecialized(IRType type, Sym *sym, GlobOptBlockData *data);
  1313. static BOOL IsSimd128F4TypeSpecialized(Sym *sym, BasicBlock *block);
  1314. static BOOL IsSimd128F4TypeSpecialized(Sym *sym, GlobOptBlockData *data);
  1315. static BOOL IsSimd128I4TypeSpecialized(Sym *sym, BasicBlock *block);
  1316. static BOOL IsSimd128I4TypeSpecialized(Sym *sym, GlobOptBlockData *data);
  1317. static BOOL IsLiveAsSimd128(Sym *sym, GlobOptBlockData *data);
  1318. static BOOL IsLiveAsSimd128F4(Sym *sym, GlobOptBlockData *data);
  1319. static BOOL IsLiveAsSimd128I4(Sym *sym, GlobOptBlockData *data);
  1320. static BOOL IsTypeSpecialized(Sym *sym, BasicBlock *block);
  1321. static BOOL IsTypeSpecialized(Sym *sym, GlobOptBlockData *data);
  1322. static BOOL IsLive(Sym *sym, BasicBlock *block);
  1323. static BOOL IsLive(Sym *sym, GlobOptBlockData *data);
  1324. void MakeLive(StackSym *const sym, GlobOptBlockData *const blockData, const bool lossy) const;
  1325. void OptConstFoldBr(bool test, IR::Instr *instr, Value * intTypeSpecSrc1Val = nullptr, Value * intTypeSpecSrc2Val = nullptr);
  1326. void PropagateIntRangeForNot(int32 minimum, int32 maximum, int32 *pNewMin, int32 * pNewMax);
  1327. void PropagateIntRangeBinary(IR::Instr *instr, int32 min1, int32 max1,
  1328. int32 min2, int32 max2, int32 *pNewMin, int32 *pNewMax);
  1329. bool OptIsInvariant(IR::Opnd *src, BasicBlock *block, Loop *loop, Value *srcVal, bool isNotTypeSpecConv, bool allowNonPrimitives);
  1330. bool OptIsInvariant(Sym *sym, BasicBlock *block, Loop *loop, Value *srcVal, bool isNotTypeSpecConv, bool allowNonPrimitives, Value **loopHeadValRef = nullptr);
  1331. bool OptDstIsInvariant(IR::RegOpnd *dst);
  1332. bool OptIsInvariant(IR::Instr *instr, BasicBlock *block, Loop *loop, Value *src1Val, Value *src2Val, bool isNotTypeSpecConv, const bool forceInvariantHoisting = false);
  1333. void OptHoistInvariant(IR::Instr *instr, BasicBlock *block, Loop *loop, Value *dstVal, Value *const src1Val, bool isNotTypeSpecConv, bool lossy = false);
  1334. bool TryHoistInvariant(IR::Instr *instr, BasicBlock *block, Value *dstVal, Value *src1Val, Value *src2Val, bool isNotTypeSpecConv, const bool lossy = false, const bool forceInvariantHoisting = false);
  1335. void HoistInvariantValueInfo(ValueInfo *const invariantValueInfoToHoist, Value *const valueToUpdate, BasicBlock *const targetBlock);
  1336. public:
  1337. static bool IsTypeSpecPhaseOff(Func* func);
  1338. static bool DoAggressiveIntTypeSpec(Func* func);
  1339. static bool DoLossyIntTypeSpec(Func* func);
  1340. static bool DoFloatTypeSpec(Func* func);
  1341. static bool DoStringTypeSpec(Func* func);
  1342. static bool DoArrayCheckHoist(Func *const func);
  1343. static bool DoArrayMissingValueCheckHoist(Func *const func);
  1344. static bool DoArraySegmentHoist(const ValueType baseValueType, Func *const func);
  1345. static bool DoArrayLengthHoist(Func *const func);
  1346. static bool DoTypedArrayTypeSpec(Func* func);
  1347. static bool DoNativeArrayTypeSpec(Func* func);
  1348. static bool IsSwitchOptEnabled(Func* func);
  1349. static bool DoEquivObjTypeSpec(Func* func);
  1350. static bool DoInlineArgsOpt(Func* func);
  1351. static bool IsPREInstrCandidateLoad(Js::OpCode opcode);
  1352. static bool IsPREInstrCandidateStore(Js::OpCode opcode);
  1353. static bool ImplicitCallFlagsAllowOpts(Loop * loop);
  1354. static bool ImplicitCallFlagsAllowOpts(Func *func);
  1355. private:
  1356. bool DoConstFold() const;
  1357. bool DoTypeSpec() const;
  1358. bool DoAggressiveIntTypeSpec() const;
  1359. bool DoAggressiveMulIntTypeSpec() const;
  1360. bool DoDivIntTypeSpec() const;
  1361. bool DoLossyIntTypeSpec() const;
  1362. bool DoFloatTypeSpec() const;
  1363. bool DoStringTypeSpec() const { return GlobOpt::DoStringTypeSpec(this->func); }
  1364. bool DoArrayCheckHoist() const;
  1365. bool DoArrayCheckHoist(const ValueType baseValueType, Loop* loop, IR::Instr *const instr = nullptr) const;
  1366. bool DoArrayMissingValueCheckHoist() const;
  1367. bool DoArraySegmentHoist(const ValueType baseValueType) const;
  1368. bool DoTypedArraySegmentLengthHoist(Loop *const loop) const;
  1369. bool DoArrayLengthHoist() const;
  1370. bool DoEliminateArrayAccessHelperCall() const;
  1371. bool DoTypedArrayTypeSpec() const { return GlobOpt::DoTypedArrayTypeSpec(this->func); }
  1372. bool DoNativeArrayTypeSpec() const { return GlobOpt::DoNativeArrayTypeSpec(this->func); }
  1373. bool DoLdLenIntSpec(IR::Instr *const instr, const ValueType baseValueType) const;
  1374. bool IsSwitchOptEnabled() const { return GlobOpt::IsSwitchOptEnabled(this->func); }
  1375. bool DoPathDependentValues() const;
  1376. bool DoTrackRelativeIntBounds() const;
  1377. bool DoBoundCheckElimination() const;
  1378. bool DoBoundCheckHoist() const;
  1379. bool DoLoopCountBasedBoundCheckHoist() const;
  1380. private:
  1381. // GlobOptBailout.cpp
  1382. bool MayNeedBailOut(Loop * loop) const;
  1383. static void TrackByteCodeSymUsed(IR::Opnd * opnd, BVSparse<JitArenaAllocator> * instrByteCodeStackSymUsed, PropertySym **pPropertySymUse);
  1384. static void TrackByteCodeSymUsed(IR::RegOpnd * opnd, BVSparse<JitArenaAllocator> * instrByteCodeStackSymUsed);
  1385. static void TrackByteCodeSymUsed(StackSym * sym, BVSparse<JitArenaAllocator> * instrByteCodeStackSymUsed);
  1386. void CaptureValues(BasicBlock *block, BailOutInfo * bailOutInfo);
  1387. void CaptureValue(BasicBlock *block, StackSym * stackSym, Value * value, BailOutInfo * bailOutInfo);
  1388. void CaptureArguments(BasicBlock *block, BailOutInfo * bailOutInfo, JitArenaAllocator *allocator);
  1389. void CaptureByteCodeSymUses(IR::Instr * instr);
  1390. IR::ByteCodeUsesInstr * InsertByteCodeUses(IR::Instr * instr, bool includeDef = false);
  1391. void TrackCalls(IR::Instr * instr);
  1392. void RecordInlineeFrameInfo(IR::Instr* instr);
  1393. void EndTrackCall(IR::Instr * instr);
  1394. void EndTrackingOfArgObjSymsForInlinee();
  1395. void FillBailOutInfo(BasicBlock *block, BailOutInfo *bailOutInfo);
  1396. static void MarkNonByteCodeUsed(IR::Instr * instr);
  1397. static void MarkNonByteCodeUsed(IR::Opnd * opnd);
  1398. bool IsImplicitCallBailOutCurrentlyNeeded(IR::Instr * instr, Value *src1Val, Value *src2Val);
  1399. bool IsImplicitCallBailOutCurrentlyNeeded(IR::Instr * instr, Value *src1Val, Value *src2Val, BasicBlock * block, bool hasLiveFields, bool mayNeedImplicitCallBailOut, bool isForwardPass);
  1400. static bool IsTypeCheckProtected(const IR::Instr * instr);
  1401. static bool MayNeedBailOnImplicitCall(const IR::Instr * instr, Value *src1Val, Value *src2Val);
  1402. static bool MayNeedBailOnImplicitCall(IR::Opnd * opnd, Value *val, bool callsToPrimitive);
  1403. void GenerateBailAfterOperation(IR::Instr * *const pInstr, IR::BailOutKind kind);
  1404. public:
  1405. void GenerateBailAtOperation(IR::Instr * *const pInstr, const IR::BailOutKind bailOutKind);
  1406. private:
  1407. IR::Instr * EnsureBailTarget(Loop * loop);
  1408. // GlobOptFields.cpp
  1409. void ProcessFieldKills(IR::Instr * instr);
  1410. void KillLiveFields(StackSym * stackSym, BVSparse<JitArenaAllocator> * bv);
  1411. void KillLiveFields(PropertySym * propertySym, BVSparse<JitArenaAllocator> * bv);
  1412. void KillLiveFields(BVSparse<JitArenaAllocator> *const propertyEquivSet, BVSparse<JitArenaAllocator> *const bv) const;
  1413. void KillLiveElems(IR::IndirOpnd * indirOpnd, BVSparse<JitArenaAllocator> * bv, bool inGlobOpt, Func *func);
  1414. void KillAllFields(BVSparse<JitArenaAllocator> * bv);
  1415. void SetAnyPropertyMayBeWrittenTo();
  1416. void AddToPropertiesWrittenTo(Js::PropertyId propertyId);
  1417. bool DoFieldCopyProp() const;
  1418. bool DoFieldCopyProp(Loop * loop) const;
  1419. bool DoFunctionFieldCopyProp() const;
  1420. bool DoFieldHoisting() const;
  1421. bool DoObjTypeSpec() const;
  1422. bool DoObjTypeSpec(Loop * loop) const;
  1423. bool DoEquivObjTypeSpec() const { return DoEquivObjTypeSpec(this->func); }
  1424. bool DoFieldRefOpts() const { return DoObjTypeSpec(); }
  1425. bool DoFieldRefOpts(Loop * loop) const { return DoObjTypeSpec(loop); }
  1426. bool DoFieldOpts(Loop * loop) const;
  1427. bool DoFieldPRE() const;
  1428. bool DoFieldPRE(Loop *loop) const;
  1429. bool FieldHoistOptSrc(IR::Opnd *opnd, IR::Instr *instr, PropertySym * propertySym);
  1430. void FieldHoistOptDst(IR::Instr * instr, PropertySym * propertySym, Value * src1Val);
  1431. bool TrackHoistableFields() const;
  1432. void PreparePrepassFieldHoisting(Loop * loop);
  1433. void PrepareFieldHoisting(Loop * loop);
  1434. void CheckFieldHoistCandidate(IR::Instr * instr, PropertySym * sym);
  1435. Loop * FindFieldHoistStackSym(Loop * startLoop, SymID propertySymId, StackSym ** copySym, IR::Instr * instrToHoist = nullptr) const;
  1436. bool CopyPropHoistedFields(PropertySym * sym, IR::Opnd ** ppOpnd, IR::Instr * instr);
  1437. void HoistFieldLoad(PropertySym * sym, Loop * loop, IR::Instr * instr, Value * oldValue, Value * newValue);
  1438. void HoistNewFieldLoad(PropertySym * sym, Loop * loop, IR::Instr * instr, Value * oldValue, Value * newValue);
  1439. void GenerateHoistFieldLoad(PropertySym * sym, Loop * loop, IR::Instr * instr, StackSym * newStackSym, Value * oldValue, Value * newValue);
  1440. void HoistFieldLoadValue(Loop * loop, Value * newValue, SymID symId, Js::OpCode opcode, IR::Opnd * srcOpnd);
  1441. void ReloadFieldHoistStackSym(IR::Instr * instr, PropertySym * propertySym);
  1442. void CopyStoreFieldHoistStackSym(IR::Instr * storeFldInstr, PropertySym * sym, Value * src1Val);
  1443. Value * CreateFieldSrcValue(PropertySym * sym, PropertySym * originalSym, IR::Opnd **ppOpnd, IR::Instr * instr);
  1444. static bool HasHoistableFields(BasicBlock * block);
  1445. static bool HasHoistableFields(GlobOptBlockData const * globOptData);
  1446. bool IsHoistablePropertySym(SymID symId) const;
  1447. bool NeedBailOnImplicitCallWithFieldOpts(Loop *loop, bool hasLiveFields) const;
  1448. IR::Instr * EnsureDisableImplicitCallRegion(Loop * loop);
  1449. void UpdateObjPtrValueType(IR::Opnd * opnd, IR::Instr * instr);
  1450. bool TrackArgumentsObject();
  1451. void CannotAllocateArgumentsObjectOnStack();
  1452. #if DBG
  1453. bool IsPropertySymId(SymID symId) const;
  1454. bool IsHoistedPropertySym(PropertySym * sym) const;
  1455. bool IsHoistedPropertySym(SymID symId, Loop * loop) const;
  1456. static void AssertCanCopyPropOrCSEFieldLoad(IR::Instr * instr);
  1457. #endif
  1458. StackSym * EnsureObjectTypeSym(StackSym * objectSym);
  1459. PropertySym * EnsurePropertyWriteGuardSym(PropertySym * propertySym);
  1460. void PreparePropertySymForTypeCheckSeq(PropertySym *propertySym);
  1461. bool IsPropertySymPreparedForTypeCheckSeq(PropertySym *propertySym);
  1462. bool PreparePropertySymOpndForTypeCheckSeq(IR::PropertySymOpnd *propertySymOpnd, IR::Instr * instr, Loop *loop);
  1463. static bool AreTypeSetsIdentical(Js::EquivalentTypeSet * leftTypeSet, Js::EquivalentTypeSet * rightTypeSet);
  1464. static bool IsSubsetOf(Js::EquivalentTypeSet * leftTypeSet, Js::EquivalentTypeSet * rightTypeSet);
  1465. bool ProcessPropOpInTypeCheckSeq(IR::Instr* instr, IR::PropertySymOpnd *opnd);
  1466. bool CheckIfInstrInTypeCheckSeqEmitsTypeCheck(IR::Instr* instr, IR::PropertySymOpnd *opnd);
  1467. template<bool makeChanges>
  1468. bool ProcessPropOpInTypeCheckSeq(IR::Instr* instr, IR::PropertySymOpnd *opnd, BasicBlock* block, bool updateExistingValue, bool* emitsTypeCheckOut = nullptr, bool* changesTypeValueOut = nullptr, bool *isObjTypeChecked = nullptr);
  1469. void KillObjectHeaderInlinedTypeSyms(BasicBlock *block, bool isObjTypeSpecialized, SymID symId = (SymID)-1);
  1470. void ValueNumberObjectType(IR::Opnd *dstOpnd, IR::Instr *instr);
  1471. void SetSingleTypeOnObjectTypeValue(Value* value, const Js::Type* type);
  1472. void SetTypeSetOnObjectTypeValue(Value* value, Js::EquivalentTypeSet* typeSet);
  1473. void UpdateObjectTypeValue(Value* value, const Js::Type* type, bool setType, Js::EquivalentTypeSet* typeSet, bool setTypeSet);
  1474. void SetObjectTypeFromTypeSym(StackSym *typeSym, Value* value, BasicBlock* block = nullptr);
  1475. void SetObjectTypeFromTypeSym(StackSym *typeSym, const Js::Type *type, Js::EquivalentTypeSet * typeSet, BasicBlock* block = nullptr, bool updateExistingValue = false);
  1476. void SetObjectTypeFromTypeSym(StackSym *typeSym, const Js::Type *type, Js::EquivalentTypeSet * typeSet, GlobOptBlockData *blockData, bool updateExistingValue = false);
  1477. void KillObjectType(StackSym *objectSym, BVSparse<JitArenaAllocator>* liveFields = nullptr);
  1478. void KillAllObjectTypes(BVSparse<JitArenaAllocator>* liveFields = nullptr);
  1479. void EndFieldLifetime(IR::SymOpnd *symOpnd);
  1480. PropertySym * CopyPropPropertySymObj(IR::SymOpnd *opnd, IR::Instr *instr);
  1481. static bool NeedsTypeCheckBailOut(const IR::Instr *instr, IR::PropertySymOpnd *propertySymOpnd, bool isStore, bool* pIsTypeCheckProtected, IR::BailOutKind *pBailOutKind);
  1482. IR::Instr * PreOptPeep(IR::Instr *instr);
  1483. IR::Instr * OptPeep(IR::Instr *instr, Value *src1Val, Value *src2Val);
  1484. void OptimizeIndirUses(IR::IndirOpnd *indir, IR::Instr * *pInstr, Value **indirIndexValRef);
  1485. void RemoveCodeAfterNoFallthroughInstr(IR::Instr *instr);
  1486. void ProcessTryCatch(IR::Instr* instr);
  1487. void InsertToVarAtDefInTryRegion(IR::Instr * instr, IR::Opnd * dstOpnd);
  1488. void RemoveFlowEdgeToCatchBlock(IR::Instr * instr);
  1489. void CSEAddInstr(BasicBlock *block, IR::Instr *instr, Value *dstVal, Value *src1Val, Value *src2Val, Value *dstIndirIndexVal, Value *src1IndirIndexVal);
  1490. bool CSEOptimize(BasicBlock *block, IR::Instr * *const instrRef, Value **pSrc1Val, Value **pSrc2Val, Value **pSrc1IndirIndexVal, bool intMathExprOnly = false);
  1491. bool GetHash(IR::Instr *instr, Value *src1Val, Value *src2Val, ExprAttributes exprAttributes, ExprHash *pHash);
  1492. void ProcessArrayValueKills(IR::Instr *instr);
  1493. static bool NeedBailOnImplicitCallForCSE(BasicBlock *block, bool isForwardPass);
  1494. bool DoCSE();
  1495. bool CanCSEArrayStore(IR::Instr *instr);
  1496. #if DBG_DUMP
  1497. void Dump();
  1498. void DumpSymToValueMap();
  1499. void DumpSymToValueMap(GlobHashTable* symToValueMap);
  1500. void DumpSymToValueMap(BasicBlock *block);
  1501. static void DumpSym(Sym *sym);
  1502. void DumpSymVal(int index);
  1503. void Trace(BasicBlock * basicBlock, bool before);
  1504. void TraceSettings();
  1505. #endif
  1506. bool IsWorthSpecializingToInt32Branch(IR::Instr * instr, Value * src1Val, Value * src2Val);
  1507. bool TryOptConstFoldBrFalse(IR::Instr *const instr, Value *const srcValue, const int32 min, const int32 max);
  1508. bool TryOptConstFoldBrEqual(IR::Instr *const instr, const bool branchOnEqual, Value *const src1Value, const int32 min1, const int32 max1, Value *const src2Value, const int32 min2, const int32 max2);
  1509. bool TryOptConstFoldBrGreaterThan(IR::Instr *const instr, const bool branchOnGreaterThan, Value *const src1Value, const int32 min1, const int32 max1, Value *const src2Value, const int32 min2, const int32 max2);
  1510. bool TryOptConstFoldBrGreaterThanOrEqual(IR::Instr *const instr, const bool branchOnGreaterThanOrEqual, Value *const src1Value, const int32 min1, const int32 max1, Value *const src2Value, const int32 min2, const int32 max2);
  1511. bool TryOptConstFoldBrUnsignedLessThan(IR::Instr *const instr, const bool branchOnLessThan, Value *const src1Value, const int32 min1, const int32 max1, Value *const src2Value, const int32 min2, const int32 max2);
  1512. bool TryOptConstFoldBrUnsignedGreaterThan(IR::Instr *const instr, const bool branchOnGreaterThan, Value *const src1Value, const int32 min1, const int32 max1, Value *const src2Value, const int32 min2, const int32 max2);
  1513. void UpdateIntBoundsForEqualBranch(Value *const src1Value, Value *const src2Value, const int32 src2ConstantValue = 0);
  1514. void UpdateIntBoundsForNotEqualBranch(Value *const src1Value, Value *const src2Value, const int32 src2ConstantValue = 0);
  1515. void UpdateIntBoundsForGreaterThanOrEqualBranch(Value *const src1Value, Value *const src2Value);
  1516. void UpdateIntBoundsForGreaterThanBranch(Value *const src1Value, Value *const src2Value);
  1517. void UpdateIntBoundsForLessThanOrEqualBranch(Value *const src1Value, Value *const src2Value);
  1518. void UpdateIntBoundsForLessThanBranch(Value *const src1Value, Value *const src2Value);
  1519. IntBounds * GetIntBoundsToUpdate(const ValueInfo *const valueInfo, const IntConstantBounds &constantBounds, const bool isSettingNewBound, const bool isBoundConstant, const bool isSettingUpperBound, const bool isExplicit);
  1520. ValueInfo * UpdateIntBoundsForEqual(Value *const value, const IntConstantBounds &constantBounds, Value *const boundValue, const IntConstantBounds &boundConstantBounds, const bool isExplicit);
  1521. ValueInfo * UpdateIntBoundsForNotEqual(Value *const value, const IntConstantBounds &constantBounds, Value *const boundValue, const IntConstantBounds &boundConstantBounds, const bool isExplicit);
  1522. ValueInfo * UpdateIntBoundsForGreaterThanOrEqual(Value *const value, const IntConstantBounds &constantBounds, Value *const boundValue, const IntConstantBounds &boundConstantBounds, const bool isExplicit);
  1523. ValueInfo * UpdateIntBoundsForGreaterThanOrEqual(Value *const value, const IntConstantBounds &constantBounds, Value *const boundValue, const IntConstantBounds &boundConstantBounds, const int boundOffset, const bool isExplicit);
  1524. ValueInfo * UpdateIntBoundsForGreaterThan(Value *const value, const IntConstantBounds &constantBounds, Value *const boundValue, const IntConstantBounds &boundConstantBounds, const bool isExplicit);
  1525. ValueInfo * UpdateIntBoundsForLessThanOrEqual(Value *const value, const IntConstantBounds &constantBounds, Value *const boundValue, const IntConstantBounds &boundConstantBounds, const bool isExplicit);
  1526. ValueInfo * UpdateIntBoundsForLessThanOrEqual(Value *const value, const IntConstantBounds &constantBounds, Value *const boundValue, const IntConstantBounds &boundConstantBounds, const int boundOffset, const bool isExplicit);
  1527. ValueInfo * UpdateIntBoundsForLessThan(Value *const value, const IntConstantBounds &constantBounds, Value *const boundValue, const IntConstantBounds &boundConstantBounds, const bool isExplicit);
  1528. void SetPathDependentInfo(const bool conditionToBranch, const PathDependentInfo &info);
  1529. PathDependentInfoToRestore UpdatePathDependentInfo(PathDependentInfo *const info);
  1530. void RestorePathDependentInfo(PathDependentInfo *const info, const PathDependentInfoToRestore infoToRestore);
  1531. IR::Instr * TrackMarkTempObject(IR::Instr * instrStart, IR::Instr * instrEnd);
  1532. void TrackTempObjectSyms(IR::Instr * instr, IR::RegOpnd * opnd);
  1533. IR::Instr * GenerateBailOutMarkTempObjectIfNeeded(IR::Instr * instr, IR::Opnd * opnd, bool isDst);
  1534. bool IsDefinedInCurrentLoopIteration(Loop *loop, Value *val) const;
  1535. void KillStateForGeneratorYield();
  1536. static void InstantiateForceInlinedMembers_GlobOptIntBounds();
  1537. friend class InvariantBlockBackwardIterator;
  1538. };