Source/JavaScriptCore/ChangeLog

 12018-03-11 Yusuke Suzuki <utatane.tea@gmail.com>
 2
 3 [B3] Above/Below should be strength-reduced for comparison with 0
 4 https://bugs.webkit.org/show_bug.cgi?id=183543
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Above(0, x) and BelowEqual(0, x) can be converted to constants false and true respectively.
 9 This can be seen in ArraySlice(0) case: `Select(Above(0, length), length, 0)` this should
 10 be converted to `0`. This patch adds such a folding to comparisons.
 11
 12 We also fix B3ReduceStrength issue creating an orphan value. This issue causes JSC test failure
 13 with this B3Const32/64Value change. We carefully change the opcode of m_value to fix this issue.
 14
 15 * b3/B3Const32Value.cpp:
 16 (JSC::B3::Const32Value::lessThanConstant const):
 17 (JSC::B3::Const32Value::greaterThanConstant const):
 18 (JSC::B3::Const32Value::lessEqualConstant const):
 19 (JSC::B3::Const32Value::greaterEqualConstant const):
 20 (JSC::B3::Const32Value::aboveConstant const):
 21 (JSC::B3::Const32Value::belowConstant const):
 22 (JSC::B3::Const32Value::aboveEqualConstant const):
 23 (JSC::B3::Const32Value::belowEqualConstant const):
 24 * b3/B3Const64Value.cpp:
 25 (JSC::B3::Const64Value::lessThanConstant const):
 26 (JSC::B3::Const64Value::greaterThanConstant const):
 27 (JSC::B3::Const64Value::lessEqualConstant const):
 28 (JSC::B3::Const64Value::greaterEqualConstant const):
 29 (JSC::B3::Const64Value::aboveConstant const):
 30 (JSC::B3::Const64Value::belowConstant const):
 31 (JSC::B3::Const64Value::aboveEqualConstant const):
 32 (JSC::B3::Const64Value::belowEqualConstant const):
 33 * b3/B3ReduceStrength.cpp:
 34 * b3/testb3.cpp:
 35 (JSC::B3::int64Operands):
 36 (JSC::B3::int32Operands):
 37
1382018-03-10 Yusuke Suzuki <utatane.tea@gmail.com>
239
340 [FTL] Drop NewRegexp for String.prototype.match with RegExp + global flag

Source/JavaScriptCore/b3/B3Const32Value.cpp

@@TriState Const32Value::notEqualConstant(const Value* other) const
220220
221221TriState Const32Value::lessThanConstant(const Value* other) const
222222{
 223 // INT32_MAX < x is always false.
 224 if (static_cast<int32_t>(m_value) == std::numeric_limits<int32_t>::max())
 225 return FalseTriState;
223226 if (!other->hasInt32())
224227 return MixedTriState;
225228 return triState(m_value < other->asInt32());

@@TriState Const32Value::lessThanConstant(const Value* other) const
227230
228231TriState Const32Value::greaterThanConstant(const Value* other) const
229232{
 233 // INT32_MIN > x is always false.
 234 if (static_cast<int32_t>(m_value) == std::numeric_limits<int32_t>::min())
 235 return FalseTriState;
230236 if (!other->hasInt32())
231237 return MixedTriState;
232238 return triState(m_value > other->asInt32());

@@TriState Const32Value::greaterThanConstant(const Value* other) const
234240
235241TriState Const32Value::lessEqualConstant(const Value* other) const
236242{
 243 // INT32_MIN <= x is always true.
 244 if (static_cast<int32_t>(m_value) == std::numeric_limits<int32_t>::min())
 245 return TrueTriState;
237246 if (!other->hasInt32())
238247 return MixedTriState;
239248 return triState(m_value <= other->asInt32());

@@TriState Const32Value::lessEqualConstant(const Value* other) const
241250
242251TriState Const32Value::greaterEqualConstant(const Value* other) const
243252{
 253 // INT32_MAX >= x is always true.
 254 if (static_cast<int32_t>(m_value) == std::numeric_limits<int32_t>::max())
 255 return TrueTriState;
244256 if (!other->hasInt32())
245257 return MixedTriState;
246258 return triState(m_value >= other->asInt32());

@@TriState Const32Value::greaterEqualConstant(const Value* other) const
248260
249261TriState Const32Value::aboveConstant(const Value* other) const
250262{
 263 // UINT32_MIN > x is always false.
 264 if (static_cast<uint32_t>(m_value) == std::numeric_limits<uint32_t>::min())
 265 return FalseTriState;
251266 if (!other->hasInt32())
252267 return MixedTriState;
253268 return triState(static_cast<uint32_t>(m_value) > static_cast<uint32_t>(other->asInt32()));

@@TriState Const32Value::aboveConstant(const Value* other) const
255270
256271TriState Const32Value::belowConstant(const Value* other) const
257272{
 273 // UINT32_MAX < x is always false.
 274 if (static_cast<uint32_t>(m_value) == std::numeric_limits<uint32_t>::max())
 275 return FalseTriState;
258276 if (!other->hasInt32())
259277 return MixedTriState;
260278 return triState(static_cast<uint32_t>(m_value) < static_cast<uint32_t>(other->asInt32()));

@@TriState Const32Value::belowConstant(const Value* other) const
262280
263281TriState Const32Value::aboveEqualConstant(const Value* other) const
264282{
 283 // UINT32_MAX >= x is always true.
 284 if (static_cast<uint32_t>(m_value) == std::numeric_limits<uint32_t>::max())
 285 return TrueTriState;
265286 if (!other->hasInt32())
266287 return MixedTriState;
267288 return triState(static_cast<uint32_t>(m_value) >= static_cast<uint32_t>(other->asInt32()));

@@TriState Const32Value::aboveEqualConstant(const Value* other) const
269290
270291TriState Const32Value::belowEqualConstant(const Value* other) const
271292{
 293 // UINT32_MIN <= x is always true.
 294 if (static_cast<uint32_t>(m_value) == std::numeric_limits<uint32_t>::min())
 295 return TrueTriState;
272296 if (!other->hasInt32())
273297 return MixedTriState;
274298 return triState(static_cast<uint32_t>(m_value) <= static_cast<uint32_t>(other->asInt32()));

Source/JavaScriptCore/b3/B3Const64Value.cpp

@@TriState Const64Value::notEqualConstant(const Value* other) const
220220
221221TriState Const64Value::lessThanConstant(const Value* other) const
222222{
 223 // INT64_MAX < x is always false.
 224 if (static_cast<int64_t>(m_value) == std::numeric_limits<int64_t>::max())
 225 return FalseTriState;
223226 if (!other->hasInt64())
224227 return MixedTriState;
225228 return triState(m_value < other->asInt64());

@@TriState Const64Value::lessThanConstant(const Value* other) const
227230
228231TriState Const64Value::greaterThanConstant(const Value* other) const
229232{
 233 // INT64_MIN > x is always false.
 234 if (static_cast<int64_t>(m_value) == std::numeric_limits<int64_t>::min())
 235 return FalseTriState;
230236 if (!other->hasInt64())
231237 return MixedTriState;
232238 return triState(m_value > other->asInt64());

@@TriState Const64Value::greaterThanConstant(const Value* other) const
234240
235241TriState Const64Value::lessEqualConstant(const Value* other) const
236242{
 243 // INT64_MIN <= x is always true.
 244 if (static_cast<int64_t>(m_value) == std::numeric_limits<int64_t>::min())
 245 return TrueTriState;
237246 if (!other->hasInt64())
238247 return MixedTriState;
239248 return triState(m_value <= other->asInt64());

@@TriState Const64Value::lessEqualConstant(const Value* other) const
241250
242251TriState Const64Value::greaterEqualConstant(const Value* other) const
243252{
 253 // INT64_MAX >= x is always true.
 254 if (static_cast<int64_t>(m_value) == std::numeric_limits<int64_t>::max())
 255 return TrueTriState;
244256 if (!other->hasInt64())
245257 return MixedTriState;
246258 return triState(m_value >= other->asInt64());

@@TriState Const64Value::greaterEqualConstant(const Value* other) const
248260
249261TriState Const64Value::aboveConstant(const Value* other) const
250262{
 263 // UINT64_MIN > x is always false.
 264 if (static_cast<uint64_t>(m_value) == std::numeric_limits<uint64_t>::min())
 265 return FalseTriState;
251266 if (!other->hasInt64())
252267 return MixedTriState;
253268 return triState(static_cast<uint64_t>(m_value) > static_cast<uint64_t>(other->asInt64()));

@@TriState Const64Value::aboveConstant(const Value* other) const
255270
256271TriState Const64Value::belowConstant(const Value* other) const
257272{
 273 // UINT64_MAX < x is always false.
 274 if (static_cast<uint64_t>(m_value) == std::numeric_limits<uint64_t>::max())
 275 return FalseTriState;
258276 if (!other->hasInt64())
259277 return MixedTriState;
260278 return triState(static_cast<uint64_t>(m_value) < static_cast<uint64_t>(other->asInt64()));

@@TriState Const64Value::belowConstant(const Value* other) const
262280
263281TriState Const64Value::aboveEqualConstant(const Value* other) const
264282{
 283 // UINT64_MAX >= x is always true.
 284 if (static_cast<uint64_t>(m_value) == std::numeric_limits<uint64_t>::max())
 285 return TrueTriState;
265286 if (!other->hasInt64())
266287 return MixedTriState;
267288 return triState(static_cast<uint64_t>(m_value) >= static_cast<uint64_t>(other->asInt64()));

@@TriState Const64Value::aboveEqualConstant(const Value* other) const
269290
270291TriState Const64Value::belowEqualConstant(const Value* other) const
271292{
 293 // UINT64_MIN <= x is always true.
 294 if (static_cast<uint64_t>(m_value) == std::numeric_limits<uint64_t>::min())
 295 return TrueTriState;
272296 if (!other->hasInt64())
273297 return MixedTriState;
274298 return triState(static_cast<uint64_t>(m_value) <= static_cast<uint64_t>(other->asInt64()));

Source/JavaScriptCore/b3/B3ReduceStrength.cpp

@@class ReduceStrength {
16731673 case Below:
16741674 case AboveEqual:
16751675 case BelowEqual: {
1676  auto* value = newComparisonVaueIfNecessary();
 1676 handleComparisonCommutativity();
 1677
16771678 TriState result = MixedTriState;
1678  switch (value->opcode()) {
 1679 switch (m_value->opcode()) {
16791680 case LessThan:
1680  result = value->child(1)->greaterThanConstant(value->child(0));
 1681 result = m_value->child(1)->greaterThanConstant(m_value->child(0));
16811682 break;
16821683 case GreaterThan:
1683  result = value->child(1)->lessThanConstant(value->child(0));
 1684 result = m_value->child(1)->lessThanConstant(m_value->child(0));
16841685 break;
16851686 case LessEqual:
1686  result = value->child(1)->greaterEqualConstant(value->child(0));
 1687 result = m_value->child(1)->greaterEqualConstant(m_value->child(0));
16871688 break;
16881689 case GreaterEqual:
1689  result = value->child(1)->lessEqualConstant(value->child(0));
 1690 result = m_value->child(1)->lessEqualConstant(m_value->child(0));
16901691 break;
16911692 case Above:
1692  result = value->child(1)->belowConstant(value->child(0));
 1693 result = m_value->child(1)->belowConstant(m_value->child(0));
16931694 break;
16941695 case Below:
1695  result = value->child(1)->aboveConstant(value->child(0));
 1696 result = m_value->child(1)->aboveConstant(m_value->child(0));
16961697 break;
16971698 case AboveEqual:
1698  result = value->child(1)->belowEqualConstant(value->child(0));
 1699 result = m_value->child(1)->belowEqualConstant(m_value->child(0));
16991700 break;
17001701 case BelowEqual:
1701  result = value->child(1)->aboveEqualConstant(value->child(0));
 1702 result = m_value->child(1)->aboveEqualConstant(m_value->child(0));
17021703 break;
17031704 default:
17041705 RELEASE_ASSERT_NOT_REACHED();
17051706 break;
17061707 }
17071708
1708  if (auto* constant = m_proc.addBoolConstant(value->origin(), result)) {
1709  replaceWithNewValue(constant);
1710  break;
1711  }
1712 
1713  // Replace with newly created "value". Its opcode is flipped and operands are swapped from m_value.
1714  if (m_value != value)
1715  replaceWithNewValue(value);
 1709 replaceWithNewValue(m_proc.addBoolConstant(m_value->origin(), result));
17161710 break;
17171711 }
17181712

@@class ReduceStrength {
21662160 }
21672161 }
21682162
2169  Value* newComparisonVaueIfNecessary()
 2163 void handleComparisonCommutativity()
21702164 {
21712165 auto flip = [] (Opcode opcode) {
21722166 switch (opcode) {

@@class ReduceStrength {
21922186 };
21932187 if (shouldSwapBinaryOperands(m_value)) {
21942188 m_changed = true;
2195  return m_proc.add<Value>(flip(m_value->opcode()), m_value->origin(), m_value->child(1), m_value->child(0));
 2189 std::swap(m_value->child(0), m_value->child(1));
 2190 // Do this really carefully. Here, we are allowed to convert m_value to some other ones (as we convert it to Identity).
 2191 // And all the comparison nodes should have the same C++ classes. Changing opcode here is safe.
 2192 m_value->setOpcodeUnsafely(flip(m_value->opcode()));
21962193 }
2197  return m_value;
21982194 }
21992195
22002196 // FIXME: This should really be a forward analysis. Instead, we uses a bounded-search backwards

Source/JavaScriptCore/b3/testb3.cpp

@@static Vector<Int64Operand> int64Operands()
247247 operands.append({ "int64-min", std::numeric_limits<int64_t>::min() });
248248 operands.append({ "int32-max", std::numeric_limits<int32_t>::max() });
249249 operands.append({ "int32-min", std::numeric_limits<int32_t>::min() });
 250 operands.append({ "uint64-max", static_cast<int64_t>(std::numeric_limits<uint64_t>::max()) });
 251 operands.append({ "uint64-min", static_cast<int64_t>(std::numeric_limits<uint64_t>::min()) });
 252 operands.append({ "uint32-max", static_cast<int64_t>(std::numeric_limits<uint32_t>::max()) });
 253 operands.append({ "uint32-min", static_cast<int64_t>(std::numeric_limits<uint32_t>::min()) });
250254
251255 return operands;
252256}

@@static Vector<Int32Operand> int32Operands()
260264 { "42", 42 },
261265 { "-42", -42 },
262266 { "int32-max", std::numeric_limits<int32_t>::max() },
263  { "int32-min", std::numeric_limits<int32_t>::min() }
 267 { "int32-min", std::numeric_limits<int32_t>::min() },
 268 { "uint32-max", static_cast<int32_t>(std::numeric_limits<uint32_t>::max()) },
 269 { "uint32-min", static_cast<int32_t>(std::numeric_limits<uint32_t>::min()) }
264270 });
265271 return operands;
266272}