Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (281586 => 281587)
--- trunk/Source/_javascript_Core/ChangeLog 2021-08-25 21:18:16 UTC (rev 281586)
+++ trunk/Source/_javascript_Core/ChangeLog 2021-08-25 21:19:31 UTC (rev 281587)
@@ -1,3 +1,77 @@
+2021-08-25 Yijia Huang <[email protected]>
+
+ [ARM64] Fix pre-index address mode
+ https://bugs.webkit.org/show_bug.cgi?id=229175
+
+ Reviewed by Saam Barati.
+
+ This patch fixes the canonicalization phase for pre/post-increment address mode
+ due to the potential bugs commented on in the previous patch
+ https://bugs.webkit.org/show_bug.cgi?id=228538. And this patch removed the
+ temporary fix in https://bugs.webkit.org/show_bug.cgi?id=229211.
+
+ Previously, the pre-index address mode for Load instruction convert the pattern
+ to the canonical form like this:
+
+ address = Add(base, offset) address = Add(base, offset)
+ ... --> newMemory = Load(base, offset)
+ ... ...
+ memory = Load(base, offset) memory = Identity(newMemory)
+
+ which is wrong. Assume "..." contains a store to a memory location that aliases for address:
+
+ address = Add(base, offset) address = Add(base, offset)
+ ... --> newMemory = Load(base, offset)
+ ... ...
+ Store(value1, address) Store(value1, address)
+ memory = Load(base, offset) memory = Identity(newMemory)
+
+ The loaded value should always be value1 which is not true after the conversion.
+ So, moving the load above the store is semantically incorrect because it's not identical to
+ the behavior of the original program. In this case, maybe we should apply alias analysis to
+ detect the violations of reference updating.
+
+ To solve this problem, we moves the address value to just before the memory value instead of
+ moving memory value upward.
+
+ Convert Pre-Index Load Pattern to the Canonical Form:
+
+ address = Add(base, offset) address = Nop
+ ... ...
+ ... newAddress = Add(base, offset)
+ memory = Load(base, offset) --> memory = Load(base, offset)
+ ... ...
+ parent = B3Opcode(address, ...) parent = B3Opcode(newAddress, ...)
+
+ Convert Pre-Index Store Pattern to the Canonical Form:
+
+ address = Add(base, offset) address = Nop
+ ... ...
+ ... newAddress = Add(base, offset)
+ memory = Store(value1, base, offset) --> memory = Store(value1, base, offset)
+ ... ...
+ parent = B3Opcode(address, ...) parent = B3Opcode(newAddress, ...)
+
+ To move the address value downward, we need to make sure that no use reference of address between
+ the address and memory values.
+
+ * b3/B3CanonicalizePrePostIncrements.cpp:
+ (JSC::B3::canonicalizePrePostIncrements):
+ * b3/B3Generate.cpp:
+ (JSC::B3::generateToAir):
+ * b3/B3ValueKey.h:
+ * b3/B3ValueKeyInlines.h:
+ (JSC::B3::ValueKey::ValueKey):
+ * b3/testb3.h:
+ * b3/testb3_3.cpp:
+ (testLoadWithStorePreIndex32):
+ (testStorePreIndex32):
+ (testStorePreIndex64):
+ (testStorePostIndex32):
+ (testStorePostIndex64):
+ (addShrTests):
+ * runtime/OptionsList.h:
+
2021-08-25 Xan Lopez <[email protected]>
[JSC] Infinite loop in for...in after r280760
Modified: trunk/Source/_javascript_Core/b3/B3CanonicalizePrePostIncrements.cpp (281586 => 281587)
--- trunk/Source/_javascript_Core/b3/B3CanonicalizePrePostIncrements.cpp 2021-08-25 21:18:16 UTC (rev 281586)
+++ trunk/Source/_javascript_Core/b3/B3CanonicalizePrePostIncrements.cpp 2021-08-25 21:19:31 UTC (rev 281587)
@@ -52,69 +52,57 @@
unsigned index { 0 };
InsertionSet insertionSet { proc };
- BlockInsertionSet blockInsertionSet { proc };
Dominators& dominators = proc.dominators();
BackwardsDominators& backwardsDominators = proc.backwardsDominators();
- IndexSet<Value*> ignoredValues;
- HashMap<Value*, Vector<MemoryValue*>> baseToLoads;
- HashMap<MemoryValue*, Value*> preIndexLoadCandidates;
- HashMap<MemoryValue*, Value*> postIndexLoadCandidates;
+ IndexSet<Value*> handledValues;
+ HashMap<Value*, unsigned> memoryToIndex;
+ HashMap<Value*, Vector<Value*>> addUses;
+ HashMap<Value*, Vector<MemoryValue*>> baseToMemories;
HashMap<ValueKey, Vector<Value*>> baseOffsetToAddresses;
+ HashMap<MemoryValue*, Vector<Value*>> preIndexCandidates;
+ HashMap<MemoryValue*, Vector<Value*>> postIndexCandidates;
+ HashMap<BasicBlock*, HashSet<MemoryValue*>> blockToPrePostIndexCandidates;
- HashMap<Value*, Vector<MemoryValue*>> baseToStores;
- HashMap<MemoryValue*, Value*> postIndexStoreCandidates;
-
- auto tryAddPrePostIndexCandidate = [&] (Value* value) {
+ // Strength Reduction will leave the IR in the form we're matching now.
+ // It'll take an add(x, constant) that's an address and move the offset
+ // into the load itself, and that's why we can match this redundancy.
+ auto tryAddCandidates = [&] (Value* value) {
switch (value->opcode()) {
- case Load: {
- // Pre-Index Pattern:
- // address = Add(base, offset)
- // ...
- // memory = Load(base, offset)
- // Post-Index Pattern:
- // memory = Load(base, 0)
- // ...
- // address = Add(base, offset)
- auto tryAddpreIndexLoadCandidates = [&] () {
- MemoryValue* memory = value->as<MemoryValue>();
- if (memory->type() != Int32 && memory->type() != Int64)
- return;
- if (memory->offset()) {
- if (!Arg::isValidIncrementIndexForm(memory->offset()))
- return;
- ValueKey baseOffsetkey = ValueKey(memory->child(0), static_cast<int64_t>(memory->offset()));
- if (!baseOffsetToAddresses.contains(baseOffsetkey))
- return;
- for (Value* address : baseOffsetToAddresses.get(baseOffsetkey))
- preIndexLoadCandidates.add(memory, address);
- } else
- baseToLoads.add(memory->child(0), Vector<MemoryValue*>()).iterator->value.append(memory);
- };
-
- tryAddpreIndexLoadCandidates();
- break;
- }
-
+ case Load:
case Store: {
- // Pre-Index Pattern:
- // address = Add(base, offset)
- // memory = Store(value, base, offset)
- // Post-Index Pattern:
- // memory = Store(value, base, 0)
- // ...
- // address = Add(base, offset)
- auto tryUpdateBaseToStores = [&] () {
- MemoryValue* memory = value->as<MemoryValue>();
- if (memory->child(0)->type() != Int32 && memory->child(0)->type() != Int64)
- return;
- if (memory->child(0)->hasInt() || memory->offset())
- return;
- baseToStores.add(memory->child(1), Vector<MemoryValue*>()).iterator->value.append(memory);
- };
-
- tryUpdateBaseToStores();
+ MemoryValue* memory = value->as<MemoryValue>();
+ Value* type = value->opcode() == Load ? memory : memory->child(0);
+ if (type->type() != Int32 && type->type() != Int64)
+ break;
+ if (memory->offset()) {
+ // Pre-Index Load/Store Pattern:
+ // address = Add(base, offset)
+ // ...
+ // memory = MemoryValue(base, offset)
+ ValueKey baseOffsetKey = ValueKey(memory->lastChild(), memory->offset());
+ auto iter = baseOffsetToAddresses.find(baseOffsetKey);
+ if (iter == baseOffsetToAddresses.end())
+ break;
+ for (Value* address : iter->value) {
+ // The goal is to move the Add to this Load/Store. We only move the Add to this Memory value
+ // if we guarantee it dominates all uses. If there are already other uses of the Add, it guarantees
+ // this Memory value doesn't dominate those uses. This is because we're visiting the program in pre-order
+ // traversal, so we visit this Memory value before all the things it dominates. So if the Add has other
+ // users, we must not dominate those users. Therefore, this MemoryValue won't be a candidate.
+ auto addUsesIter = addUses.find(address);
+ if (addUsesIter != addUses.end() && addUsesIter->value.size() > 0)
+ continue;
+ // double check offsets to avoid ValueKey collisions
+ if (memory->offset() != static_cast<Value::OffsetType>(address->child(1)->asIntPtr()))
+ continue;
+ preIndexCandidates.add(memory, Vector<Value*>()).iterator->value.append(address);
+ blockToPrePostIndexCandidates.add(memory->owner, HashSet<MemoryValue*>()).iterator->value.add(memory);
+ }
+ } else
+ baseToMemories.add(memory->lastChild(), Vector<MemoryValue*>()).iterator->value.append(memory);
+ memoryToIndex.add(memory, index);
break;
}
@@ -122,27 +110,29 @@
Value* left = value->child(0);
Value* right = value->child(1);
- auto tryAddpostIndexCandidates = [&] () {
- if (!right->hasIntPtr() || value->type() != Int64)
- return;
- intptr_t offset = right->asIntPtr();
- Value::OffsetType smallOffset = static_cast<Value::OffsetType>(offset);
- if (smallOffset != offset || !Arg::isValidIncrementIndexForm(smallOffset))
- return;
- // so far this Add value is a valid address candidate for both prefix and postfix pattern
- ValueKey baseOffsetkey = ValueKey(left, static_cast<int64_t>(smallOffset));
- baseOffsetToAddresses.add(baseOffsetkey, Vector<Value*>()).iterator->value.append(value);
- if (baseToLoads.contains(left)) {
- for (MemoryValue* memory : baseToLoads.get(left))
- postIndexLoadCandidates.add(memory, value);
- }
- if (baseToStores.contains(left)) {
- for (MemoryValue* memory : baseToStores.get(left))
- postIndexStoreCandidates.add(memory, value);
- }
- };
+ if (!right->hasIntPtr() || value->type() != Int64)
+ break;
+ intptr_t offset = right->asIntPtr();
+ Value::OffsetType smallOffset = static_cast<Value::OffsetType>(offset);
+ if (smallOffset != offset || !Arg::isValidIncrementIndexForm(smallOffset))
+ break;
- tryAddpostIndexCandidates();
+ // so far this Add value is a valid address candidate for both prefix and postfix pattern
+ addUses.add(value, Vector<Value*>());
+ ValueKey baseOffsetKey = ValueKey(left, smallOffset);
+ baseOffsetToAddresses.add(baseOffsetKey, Vector<Value*>()).iterator->value.append(value);
+
+ // Post-Index Load/Store Pattern:
+ // memory = MemoryValue(base, 0)
+ // ...
+ // address = Add(base, offset)
+ auto iter = baseToMemories.find(left);
+ if (iter == baseToMemories.end())
+ break;
+ for (MemoryValue* memory : iter->value) {
+ postIndexCandidates.add(memory, Vector<Value*>()).iterator->value.append(value);
+ blockToPrePostIndexCandidates.add(memory->owner, HashSet<MemoryValue*>()).iterator->value.add(memory);
+ }
break;
}
@@ -149,11 +139,17 @@
default:
break;
}
+
+ for (Value* child : value->children()) {
+ auto iter = addUses.find(child);
+ if (iter != addUses.end())
+ iter->value.append(value);
+ }
};
for (BasicBlock* basicBlock : proc.blocksInPreOrder()) {
for (index = 0; index < basicBlock->size(); ++index)
- tryAddPrePostIndexCandidate(basicBlock->at(index));
+ tryAddCandidates(basicBlock->at(index));
}
auto controlEquivalent = [&] (Value* v1, Value* v2) -> bool {
@@ -161,68 +157,75 @@
|| (dominators.dominates(v2->owner, v1->owner) && backwardsDominators.dominates(v1->owner, v2->owner));
};
- // This search is expensive. However, due to the greedy pattern
- // matching, no better method can be proposed at present.
- auto valueIndexInBasicBlock = [&] (Value* value) -> unsigned {
- unsigned index = 0;
- BasicBlock* block = value->owner;
- for (index = 0; index < block->size(); ++index) {
- if (block->at(index) == value)
- return index;
- }
- return index;
- };
+ for (const auto& pair : blockToPrePostIndexCandidates) {
+ BasicBlock* basicBlock = pair.key;
+ for (MemoryValue* memory : pair.value) {
+ if (handledValues.contains(memory))
+ continue;
- for (auto pair : preIndexLoadCandidates) {
- MemoryValue* memory = pair.key;
- Value* address = pair.value;
- if (ignoredValues.contains(memory) || ignoredValues.contains(address) || !controlEquivalent(memory, address))
- continue;
- // address = Add(base, offset) address = Add(base, offset)
- // ... --> newMemory = Load(base, offset)
- // ... ...
- // memory = Load(base, offset) memory = Identity(newMemory)
- unsigned insertionIndex = valueIndexInBasicBlock(address) + 1;
- MemoryValue* newMemory = insertionSet.insert<MemoryValue>(insertionIndex, Load, memory->type(), address->origin(), memory->lastChild());
- newMemory->setOffset(memory->offset());
- memory->replaceWithIdentity(newMemory);
- insertionSet.execute(address->owner);
+ // Convert Pre-Index Load/Store Pattern to the Canonical Form:
+ // address = Add(base, offset) address = Nop
+ // ... ...
+ // ... newAddress = Add(base, offset)
+ // memory = MemoryValue(base, offset) --> memory = MemoryValue(base, offset)
+ // ... ...
+ // parent = B3Opcode(address, ...) parent = B3Opcode(newAddress, ...)
+ for (Value* address : preIndexCandidates.get(memory)) {
+ if (handledValues.contains(address) || !controlEquivalent(memory, address))
+ continue;
- ignoredValues.add(memory);
- ignoredValues.add(address);
- }
+ auto dominatesAllAddUses = [&] () -> bool {
+ auto iter = addUses.find(address);
+ ASSERT(iter != addUses.end() && iter->value.size());
+ for (Value* parent : iter->value) {
+ if (!dominators.dominates(memory->owner, parent->owner))
+ return false;
+ }
+ return true;
+ };
- auto detectPostIndex = [&] (const HashMap<MemoryValue*, Value*>& candidates) {
- for (auto pair : candidates) {
- MemoryValue* memory = pair.key;
- Value* address = pair.value;
- if (ignoredValues.contains(memory) || ignoredValues.contains(address) || !controlEquivalent(memory, address))
- continue;
+ if (!dominatesAllAddUses())
+ continue;
- unsigned insertionIndex = valueIndexInBasicBlock(memory);
- Value* newOffset = insertionSet.insert<Const64Value>(insertionIndex, memory->origin(), address->child(1)->asInt());
- Value* newAddress = insertionSet.insert<Value>(insertionIndex, Add, memory->origin(), address->child(0), newOffset);
- address->replaceWithIdentity(newAddress);
- insertionSet.execute(memory->owner);
+ unsigned insertionIndex = memoryToIndex.get(memory);
+ Value* newAddress = insertionSet.insert<Value>(insertionIndex, Add, memory->origin(), address->child(0), address->child(1));
+ for (Value* parent : addUses.get(address)) {
+ for (unsigned i = 0; i < parent->numChildren(); ++i) {
+ Value*& child = parent->child(i);
+ if (child == address)
+ child = newAddress;
+ }
+ }
+ address->replaceWithNopIgnoringType();
- ignoredValues.add(memory);
- ignoredValues.add(address);
+ handledValues.add(memory);
+ handledValues.add(address);
+ }
+
+ // Convert Post-Index Load/Store Pattern to the Canonical Form:
+ // ... newOffset = Constant
+ // ... newAddress = Add(base, newOffset)
+ // memory = MemoryValue(base, 0) memory = MemoryValue(base, 0)
+ // ... --> ...
+ // address = Add(base, offset) address = Identity(newAddress)
+ for (Value* address : postIndexCandidates.get(memory)) {
+ if (handledValues.contains(address) || !controlEquivalent(memory, address))
+ continue;
+
+ unsigned insertionIndex = memoryToIndex.get(memory);
+ Value* newOffset = insertionSet.insert<Const64Value>(insertionIndex, memory->origin(), address->child(1)->asInt());
+ Value* newAddress = insertionSet.insert<Value>(insertionIndex, Add, memory->origin(), address->child(0), newOffset);
+ address->replaceWithIdentity(newAddress);
+
+ handledValues.add(memory);
+ handledValues.add(address);
+ }
}
- };
+ // After this executes, memoryToIndex no longer contains up to date information for this block.
+ // But that's ok because we never touch this block again.
+ insertionSet.execute(basicBlock);
+ }
- // ... newOffset = Constant
- // ... newAddress = Add(base, newOffset)
- // memory = Load(base, 0) memory = Load(base, 0)
- // ... --> ...
- // address = Add(base, offset) address = Identity(newAddress)
- detectPostIndex(postIndexLoadCandidates);
-
- // ... newOffset = Constant
- // ... newAddress = Add(base, newOffset)
- // memory = Store(value, base, 0) memory = Store(value, base, 0)
- // ... --> ...
- // address = Add(base, offset) address = Identity(newAddress)
- detectPostIndex(postIndexStoreCandidates);
return true;
}
Modified: trunk/Source/_javascript_Core/b3/B3Generate.cpp (281586 => 281587)
--- trunk/Source/_javascript_Core/b3/B3Generate.cpp 2021-08-25 21:18:16 UTC (rev 281586)
+++ trunk/Source/_javascript_Core/b3/B3Generate.cpp 2021-08-25 21:19:31 UTC (rev 281587)
@@ -118,7 +118,7 @@
lowerMacrosAfterOptimizations(procedure);
legalizeMemoryOffsets(procedure);
moveConstants(procedure);
- if (Options::useB3CanonicalizePrePostIncrements() && procedure.optLevel() >= 2)
+ if (procedure.optLevel() >= 2)
canonicalizePrePostIncrements(procedure);
eliminateDeadCode(procedure);
Modified: trunk/Source/_javascript_Core/b3/B3ValueKey.h (281586 => 281587)
--- trunk/Source/_javascript_Core/b3/B3ValueKey.h 2021-08-25 21:18:16 UTC (rev 281586)
+++ trunk/Source/_javascript_Core/b3/B3ValueKey.h 2021-08-25 21:19:31 UTC (rev 281587)
@@ -56,7 +56,7 @@
{
}
- ValueKey(Value* child, int64_t value);
+ ValueKey(Value* child, int32_t offset);
ValueKey(Kind, Type, Value* child);
Modified: trunk/Source/_javascript_Core/b3/B3ValueKeyInlines.h (281586 => 281587)
--- trunk/Source/_javascript_Core/b3/B3ValueKeyInlines.h 2021-08-25 21:18:16 UTC (rev 281586)
+++ trunk/Source/_javascript_Core/b3/B3ValueKeyInlines.h 2021-08-25 21:19:31 UTC (rev 281587)
@@ -33,12 +33,14 @@
namespace JSC { namespace B3 {
-inline ValueKey::ValueKey(Value* child, int64_t value)
+inline ValueKey::ValueKey(Value* child, int32_t offset)
{
m_kind = Oops;
m_type = Void;
- u.indices[0] = child->index();
- u.value = value;
+ // The observation is that when both child->index() and offset are 0's,
+ // HashMap would not accept the ValueKey.
+ u.indices[0] = child->index() + 1;
+ u.indices[1] = offset + 1;
}
inline ValueKey::ValueKey(Kind kind, Type type, Value* child)
Modified: trunk/Source/_javascript_Core/b3/testb3.h (281586 => 281587)
--- trunk/Source/_javascript_Core/b3/testb3.h 2021-08-25 21:18:16 UTC (rev 281586)
+++ trunk/Source/_javascript_Core/b3/testb3.h 2021-08-25 21:19:31 UTC (rev 281587)
@@ -1164,6 +1164,7 @@
bool shouldRun(const char* filter, const char* testName);
void testLoadPreIndex32();
+void testLoadWithStorePreIndex32();
void testLoadPreIndex64();
void testLoadPostIndex32();
void testLoadPostIndex64();
Modified: trunk/Source/_javascript_Core/b3/testb3_3.cpp (281586 => 281587)
--- trunk/Source/_javascript_Core/b3/testb3_3.cpp 2021-08-25 21:18:16 UTC (rev 281586)
+++ trunk/Source/_javascript_Core/b3/testb3_3.cpp 2021-08-25 21:19:31 UTC (rev 281587)
@@ -102,6 +102,83 @@
CHECK_EQ(invoke<int32_t>(*code, bitwise_cast<intptr_t>(ptr)), test());
}
+void testLoadWithStorePreIndex32()
+{
+ if (Options::defaultB3OptLevel() < 2)
+ return;
+
+ int32_t nums[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ int32_t* ptr = nums;
+
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ BasicBlock* loopTest = proc.addBlock();
+ BasicBlock* loopBody = proc.addBlock();
+ BasicBlock* done = proc.addBlock();
+
+ Variable* r = proc.addVariable(Int32);
+ Variable* p = proc.addVariable(Int64);
+
+ // ---------------------- Root_Block
+ // r1 = 0
+ // Upsilon(r1, ^r2)
+ // p1 = addr
+ // Upsilon(p1, ^p2)
+ Value* r1 = root->appendIntConstant(proc, Origin(), Int32, 0);
+ root->appendNew<VariableValue>(proc, B3::Set, Origin(), r, r1);
+ Value* p1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+ root->appendNew<VariableValue>(proc, B3::Set, Origin(), p, p1);
+ root->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loopTest));
+
+ // ---------------------- Loop_Test_Block
+ // loop:
+ // p2 = Phi()
+ // r2 = Phi()
+ // if r2 >= 10 goto done
+ Value* r2 = loopTest->appendNew<VariableValue>(proc, B3::Get, Origin(), r);
+ Value* p2 = loopTest->appendNew<VariableValue>(proc, B3::Get, Origin(), p);
+ Value* cond = loopTest->appendNew<Value>(proc, AboveEqual, Origin(), r2, loopTest->appendNew<Const32Value>(proc, Origin(), 10));
+ loopTest->appendNewControlValue(proc, Branch, Origin(), cond, FrequentedBlock(done), FrequentedBlock(loopBody));
+
+ // ---------------------- Loop_Body_Block
+ // p3 = p2 + 1
+ // Upsilon(p3, ^p2)
+ // p3' = &p3
+ // store(5, p3')
+ // r3 = r2 + load(p3)
+ // Upsilon(r3, ^r2)
+ // goto loop
+ Value* p3 = loopBody->appendNew<Value>(proc, Add, Origin(), p2, loopBody->appendNew<Const64Value>(proc, Origin(), 4));
+ loopBody->appendNew<VariableValue>(proc, B3::Set, Origin(), p, p3);
+ Value* p3Prime = loopBody->appendNew<Value>(proc, Opaque, Origin(), p3);
+ loopBody->appendNew<MemoryValue>(proc, Store, Origin(), loopBody->appendNew<Const32Value>(proc, Origin(), 5), p3Prime);
+ Value* r3 = loopBody->appendNew<Value>(proc, Add, Origin(), r2, loopBody->appendNew<MemoryValue>(proc, Load, Int32, Origin(), p3));
+ loopBody->appendNew<VariableValue>(proc, B3::Set, Origin(), r, r3);
+ loopBody->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loopTest));
+
+ // ---------------------- Done_Block
+ // done:
+ // return r2
+ done->appendNewControlValue(proc, Return, Origin(), r2);
+
+ proc.resetReachability();
+ validate(proc);
+ fixSSA(proc);
+
+ auto code = compileProc(proc);
+
+ auto test = [&] () -> int32_t {
+ int32_t r = 0;
+ while (r < 10) {
+ *++ptr = 5;
+ r += *ptr;
+ }
+ return r;
+ };
+
+ CHECK_EQ(invoke<int32_t>(*code, bitwise_cast<intptr_t>(ptr)), test());
+}
+
void testLoadPreIndex64()
{
if (Options::defaultB3OptLevel() < 2)
@@ -344,6 +421,7 @@
auto code = compileProc(proc);
if (isARM64())
checkUsesInstruction(*code, "#4]!");
+
intptr_t res = invoke<intptr_t>(*code, bitwise_cast<intptr_t>(ptr), 4);
ptr = bitwise_cast<int32_t*>(res);
CHECK_EQ(nums[2], *ptr);
@@ -368,6 +446,9 @@
root->appendNewControlValue(proc, Return, Origin(), preIncrement);
auto code = compileProc(proc);
+ if (isARM64())
+ checkUsesInstruction(*code, "#8]!");
+
intptr_t res = invoke<intptr_t>(*code, bitwise_cast<intptr_t>(ptr), 4);
ptr = bitwise_cast<int64_t*>(res);
CHECK_EQ(nums[2], *ptr);
@@ -396,6 +477,7 @@
auto code = compileProc(proc);
if (isARM64())
checkUsesInstruction(*code, "], #4");
+
intptr_t res = invoke<intptr_t>(*code, bitwise_cast<intptr_t>(ptr), 4);
ptr = bitwise_cast<int32_t*>(res);
CHECK_EQ(nums[1], 4);
@@ -423,6 +505,7 @@
auto code = compileProc(proc);
if (isARM64())
checkUsesInstruction(*code, "], #8");
+
intptr_t res = invoke<intptr_t>(*code, bitwise_cast<intptr_t>(ptr), 4);
ptr = bitwise_cast<int64_t*>(res);
CHECK_EQ(nums[1], 4);
@@ -4097,17 +4180,15 @@
RUN(testZShrArgImm32(0xffffffff, 1));
RUN(testZShrArgImm32(0xffffffff, 63));
- if (Options::useB3CanonicalizePrePostIncrements()) {
- RUN(testLoadPreIndex32());
- RUN(testLoadPreIndex64());
- RUN(testLoadPostIndex32());
- RUN(testLoadPostIndex64());
+ RUN(testLoadPreIndex32());
+ RUN(testLoadPreIndex64());
+ RUN(testLoadPostIndex32());
+ RUN(testLoadPostIndex64());
- RUN(testStorePreIndex32());
- RUN(testStorePreIndex64());
- RUN(testStorePostIndex32());
- RUN(testStorePostIndex64());
- }
+ RUN(testStorePreIndex32());
+ RUN(testStorePreIndex64());
+ RUN(testStorePostIndex32());
+ RUN(testStorePostIndex64());
}
#endif // ENABLE(B3_JIT)
Modified: trunk/Source/_javascript_Core/runtime/OptionsList.h (281586 => 281587)
--- trunk/Source/_javascript_Core/runtime/OptionsList.h 2021-08-25 21:18:16 UTC (rev 281586)
+++ trunk/Source/_javascript_Core/runtime/OptionsList.h 2021-08-25 21:19:31 UTC (rev 281587)
@@ -437,7 +437,6 @@
v(Unsigned, maxB3TailDupBlockSize, 3, Normal, nullptr) \
v(Unsigned, maxB3TailDupBlockSuccessors, 3, Normal, nullptr) \
v(Bool, useB3HoistLoopInvariantValues, false, Normal, nullptr) \
- v(Bool, useB3CanonicalizePrePostIncrements, false, Normal, nullptr) \
\
v(Bool, useDollarVM, false, Restricted, "installs the $vm debugging tool in global objects") \
v(OptionString, functionOverrides, nullptr, Restricted, "file with debugging overrides for function bodies") \