Log Message
mandreel should run just as fast in FTL B3 as FTL LLVM https://bugs.webkit.org/show_bug.cgi?id=153394
Reviewed by Gavin Barraclough. This fixes two performance bugs and one disassembler bug. - B3 now turns Branches into Jumps when they are dominated by a Check on the same condition. This is like the opposite of foldPathConstants() was doing. - Air now supports adding to 8-bit or 16-bit memory locations on x86. B3 now knows how to lower Store8(Add(Load8Z(...))) and various other things to these new instructions. - Disassembler now knows to print out the instruction's width, whenever it has one. Previously, we'd print movb, movw, movl, and movq as "mov", which is unhelpful if you're storing an immediate, for example. This adds a bunch of tests for the new instruction forms. This is a big speed-up on mandreel. It makes us just as fast as LLVM on that benchmark. * assembler/MacroAssemblerX86Common.h: (JSC::MacroAssemblerX86Common::add32): (JSC::MacroAssemblerX86Common::add8): (JSC::MacroAssemblerX86Common::add16): (JSC::MacroAssemblerX86Common::add32AndSetFlags): (JSC::MacroAssemblerX86Common::clz32AfterBsr): * assembler/X86Assembler.h: (JSC::X86Assembler::addl_rm): (JSC::X86Assembler::addb_rm): (JSC::X86Assembler::addw_rm): (JSC::X86Assembler::addl_ir): (JSC::X86Assembler::addl_im): (JSC::X86Assembler::addb_im): (JSC::X86Assembler::addw_im): (JSC::X86Assembler::addq_rr): * b3/B3LowerToAir.cpp: (JSC::B3::Air::LowerToAir::addr): (JSC::B3::Air::LowerToAir::loadPromiseAnyOpcode): (JSC::B3::Air::LowerToAir::loadPromise): (JSC::B3::Air::LowerToAir::tryAppendStoreBinOp): (JSC::B3::Air::LowerToAir::lower): * b3/B3PureCSE.cpp: (JSC::B3::PureCSE::clear): (JSC::B3::PureCSE::findMatch): (JSC::B3::PureCSE::process): * b3/B3PureCSE.h: * b3/B3ReduceStrength.cpp: * b3/air/AirOpcode.opcodes: * b3/testb3.cpp: (JSC::B3::testNegPtr): (JSC::B3::testStoreAddLoad32): (JSC::B3::testStoreAddLoadImm32): (JSC::B3::testStoreAddLoad8): (JSC::B3::testStoreAddLoadImm8): (JSC::B3::testStoreAddLoad16): (JSC::B3::testStoreAddLoadImm16): (JSC::B3::testStoreAddLoad64): (JSC::B3::testStoreAddLoadImm64): (JSC::B3::testStoreAddLoad32Index): (JSC::B3::testStoreAddLoadImm32Index): (JSC::B3::testStoreAddLoad8Index): (JSC::B3::testStoreAddLoadImm8Index): (JSC::B3::testStoreAddLoad16Index): (JSC::B3::testStoreAddLoadImm16Index): (JSC::B3::testStoreAddLoad64Index): (JSC::B3::testStoreAddLoadImm64Index): (JSC::B3::testStoreSubLoad): (JSC::B3::run): (JSC::B3::testStoreAddLoad): Deleted. * disassembler/udis86/udis86_syn-att.c: (ud_translate_att):
Modified Paths
- trunk/Source/_javascript_Core/ChangeLog
- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h
- trunk/Source/_javascript_Core/assembler/X86Assembler.h
- trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp
- trunk/Source/_javascript_Core/b3/B3PureCSE.cpp
- trunk/Source/_javascript_Core/b3/B3PureCSE.h
- trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp
- trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes
- trunk/Source/_javascript_Core/b3/testb3.cpp
- trunk/Source/_javascript_Core/disassembler/udis86/udis86_syn-att.c
Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (195548 => 195549)
--- trunk/Source/_javascript_Core/ChangeLog 2016-01-25 20:37:44 UTC (rev 195548)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-01-25 20:47:18 UTC (rev 195549)
@@ -1,3 +1,77 @@
+2016-01-22 Filip Pizlo <[email protected]>
+
+ mandreel should run just as fast in FTL B3 as FTL LLVM
+ https://bugs.webkit.org/show_bug.cgi?id=153394
+
+ Reviewed by Gavin Barraclough.
+
+ This fixes two performance bugs and one disassembler bug.
+
+ - B3 now turns Branches into Jumps when they are dominated by a Check on the same
+ condition. This is like the opposite of foldPathConstants() was doing.
+
+ - Air now supports adding to 8-bit or 16-bit memory locations on x86. B3 now knows how to
+ lower Store8(Add(Load8Z(...))) and various other things to these new instructions.
+
+ - Disassembler now knows to print out the instruction's width, whenever it has one.
+ Previously, we'd print movb, movw, movl, and movq as "mov", which is unhelpful if
+ you're storing an immediate, for example.
+
+ This adds a bunch of tests for the new instruction forms. This is a big speed-up on
+ mandreel. It makes us just as fast as LLVM on that benchmark.
+
+ * assembler/MacroAssemblerX86Common.h:
+ (JSC::MacroAssemblerX86Common::add32):
+ (JSC::MacroAssemblerX86Common::add8):
+ (JSC::MacroAssemblerX86Common::add16):
+ (JSC::MacroAssemblerX86Common::add32AndSetFlags):
+ (JSC::MacroAssemblerX86Common::clz32AfterBsr):
+ * assembler/X86Assembler.h:
+ (JSC::X86Assembler::addl_rm):
+ (JSC::X86Assembler::addb_rm):
+ (JSC::X86Assembler::addw_rm):
+ (JSC::X86Assembler::addl_ir):
+ (JSC::X86Assembler::addl_im):
+ (JSC::X86Assembler::addb_im):
+ (JSC::X86Assembler::addw_im):
+ (JSC::X86Assembler::addq_rr):
+ * b3/B3LowerToAir.cpp:
+ (JSC::B3::Air::LowerToAir::addr):
+ (JSC::B3::Air::LowerToAir::loadPromiseAnyOpcode):
+ (JSC::B3::Air::LowerToAir::loadPromise):
+ (JSC::B3::Air::LowerToAir::tryAppendStoreBinOp):
+ (JSC::B3::Air::LowerToAir::lower):
+ * b3/B3PureCSE.cpp:
+ (JSC::B3::PureCSE::clear):
+ (JSC::B3::PureCSE::findMatch):
+ (JSC::B3::PureCSE::process):
+ * b3/B3PureCSE.h:
+ * b3/B3ReduceStrength.cpp:
+ * b3/air/AirOpcode.opcodes:
+ * b3/testb3.cpp:
+ (JSC::B3::testNegPtr):
+ (JSC::B3::testStoreAddLoad32):
+ (JSC::B3::testStoreAddLoadImm32):
+ (JSC::B3::testStoreAddLoad8):
+ (JSC::B3::testStoreAddLoadImm8):
+ (JSC::B3::testStoreAddLoad16):
+ (JSC::B3::testStoreAddLoadImm16):
+ (JSC::B3::testStoreAddLoad64):
+ (JSC::B3::testStoreAddLoadImm64):
+ (JSC::B3::testStoreAddLoad32Index):
+ (JSC::B3::testStoreAddLoadImm32Index):
+ (JSC::B3::testStoreAddLoad8Index):
+ (JSC::B3::testStoreAddLoadImm8Index):
+ (JSC::B3::testStoreAddLoad16Index):
+ (JSC::B3::testStoreAddLoadImm16Index):
+ (JSC::B3::testStoreAddLoad64Index):
+ (JSC::B3::testStoreAddLoadImm64Index):
+ (JSC::B3::testStoreSubLoad):
+ (JSC::B3::run):
+ (JSC::B3::testStoreAddLoad): Deleted.
+ * disassembler/udis86/udis86_syn-att.c:
+ (ud_translate_att):
+
2016-01-25 Alex Christensen <[email protected]>
[Win] Copy forwarding headers before building a project
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h (195548 => 195549)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h 2016-01-25 20:37:44 UTC (rev 195548)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h 2016-01-25 20:47:18 UTC (rev 195549)
@@ -129,6 +129,33 @@
add32AndSetFlags(imm, address);
}
+ void add32(TrustedImm32 imm, BaseIndex address)
+ {
+ if (!imm.m_value)
+ return;
+ add32AndSetFlags(imm, address);
+ }
+
+ void add8(TrustedImm32 imm, Address address)
+ {
+ m_assembler.addb_im(imm.m_value, address.offset, address.base);
+ }
+
+ void add8(TrustedImm32 imm, BaseIndex address)
+ {
+ m_assembler.addb_im(imm.m_value, address.offset, address.base, address.index, address.scale);
+ }
+
+ void add16(TrustedImm32 imm, Address address)
+ {
+ m_assembler.addw_im(imm.m_value, address.offset, address.base);
+ }
+
+ void add16(TrustedImm32 imm, BaseIndex address)
+ {
+ m_assembler.addw_im(imm.m_value, address.offset, address.base, address.index, address.scale);
+ }
+
void add32(TrustedImm32 imm, RegisterID dest)
{
if (!imm.m_value)
@@ -146,6 +173,31 @@
m_assembler.addl_rm(src, dest.offset, dest.base);
}
+ void add32(RegisterID src, BaseIndex dest)
+ {
+ m_assembler.addl_rm(src, dest.offset, dest.base, dest.index, dest.scale);
+ }
+
+ void add8(RegisterID src, Address dest)
+ {
+ m_assembler.addb_rm(src, dest.offset, dest.base);
+ }
+
+ void add8(RegisterID src, BaseIndex dest)
+ {
+ m_assembler.addb_rm(src, dest.offset, dest.base, dest.index, dest.scale);
+ }
+
+ void add16(RegisterID src, Address dest)
+ {
+ m_assembler.addw_rm(src, dest.offset, dest.base);
+ }
+
+ void add16(RegisterID src, BaseIndex dest)
+ {
+ m_assembler.addw_rm(src, dest.offset, dest.base, dest.index, dest.scale);
+ }
+
void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
{
if (!imm.m_value) {
@@ -2015,6 +2067,11 @@
m_assembler.addl_im(imm.m_value, address.offset, address.base);
}
+ void add32AndSetFlags(TrustedImm32 imm, BaseIndex address)
+ {
+ m_assembler.addl_im(imm.m_value, address.offset, address.base, address.index, address.scale);
+ }
+
// If lzcnt is not available, use this after BSR
// to count the leading zeros.
void clz32AfterBsr(RegisterID dst)
Modified: trunk/Source/_javascript_Core/assembler/X86Assembler.h (195548 => 195549)
--- trunk/Source/_javascript_Core/assembler/X86Assembler.h 2016-01-25 20:37:44 UTC (rev 195548)
+++ trunk/Source/_javascript_Core/assembler/X86Assembler.h 2016-01-25 20:47:18 UTC (rev 195549)
@@ -187,6 +187,7 @@
// -v: 32 or 64bit depending on the operand-size attribute.
// -z: 32bit in both 32bit and 64bit mode. Common for immediate values.
typedef enum {
+ OP_ADD_EbGb = 0x00,
OP_ADD_EvGv = 0x01,
OP_ADD_GvEv = 0x03,
OP_ADD_EAXIv = 0x05,
@@ -433,6 +434,33 @@
m_formatter.oneByteOp(OP_ADD_EvGv, src, base, offset);
}
+ void addl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
+ {
+ m_formatter.oneByteOp(OP_ADD_EvGv, src, base, index, scale, offset);
+ }
+
+ void addb_rm(RegisterID src, int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp8(OP_ADD_EbGb, src, base, offset);
+ }
+
+ void addb_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
+ {
+ m_formatter.oneByteOp8(OP_ADD_EbGb, src, base, index, scale, offset);
+ }
+
+ void addw_rm(RegisterID src, int offset, RegisterID base)
+ {
+ m_formatter.prefix(PRE_OPERAND_SIZE);
+ m_formatter.oneByteOp8(OP_ADD_EvGv, src, base, offset);
+ }
+
+ void addw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
+ {
+ m_formatter.prefix(PRE_OPERAND_SIZE);
+ m_formatter.oneByteOp8(OP_ADD_EvGv, src, base, index, scale, offset);
+ }
+
void addl_ir(int imm, RegisterID dst)
{
if (CAN_SIGN_EXTEND_8_32(imm)) {
@@ -458,6 +486,53 @@
}
}
+ void addl_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
+ {
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, base, index, scale, offset);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, base, index, scale, offset);
+ m_formatter.immediate32(imm);
+ }
+ }
+
+ void addb_im(int imm, int offset, RegisterID base)
+ {
+ m_formatter.oneByteOp8(OP_GROUP1_EbIb, GROUP1_OP_ADD, base, offset);
+ m_formatter.immediate8(imm);
+ }
+
+ void addb_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
+ {
+ m_formatter.oneByteOp8(OP_GROUP1_EbIb, GROUP1_OP_ADD, base, index, scale, offset);
+ m_formatter.immediate8(imm);
+ }
+
+ void addw_im(int imm, int offset, RegisterID base)
+ {
+ m_formatter.prefix(PRE_OPERAND_SIZE);
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp8(OP_GROUP1_EvIb, GROUP1_OP_ADD, base, offset);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp8(OP_GROUP1_EvIz, GROUP1_OP_ADD, base, offset);
+ m_formatter.immediate16(imm);
+ }
+ }
+
+ void addw_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
+ {
+ m_formatter.prefix(PRE_OPERAND_SIZE);
+ if (CAN_SIGN_EXTEND_8_32(imm)) {
+ m_formatter.oneByteOp8(OP_GROUP1_EvIb, GROUP1_OP_ADD, base, index, scale, offset);
+ m_formatter.immediate8(imm);
+ } else {
+ m_formatter.oneByteOp8(OP_GROUP1_EvIz, GROUP1_OP_ADD, base, index, scale, offset);
+ m_formatter.immediate16(imm);
+ }
+ }
+
#if CPU(X86_64)
void addq_rr(RegisterID src, RegisterID dst)
{
@@ -1564,6 +1639,9 @@
void movw_rm(RegisterID src, int offset, RegisterID base)
{
m_formatter.prefix(PRE_OPERAND_SIZE);
+
+ // FIXME: We often use oneByteOp8 for 16-bit operations. It's not clear that this is
+ // necessary. https://bugs.webkit.org/show_bug.cgi?id=153433
m_formatter.oneByteOp8(OP_MOV_EvGv, src, base, offset);
}
Modified: trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp (195548 => 195549)
--- trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp 2016-01-25 20:37:44 UTC (rev 195548)
+++ trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp 2016-01-25 20:47:18 UTC (rev 195549)
@@ -458,10 +458,8 @@
return result;
}
- ArgPromise loadPromise(Value* loadValue, B3::Opcode loadOpcode)
+ ArgPromise loadPromiseAnyOpcode(Value* loadValue)
{
- if (loadValue->opcode() != loadOpcode)
- return Arg();
if (!canBeInternal(loadValue))
return Arg();
if (crossesInterference(loadValue))
@@ -469,6 +467,13 @@
return ArgPromise(addr(loadValue), loadValue);
}
+ ArgPromise loadPromise(Value* loadValue, B3::Opcode loadOpcode)
+ {
+ if (loadValue->opcode() != loadOpcode)
+ return Arg();
+ return loadPromiseAnyOpcode(loadValue);
+ }
+
ArgPromise loadPromise(Value* loadValue)
{
return loadPromise(loadValue, Load);
@@ -744,14 +749,34 @@
Arg storeAddr = addr(m_value);
ASSERT(storeAddr);
+ auto getLoadPromise = [&] (Value* load) -> ArgPromise {
+ switch (m_value->opcode()) {
+ case B3::Store:
+ if (load->opcode() != B3::Load)
+ return ArgPromise();
+ break;
+ case B3::Store8:
+ if (load->opcode() != B3::Load8Z && load->opcode() != B3::Load8S)
+ return ArgPromise();
+ break;
+ case B3::Store16:
+ if (load->opcode() != B3::Load16Z && load->opcode() != B3::Load16S)
+ return ArgPromise();
+ break;
+ default:
+ return ArgPromise();
+ }
+ return loadPromiseAnyOpcode(load);
+ };
+
ArgPromise loadPromise;
Value* otherValue = nullptr;
-
- loadPromise = this->loadPromise(left);
+
+ loadPromise = getLoadPromise(left);
if (loadPromise.peek() == storeAddr)
otherValue = right;
else if (commutativity == Commutative) {
- loadPromise = this->loadPromise(right);
+ loadPromise = getLoadPromise(right);
if (loadPromise.peek() == storeAddr)
otherValue = left;
}
@@ -1779,12 +1804,42 @@
case B3::Store8: {
Value* valueToStore = m_value->child(0);
+ if (canBeInternal(valueToStore)) {
+ bool matched = false;
+ switch (valueToStore->opcode()) {
+ case Add:
+ matched = tryAppendStoreBinOp<Add8, Air::Oops, Commutative>(
+ valueToStore->child(0), valueToStore->child(1));
+ break;
+ default:
+ break;
+ }
+ if (matched) {
+ commitInternal(valueToStore);
+ return;
+ }
+ }
m_insts.last().append(createStore(Air::Store8, valueToStore, addr(m_value)));
return;
}
case B3::Store16: {
Value* valueToStore = m_value->child(0);
+ if (canBeInternal(valueToStore)) {
+ bool matched = false;
+ switch (valueToStore->opcode()) {
+ case Add:
+ matched = tryAppendStoreBinOp<Add16, Air::Oops, Commutative>(
+ valueToStore->child(0), valueToStore->child(1));
+ break;
+ default:
+ break;
+ }
+ if (matched) {
+ commitInternal(valueToStore);
+ return;
+ }
+ }
m_insts.last().append(createStore(Air::Store16, valueToStore, addr(m_value)));
return;
}
Modified: trunk/Source/_javascript_Core/b3/B3PureCSE.cpp (195548 => 195549)
--- trunk/Source/_javascript_Core/b3/B3PureCSE.cpp 2016-01-25 20:37:44 UTC (rev 195548)
+++ trunk/Source/_javascript_Core/b3/B3PureCSE.cpp 2016-01-25 20:47:18 UTC (rev 195549)
@@ -46,6 +46,23 @@
m_map.clear();
}
+Value* PureCSE::findMatch(const ValueKey& key, BasicBlock* block, Dominators& dominators)
+{
+ if (!key)
+ return nullptr;
+
+ auto iter = m_map.find(key);
+ if (iter == m_map.end())
+ return nullptr;
+
+ for (Value* match : iter->value) {
+ if (dominators.dominates(match->owner, block))
+ return match;
+ }
+
+ return nullptr;
+}
+
bool PureCSE::process(Value* value, Dominators& dominators)
{
if (value->opcode() == Identity)
Modified: trunk/Source/_javascript_Core/b3/B3PureCSE.h (195548 => 195549)
--- trunk/Source/_javascript_Core/b3/B3PureCSE.h 2016-01-25 20:37:44 UTC (rev 195548)
+++ trunk/Source/_javascript_Core/b3/B3PureCSE.h 2016-01-25 20:47:18 UTC (rev 195549)
@@ -34,6 +34,7 @@
namespace JSC { namespace B3 {
+class BasicBlock;
class Dominators;
class Value;
@@ -48,6 +49,8 @@
void clear();
+ Value* findMatch(const ValueKey&, BasicBlock*, Dominators&);
+
bool process(Value*, Dominators&);
private:
Modified: trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp (195548 => 195549)
--- trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp 2016-01-25 20:37:44 UTC (rev 195548)
+++ trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp 2016-01-25 20:47:18 UTC (rev 195549)
@@ -42,7 +42,7 @@
#include "B3PureCSE.h"
#include "B3UpsilonValue.h"
#include "B3UseCounts.h"
-#include "B3ValueKey.h"
+#include "B3ValueKeyInlines.h"
#include "B3ValueInlines.h"
#include <wtf/GraphNodeWorklist.h>
#include <wtf/HashMap.h>
@@ -1643,7 +1643,19 @@
m_changedCFG = true;
break;
}
-
+
+ // If a check for the same property dominates us, we can kill the branch. This sort
+ // of makes sense here because it's cheap, but hacks like this show that we're going
+ // to need SCCP.
+ Value* check = m_pureCSE.findMatch(
+ ValueKey(Check, Void, branch->child(0)), m_block, *m_dominators);
+ if (check) {
+ // The Check would have side-exited if child(0) was non-zero. So, it must be
+ // zero here.
+ branch->taken().block()->removePredecessor(m_block);
+ branch->convertToJump(branch->notTaken().block());
+ m_changedCFG = true;
+ }
break;
}
Modified: trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes (195548 => 195549)
--- trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes 2016-01-25 20:37:44 UTC (rev 195548)
+++ trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes 2016-01-25 20:47:18 UTC (rev 195549)
@@ -110,10 +110,24 @@
Add32 U:G:32, UZD:G:32
Tmp, Tmp
x86: Imm, Addr
+ x86: Imm, Index
Imm, Tmp
x86: Addr, Tmp
x86: Tmp, Addr
+ x86: Tmp, Index
+x86: Add8 U:G:8, UD:G:8
+ Imm, Addr
+ Imm, Index
+ Tmp, Addr
+ Tmp, Index
+
+x86: Add16 U:G:16, UD:G:16
+ Imm, Addr
+ Imm, Index
+ Tmp, Addr
+ Tmp, Index
+
Add32 U:G:32, U:G:32, ZD:G:32
Imm, Tmp, Tmp
Tmp, Tmp, Tmp
Modified: trunk/Source/_javascript_Core/b3/testb3.cpp (195548 => 195549)
--- trunk/Source/_javascript_Core/b3/testb3.cpp 2016-01-25 20:37:44 UTC (rev 195548)
+++ trunk/Source/_javascript_Core/b3/testb3.cpp 2016-01-25 20:47:18 UTC (rev 195549)
@@ -4266,7 +4266,7 @@
CHECK(compileAndRun<intptr_t>(proc, value) == -value);
}
-void testStoreAddLoad(int amount)
+void testStoreAddLoad32(int amount)
{
Procedure proc;
BasicBlock* root = proc.addBlock();
@@ -4277,6 +4277,29 @@
root->appendNew<Value>(
proc, Add, Origin(),
root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
+ root->appendNew<Value>(
+ proc, Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
+ slotPtr);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Const32Value>(proc, Origin(), 0));
+
+ CHECK(!compileAndRun<int>(proc, amount));
+ CHECK(slot == 37 + amount);
+}
+
+void testStoreAddLoadImm32(int amount)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ int slot = 37;
+ ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
+ root->appendNew<MemoryValue>(
+ proc, Store, Origin(),
+ root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
root->appendNew<Const32Value>(proc, Origin(), amount)),
slotPtr);
root->appendNew<ControlValue>(
@@ -4287,6 +4310,382 @@
CHECK(slot == 37 + amount);
}
+void testStoreAddLoad8(int amount, B3::Opcode loadOpcode)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ int8_t slot = 37;
+ ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
+ root->appendNew<MemoryValue>(
+ proc, Store8, Origin(),
+ root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
+ root->appendNew<Value>(
+ proc, Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
+ slotPtr);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Const32Value>(proc, Origin(), 0));
+
+ CHECK(!compileAndRun<int>(proc, amount));
+ CHECK(slot == 37 + amount);
+}
+
+void testStoreAddLoadImm8(int amount, B3::Opcode loadOpcode)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ int8_t slot = 37;
+ ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
+ root->appendNew<MemoryValue>(
+ proc, Store8, Origin(),
+ root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
+ root->appendNew<Const32Value>(proc, Origin(), amount)),
+ slotPtr);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Const32Value>(proc, Origin(), 0));
+
+ CHECK(!compileAndRun<int>(proc));
+ CHECK(slot == 37 + amount);
+}
+
+void testStoreAddLoad16(int amount, B3::Opcode loadOpcode)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ int16_t slot = 37;
+ ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
+ root->appendNew<MemoryValue>(
+ proc, Store16, Origin(),
+ root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
+ root->appendNew<Value>(
+ proc, Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
+ slotPtr);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Const32Value>(proc, Origin(), 0));
+
+ CHECK(!compileAndRun<int>(proc, amount));
+ CHECK(slot == 37 + amount);
+}
+
+void testStoreAddLoadImm16(int amount, B3::Opcode loadOpcode)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ int16_t slot = 37;
+ ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
+ root->appendNew<MemoryValue>(
+ proc, Store16, Origin(),
+ root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
+ root->appendNew<Const32Value>(proc, Origin(), amount)),
+ slotPtr);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Const32Value>(proc, Origin(), 0));
+
+ CHECK(!compileAndRun<int>(proc));
+ CHECK(slot == 37 + amount);
+}
+
+void testStoreAddLoad64(int amount)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ int64_t slot = 37000000000ll;
+ ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
+ root->appendNew<MemoryValue>(
+ proc, Store, Origin(),
+ root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
+ slotPtr);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Const32Value>(proc, Origin(), 0));
+
+ CHECK(!compileAndRun<int>(proc, amount));
+ CHECK(slot == 37000000000ll + amount);
+}
+
+void testStoreAddLoadImm64(int64_t amount)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ int64_t slot = 370000000000ll;
+ ConstPtrValue* slotPtr = root->appendNew<ConstPtrValue>(proc, Origin(), &slot);
+ root->appendNew<MemoryValue>(
+ proc, Store, Origin(),
+ root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
+ root->appendNew<Const64Value>(proc, Origin(), amount)),
+ slotPtr);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Const32Value>(proc, Origin(), 0));
+
+ CHECK(!compileAndRun<int>(proc));
+ CHECK(slot == 370000000000ll + amount);
+}
+
+void testStoreAddLoad32Index(int amount)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ int slot = 37;
+ int* ptr = &slot;
+ intptr_t zero = 0;
+ Value* slotPtr = root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(
+ proc, Load, pointerType(), Origin(),
+ root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
+ root->appendNew<MemoryValue>(
+ proc, Load, pointerType(), Origin(),
+ root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
+ root->appendNew<MemoryValue>(
+ proc, Store, Origin(),
+ root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
+ root->appendNew<Value>(
+ proc, Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
+ slotPtr);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Const32Value>(proc, Origin(), 0));
+
+ CHECK(!compileAndRun<int>(proc, amount));
+ CHECK(slot == 37 + amount);
+}
+
+void testStoreAddLoadImm32Index(int amount)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ int slot = 37;
+ int* ptr = &slot;
+ intptr_t zero = 0;
+ Value* slotPtr = root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(
+ proc, Load, pointerType(), Origin(),
+ root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
+ root->appendNew<MemoryValue>(
+ proc, Load, pointerType(), Origin(),
+ root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
+ root->appendNew<MemoryValue>(
+ proc, Store, Origin(),
+ root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr),
+ root->appendNew<Const32Value>(proc, Origin(), amount)),
+ slotPtr);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Const32Value>(proc, Origin(), 0));
+
+ CHECK(!compileAndRun<int>(proc));
+ CHECK(slot == 37 + amount);
+}
+
+void testStoreAddLoad8Index(int amount, B3::Opcode loadOpcode)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ int8_t slot = 37;
+ int8_t* ptr = &slot;
+ intptr_t zero = 0;
+ Value* slotPtr = root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(
+ proc, Load, pointerType(), Origin(),
+ root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
+ root->appendNew<MemoryValue>(
+ proc, Load, pointerType(), Origin(),
+ root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
+ root->appendNew<MemoryValue>(
+ proc, Store8, Origin(),
+ root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
+ root->appendNew<Value>(
+ proc, Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
+ slotPtr);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Const32Value>(proc, Origin(), 0));
+
+ CHECK(!compileAndRun<int>(proc, amount));
+ CHECK(slot == 37 + amount);
+}
+
+void testStoreAddLoadImm8Index(int amount, B3::Opcode loadOpcode)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ int8_t slot = 37;
+ int8_t* ptr = &slot;
+ intptr_t zero = 0;
+ Value* slotPtr = root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(
+ proc, Load, pointerType(), Origin(),
+ root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
+ root->appendNew<MemoryValue>(
+ proc, Load, pointerType(), Origin(),
+ root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
+ root->appendNew<MemoryValue>(
+ proc, Store8, Origin(),
+ root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
+ root->appendNew<Const32Value>(proc, Origin(), amount)),
+ slotPtr);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Const32Value>(proc, Origin(), 0));
+
+ CHECK(!compileAndRun<int>(proc));
+ CHECK(slot == 37 + amount);
+}
+
+void testStoreAddLoad16Index(int amount, B3::Opcode loadOpcode)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ int16_t slot = 37;
+ int16_t* ptr = &slot;
+ intptr_t zero = 0;
+ Value* slotPtr = root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(
+ proc, Load, pointerType(), Origin(),
+ root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
+ root->appendNew<MemoryValue>(
+ proc, Load, pointerType(), Origin(),
+ root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
+ root->appendNew<MemoryValue>(
+ proc, Store16, Origin(),
+ root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
+ root->appendNew<Value>(
+ proc, Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))),
+ slotPtr);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Const32Value>(proc, Origin(), 0));
+
+ CHECK(!compileAndRun<int>(proc, amount));
+ CHECK(slot == 37 + amount);
+}
+
+void testStoreAddLoadImm16Index(int amount, B3::Opcode loadOpcode)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ int16_t slot = 37;
+ int16_t* ptr = &slot;
+ intptr_t zero = 0;
+ Value* slotPtr = root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(
+ proc, Load, pointerType(), Origin(),
+ root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
+ root->appendNew<MemoryValue>(
+ proc, Load, pointerType(), Origin(),
+ root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
+ root->appendNew<MemoryValue>(
+ proc, Store16, Origin(),
+ root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr),
+ root->appendNew<Const32Value>(proc, Origin(), amount)),
+ slotPtr);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Const32Value>(proc, Origin(), 0));
+
+ CHECK(!compileAndRun<int>(proc));
+ CHECK(slot == 37 + amount);
+}
+
+void testStoreAddLoad64Index(int amount)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ int64_t slot = 37000000000ll;
+ int64_t* ptr = &slot;
+ intptr_t zero = 0;
+ Value* slotPtr = root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(
+ proc, Load, pointerType(), Origin(),
+ root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
+ root->appendNew<MemoryValue>(
+ proc, Load, pointerType(), Origin(),
+ root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
+ root->appendNew<MemoryValue>(
+ proc, Store, Origin(),
+ root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
+ slotPtr);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Const32Value>(proc, Origin(), 0));
+
+ CHECK(!compileAndRun<int>(proc, amount));
+ CHECK(slot == 37000000000ll + amount);
+}
+
+void testStoreAddLoadImm64Index(int64_t amount)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ int64_t slot = 370000000000ll;
+ int64_t* ptr = &slot;
+ intptr_t zero = 0;
+ Value* slotPtr = root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(
+ proc, Load, pointerType(), Origin(),
+ root->appendNew<ConstPtrValue>(proc, Origin(), &ptr)),
+ root->appendNew<MemoryValue>(
+ proc, Load, pointerType(), Origin(),
+ root->appendNew<ConstPtrValue>(proc, Origin(), &zero)));
+ root->appendNew<MemoryValue>(
+ proc, Store, Origin(),
+ root->appendNew<Value>(
+ proc, Add, Origin(),
+ root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr),
+ root->appendNew<Const64Value>(proc, Origin(), amount)),
+ slotPtr);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Const32Value>(proc, Origin(), 0));
+
+ CHECK(!compileAndRun<int>(proc));
+ CHECK(slot == 370000000000ll + amount);
+}
+
void testStoreSubLoad(int amount)
{
Procedure proc;
@@ -10276,7 +10675,30 @@
RUN(testAdd1Ptr(bitwise_cast<intptr_t>(vm)));
RUN(testNeg32(52));
RUN(testNegPtr(53));
- RUN(testStoreAddLoad(46));
+ RUN(testStoreAddLoad32(46));
+ RUN(testStoreAddLoadImm32(46));
+ RUN(testStoreAddLoad64(4600));
+ RUN(testStoreAddLoadImm64(4600));
+ RUN(testStoreAddLoad8(4, Load8Z));
+ RUN(testStoreAddLoadImm8(4, Load8Z));
+ RUN(testStoreAddLoad8(4, Load8S));
+ RUN(testStoreAddLoadImm8(4, Load8S));
+ RUN(testStoreAddLoad16(6, Load16Z));
+ RUN(testStoreAddLoadImm16(6, Load16Z));
+ RUN(testStoreAddLoad16(6, Load16S));
+ RUN(testStoreAddLoadImm16(6, Load16S));
+ RUN(testStoreAddLoad32Index(46));
+ RUN(testStoreAddLoadImm32Index(46));
+ RUN(testStoreAddLoad64Index(4600));
+ RUN(testStoreAddLoadImm64Index(4600));
+ RUN(testStoreAddLoad8Index(4, Load8Z));
+ RUN(testStoreAddLoadImm8Index(4, Load8Z));
+ RUN(testStoreAddLoad8Index(4, Load8S));
+ RUN(testStoreAddLoadImm8Index(4, Load8S));
+ RUN(testStoreAddLoad16Index(6, Load16Z));
+ RUN(testStoreAddLoadImm16Index(6, Load16Z));
+ RUN(testStoreAddLoad16Index(6, Load16S));
+ RUN(testStoreAddLoadImm16Index(6, Load16S));
RUN(testStoreSubLoad(46));
RUN(testStoreAddLoadInterference(52));
RUN(testStoreAddAndLoad(47, 0xffff));
Modified: trunk/Source/_javascript_Core/disassembler/udis86/udis86_syn-att.c (195548 => 195549)
--- trunk/Source/_javascript_Core/disassembler/udis86/udis86_syn-att.c 2016-01-25 20:37:44 UTC (rev 195548)
+++ trunk/Source/_javascript_Core/disassembler/udis86/udis86_syn-att.c 2016-01-25 20:47:18 UTC (rev 195549)
@@ -167,6 +167,7 @@
ud_translate_att(struct ud *u)
{
int size = 0;
+ unsigned i;
/* check if P_OSO prefix is used */
if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) {
@@ -229,19 +230,19 @@
mkasm(u, "%s", ud_lookup_mnemonic(u->mnemonic));
}
- if (u->c1)
- size = u->operand[0].size;
- else if (u->c2)
- size = u->operand[1].size;
- else if (u->c3)
- size = u->operand[2].size;
+ for (i = 3; i--;) {
+ if (u->operand[i].size > size)
+ size = u->operand[i].size;
+ }
if (size == 8)
- mkasm(u, "b");
+ mkasm(u, "b");
else if (size == 16)
- mkasm(u, "w");
+ mkasm(u, "w");
+ else if (size == 32)
+ mkasm(u, "l");
else if (size == 64)
- mkasm(u, "q");
+ mkasm(u, "q");
mkasm(u, " ");
_______________________________________________ webkit-changes mailing list [email protected] https://lists.webkit.org/mailman/listinfo/webkit-changes
