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. If a flipped value is folded to
 13 a constant, we do not insert flipped value and make it an orphan. This issue causes JSC test
 14 failure with this B3Const32/64Value change. With this patch, we create a flipped value only
 15 when we fail to fold it to a constant.
 16
 17 * b3/B3Const32Value.cpp:
 18 (JSC::B3::Const32Value::lessThanConstant const):
 19 (JSC::B3::Const32Value::greaterThanConstant const):
 20 (JSC::B3::Const32Value::lessEqualConstant const):
 21 (JSC::B3::Const32Value::greaterEqualConstant const):
 22 (JSC::B3::Const32Value::aboveConstant const):
 23 (JSC::B3::Const32Value::belowConstant const):
 24 (JSC::B3::Const32Value::aboveEqualConstant const):
 25 (JSC::B3::Const32Value::belowEqualConstant const):
 26 * b3/B3Const64Value.cpp:
 27 (JSC::B3::Const64Value::lessThanConstant const):
 28 (JSC::B3::Const64Value::greaterThanConstant const):
 29 (JSC::B3::Const64Value::lessEqualConstant const):
 30 (JSC::B3::Const64Value::greaterEqualConstant const):
 31 (JSC::B3::Const64Value::aboveConstant const):
 32 (JSC::B3::Const64Value::belowConstant const):
 33 (JSC::B3::Const64Value::aboveEqualConstant const):
 34 (JSC::B3::Const64Value::belowEqualConstant const):
 35 * b3/B3ReduceStrength.cpp:
 36 * b3/testb3.cpp:
 37 (JSC::B3::int64Operands):
 38 (JSC::B3::int32Operands):
 39
1402018-03-10 Yusuke Suzuki <utatane.tea@gmail.com>
241
342 [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 CanonicalizedComparison comparison = canonicalizeComparison(m_value);
16771677 TriState result = MixedTriState;
1678  switch (value->opcode()) {
 1678 switch (comparison.opcode) {
16791679 case LessThan:
1680  result = value->child(1)->greaterThanConstant(value->child(0));
 1680 result = comparison.operands[1]->greaterThanConstant(comparison.operands[0]);
16811681 break;
16821682 case GreaterThan:
1683  result = value->child(1)->lessThanConstant(value->child(0));
 1683 result = comparison.operands[1]->lessThanConstant(comparison.operands[0]);
16841684 break;
16851685 case LessEqual:
1686  result = value->child(1)->greaterEqualConstant(value->child(0));
 1686 result = comparison.operands[1]->greaterEqualConstant(comparison.operands[0]);
16871687 break;
16881688 case GreaterEqual:
1689  result = value->child(1)->lessEqualConstant(value->child(0));
 1689 result = comparison.operands[1]->lessEqualConstant(comparison.operands[0]);
16901690 break;
16911691 case Above:
1692  result = value->child(1)->belowConstant(value->child(0));
 1692 result = comparison.operands[1]->belowConstant(comparison.operands[0]);
16931693 break;
16941694 case Below:
1695  result = value->child(1)->aboveConstant(value->child(0));
 1695 result = comparison.operands[1]->aboveConstant(comparison.operands[0]);
16961696 break;
16971697 case AboveEqual:
1698  result = value->child(1)->belowEqualConstant(value->child(0));
 1698 result = comparison.operands[1]->belowEqualConstant(comparison.operands[0]);
16991699 break;
17001700 case BelowEqual:
1701  result = value->child(1)->aboveEqualConstant(value->child(0));
 1701 result = comparison.operands[1]->aboveEqualConstant(comparison.operands[0]);
17021702 break;
17031703 default:
17041704 RELEASE_ASSERT_NOT_REACHED();
17051705 break;
17061706 }
17071707
1708  if (auto* constant = m_proc.addBoolConstant(value->origin(), result)) {
 1708 if (auto* constant = m_proc.addBoolConstant(m_value->origin(), result)) {
17091709 replaceWithNewValue(constant);
17101710 break;
17111711 }
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);
 1712 if (comparison.opcode != m_value->opcode()) {
 1713 replaceWithNew<Value>(comparison.opcode, m_value->origin(), comparison.operands[0], comparison.operands[1]);
 1714 break;
 1715 }
17161716 break;
17171717 }
17181718

@@class ReduceStrength {
21662166 }
21672167 }
21682168
2169  Value* newComparisonVaueIfNecessary()
 2169 struct CanonicalizedComparison {
 2170 Opcode opcode;
 2171 Value* operands[2];
 2172 };
 2173 static CanonicalizedComparison canonicalizeComparison(Value* value)
21702174 {
21712175 auto flip = [] (Opcode opcode) {
21722176 switch (opcode) {

@@class ReduceStrength {
21902194 return opcode;
21912195 }
21922196 };
2193  if (shouldSwapBinaryOperands(m_value)) {
2194  m_changed = true;
2195  return m_proc.add<Value>(flip(m_value->opcode()), m_value->origin(), m_value->child(1), m_value->child(0));
2196  }
2197  return m_value;
 2197 if (shouldSwapBinaryOperands(value))
 2198 return { flip(value->opcode()), value->child(1), value->child(0) };
 2199 return { value->opcode(), value->child(0), value->child(1) };
21982200 }
21992201
22002202 // 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}