GlobOpt.h 93 KB

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