Chromium Code Reviews| Index: src/compiler/wasm-compiler.cc |
| diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc |
| index 7270ddd24848854d9e42a020404ed04bdcca7ed4..d3193e3b2443947f9e9b77d89c88d63bc38b11b0 100644 |
| --- a/src/compiler/wasm-compiler.cc |
| +++ b/src/compiler/wasm-compiler.cc |
| @@ -992,6 +992,117 @@ Node* WasmGraphBuilder::MaskShiftCount64(Node* node) { |
| return node; |
| } |
| +Node* WasmGraphBuilder::BuildChangeEndianness(Node* node, MachineType memtype, |
| + wasm::LocalType wasmtype) { |
| + Node* result; |
| + Node* value = node; |
| + wasm::WasmOpcode shiftLeftOpcode; |
| + wasm::WasmOpcode shiftRightOpcode; |
| + wasm::WasmOpcode andOpcode, orOpcode; |
| + int valueSizeInBytes = 1 << ElementSizeLog2Of(memtype.representation()); |
| + int valueSizeInBits = 8 * valueSizeInBytes; |
| + bool isFloat = false; |
| + |
| + switch (memtype.representation()) { |
| + case MachineRepresentation::kFloat64: |
| + value = Unop(wasm::kExprI64ReinterpretF64, node); |
| + isFloat = true; |
| + case MachineRepresentation::kWord64: |
| + shiftLeftOpcode = wasm::kExprI64Shl; |
| + shiftRightOpcode = wasm::kExprI64ShrU; |
| + andOpcode = wasm::kExprI64And; |
| + orOpcode = wasm::kExprI64Ior; |
| + result = jsgraph()->Int64Constant(0); |
| + break; |
| + case MachineRepresentation::kFloat32: |
| + value = Unop(wasm::kExprI32ReinterpretF32, node); |
| + isFloat = true; |
| + case MachineRepresentation::kWord32: |
| + case MachineRepresentation::kWord16: |
| + shiftLeftOpcode = wasm::kExprI32Shl; |
| + shiftRightOpcode = wasm::kExprI32ShrU; |
| + andOpcode = wasm::kExprI32And; |
| + orOpcode = wasm::kExprI32Ior; |
| + result = jsgraph()->Int32Constant(0); |
| + break; |
| + case MachineRepresentation::kWord8: |
| + // No need to change endianness for byte size, return original node |
| + return node; |
| + break; |
| + default: |
| + UNREACHABLE(); |
| + break; |
| + } |
| + |
| + int i; |
| + uint32_t shiftCount; |
| + |
| + for (i = 0, shiftCount = valueSizeInBits - 8; i < valueSizeInBits / 2; |
| + i += 8, shiftCount -= 16) { |
| + DCHECK(shiftCount > 0); |
| + DCHECK((shiftCount + 8) % 16 == 0); |
| + |
| + Node* shiftLower = |
| + Binop(shiftLeftOpcode, value, jsgraph()->Int32Constant(shiftCount)); |
|
titzer
2016/06/06 07:44:00
Reusing the Binop() routine is a little inefficien
|
| + Node* shiftHigher = |
| + Binop(shiftRightOpcode, value, jsgraph()->Int32Constant(shiftCount)); |
| + |
| + Node* lowerByte; |
| + Node* higherByte; |
| + |
| + if (valueSizeInBits > 32) { |
| + lowerByte = |
| + Binop(andOpcode, shiftLower, |
| + jsgraph()->Int64Constant(0xFFl << (valueSizeInBits - 8 - i))); |
| + higherByte = |
| + Binop(andOpcode, shiftHigher, jsgraph()->Int64Constant(0xFFl << i)); |
| + } else { |
| + lowerByte = |
| + Binop(andOpcode, shiftLower, |
| + jsgraph()->Int32Constant(0xFF << (valueSizeInBits - 8 - i))); |
| + higherByte = |
| + Binop(andOpcode, shiftHigher, jsgraph()->Int32Constant(0xFF << i)); |
| + } |
| + |
| + result = Binop(orOpcode, result, lowerByte); |
| + result = Binop(orOpcode, result, higherByte); |
| + } |
| + |
| + if (isFloat) { |
| + switch (memtype.representation()) { |
| + case MachineRepresentation::kFloat64: |
| + result = Unop(wasm::kExprF64ReinterpretI64, result); |
| + break; |
| + case MachineRepresentation::kFloat32: |
| + result = Unop(wasm::kExprF32ReinterpretI32, result); |
| + break; |
| + default: |
| + UNREACHABLE(); |
| + break; |
| + } |
| + } |
| + |
| + // We need to sign extend the value |
| + if (memtype.IsSigned()) { |
| + DCHECK(!isFloat); |
| + if ((wasmtype == wasm::kAstI64 || wasmtype == wasm::kAstI32) && |
| + valueSizeInBits < 32) { |
| + uint32_t mask = 1 << (valueSizeInBits - 1); |
| + |
| + Node* signBit = |
| + Binop(wasm::kExprI32And, result, jsgraph()->Int32Constant(mask)); |
| + Diamond d(graph(), jsgraph()->common(), Unop(wasm::kExprI32Eqz, signBit)); |
|
titzer
2016/06/06 07:44:00
What about using (x << machine_width - width) >> (
|
| + |
| + result = |
| + d.Phi(MachineRepresentation::kWord32, result, |
| + Binop(wasm::kExprI32Ior, result, |
| + jsgraph()->Int32Constant(0xFFFFFFFF << valueSizeInBits))); |
| + } |
| + } |
| + |
| + return result; |
| +} |
| + |
| Node* WasmGraphBuilder::BuildF32Neg(Node* input) { |
| Node* result = |
| Unop(wasm::kExprF32ReinterpretI32, |
| @@ -2768,6 +2879,11 @@ Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype, |
| } else { |
| load = BuildUnalignedLoad(type, memtype, index, offset, alignment); |
| } |
| +#if defined(V8_TARGET_BIG_ENDIAN) |
| + // TODO(mips-team) Implement byte swap turbofan operator |
|
john.yan
2016/06/07 17:47:00
FYI: https://codereview.chromium.org/2045943002/
|
| + // and use it if available for better performance |
| + load = BuildChangeEndianness(load, memtype, type); |
| +#endif |
| if (type == wasm::kAstI64 && |
| ElementSizeLog2Of(memtype.representation()) < 3) { |
| @@ -2888,6 +3004,12 @@ Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, |
| bool aligned = static_cast<int>(alignment) >= |
| ElementSizeLog2Of(memtype.representation()); |
| +#if defined(V8_TARGET_BIG_ENDIAN) |
| + // TODO(mips-team) Implement byte swap turbofan operator |
| + // and use it if available for better performance |
| + val = BuildChangeEndianness(val, memtype); |
| +#endif |
| + |
| if (aligned || |
| jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) { |
| StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); |