Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(649)

Side by Side Diff: src/compiler/wasm-compiler.cc

Issue 2045943002: [compiler] [wasm] Introduce Word32/64ReverseBytes as TF Optional Opcode (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix according to titzer Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/verifier.cc ('k') | src/compiler/x64/instruction-selector-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/wasm-compiler.h" 5 #include "src/compiler/wasm-compiler.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "src/isolate-inl.h" 9 #include "src/isolate-inl.h"
10 10
(...skipping 989 matching lines...) Expand 10 before | Expand all | Expand 10 after
1000 int64_t masked = (match.Value() & kMask64); 1000 int64_t masked = (match.Value() & kMask64);
1001 if (match.Value() != masked) node = jsgraph()->Int64Constant(masked); 1001 if (match.Value() != masked) node = jsgraph()->Int64Constant(masked);
1002 } else { 1002 } else {
1003 node = graph()->NewNode(jsgraph()->machine()->Word64And(), node, 1003 node = graph()->NewNode(jsgraph()->machine()->Word64And(), node,
1004 jsgraph()->Int64Constant(kMask64)); 1004 jsgraph()->Int64Constant(kMask64));
1005 } 1005 }
1006 } 1006 }
1007 return node; 1007 return node;
1008 } 1008 }
1009 1009
1010 static bool ReverseBytesSupported(MachineOperatorBuilder* m,
1011 size_t size_in_bytes) {
1012 switch (size_in_bytes) {
1013 case 4:
1014 return m->Word32ReverseBytes().IsSupported();
1015 case 8:
1016 return m->Word64ReverseBytes().IsSupported();
1017 default:
1018 break;
1019 }
1020 return false;
1021 }
1022
1010 Node* WasmGraphBuilder::BuildChangeEndianness(Node* node, MachineType memtype, 1023 Node* WasmGraphBuilder::BuildChangeEndianness(Node* node, MachineType memtype,
1011 wasm::LocalType wasmtype) { 1024 wasm::LocalType wasmtype) {
1012 Node* result; 1025 Node* result;
1013 Node* value = node; 1026 Node* value = node;
1014 const Operator* shiftLeftOpcode;
1015 const Operator* shiftRightOpcode;
1016 const Operator* andOpcode;
1017 const Operator* orOpcode;
1018 MachineOperatorBuilder* m = jsgraph()->machine(); 1027 MachineOperatorBuilder* m = jsgraph()->machine();
1019 int valueSizeInBytes = 1 << ElementSizeLog2Of(memtype.representation()); 1028 int valueSizeInBytes = 1 << ElementSizeLog2Of(memtype.representation());
1020 int valueSizeInBits = 8 * valueSizeInBytes; 1029 int valueSizeInBits = 8 * valueSizeInBytes;
1021 bool isFloat = false; 1030 bool isFloat = false;
1022 1031
1023 switch (memtype.representation()) { 1032 switch (memtype.representation()) {
1024 case MachineRepresentation::kFloat64: 1033 case MachineRepresentation::kFloat64:
1025 value = graph()->NewNode(m->BitcastFloat64ToInt64(), node); 1034 value = graph()->NewNode(m->BitcastFloat64ToInt64(), node);
1026 isFloat = true; 1035 isFloat = true;
1027 case MachineRepresentation::kWord64: 1036 case MachineRepresentation::kWord64:
1028 shiftLeftOpcode = m->Word64Shl();
1029 shiftRightOpcode = m->Word64Shr();
1030 andOpcode = m->Word64And();
1031 orOpcode = m->Word64Or();
1032 result = jsgraph()->Int64Constant(0); 1037 result = jsgraph()->Int64Constant(0);
1033 break; 1038 break;
1034 case MachineRepresentation::kFloat32: 1039 case MachineRepresentation::kFloat32:
1035 value = graph()->NewNode(m->BitcastFloat32ToInt32(), node); 1040 value = graph()->NewNode(m->BitcastFloat32ToInt32(), node);
1036 isFloat = true; 1041 isFloat = true;
1037 case MachineRepresentation::kWord32: 1042 case MachineRepresentation::kWord32:
1038 case MachineRepresentation::kWord16: 1043 case MachineRepresentation::kWord16:
1039 shiftLeftOpcode = m->Word32Shl();
1040 shiftRightOpcode = m->Word32Shr();
1041 andOpcode = m->Word32And();
1042 orOpcode = m->Word32Or();
1043 result = jsgraph()->Int32Constant(0); 1044 result = jsgraph()->Int32Constant(0);
1044 break; 1045 break;
1045 case MachineRepresentation::kWord8: 1046 case MachineRepresentation::kWord8:
1046 // No need to change endianness for byte size, return original node 1047 // No need to change endianness for byte size, return original node
1047 return node; 1048 return node;
1048 break; 1049 break;
1049 default: 1050 default:
1050 UNREACHABLE(); 1051 UNREACHABLE();
1051 break; 1052 break;
1052 } 1053 }
1053 1054
1054 int i; 1055 int i;
1055 uint32_t shiftCount; 1056 uint32_t shiftCount;
1056 1057
1057 for (i = 0, shiftCount = valueSizeInBits - 8; i < valueSizeInBits / 2; 1058 if (ReverseBytesSupported(m, valueSizeInBytes < 4 ? 4 : valueSizeInBytes)) {
1058 i += 8, shiftCount -= 16) { 1059 switch (valueSizeInBytes) {
1059 Node* shiftLower; 1060 case 2:
1060 Node* shiftHigher; 1061 result =
1061 Node* lowerByte; 1062 graph()->NewNode(m->Word32ReverseBytes().op(),
1062 Node* higherByte; 1063 graph()->NewNode(m->Word32Shl(), value,
1064 jsgraph()->Int32Constant(16)));
1065 break;
1066 case 4:
1067 result = graph()->NewNode(m->Word32ReverseBytes().op(), value);
1068 break;
1069 case 8:
1070 result = graph()->NewNode(m->Word64ReverseBytes().op(), value);
1071 break;
1072 default:
1073 UNREACHABLE();
1074 }
1075 } else {
1076 for (i = 0, shiftCount = valueSizeInBits - 8; i < valueSizeInBits / 2;
1077 i += 8, shiftCount -= 16) {
1078 Node* shiftLower;
1079 Node* shiftHigher;
1080 Node* lowerByte;
1081 Node* higherByte;
1063 1082
1064 DCHECK(shiftCount > 0); 1083 DCHECK(shiftCount > 0);
1065 DCHECK((shiftCount + 8) % 16 == 0); 1084 DCHECK((shiftCount + 8) % 16 == 0);
1066 1085
1067 if (valueSizeInBits > 32) { 1086 if (valueSizeInBits > 32) {
1068 shiftLower = graph()->NewNode(shiftLeftOpcode, value, 1087 shiftLower = graph()->NewNode(m->Word64Shl(), value,
1069 jsgraph()->Int64Constant(shiftCount)); 1088 jsgraph()->Int64Constant(shiftCount));
1070 shiftHigher = graph()->NewNode(shiftRightOpcode, value, 1089 shiftHigher = graph()->NewNode(m->Word64Shr(), value,
1071 jsgraph()->Int64Constant(shiftCount)); 1090 jsgraph()->Int64Constant(shiftCount));
1072 lowerByte = graph()->NewNode( 1091 lowerByte = graph()->NewNode(
1073 andOpcode, shiftLower, 1092 m->Word64And(), shiftLower,
1074 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) 1093 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF)
1075 << (valueSizeInBits - 8 - i))); 1094 << (valueSizeInBits - 8 - i)));
1076 higherByte = graph()->NewNode( 1095 higherByte = graph()->NewNode(
1077 andOpcode, shiftHigher, 1096 m->Word64And(), shiftHigher,
1078 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) << i)); 1097 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) << i));
1079 } else { 1098 result = graph()->NewNode(m->Word64Or(), result, lowerByte);
1080 shiftLower = graph()->NewNode(shiftLeftOpcode, value, 1099 result = graph()->NewNode(m->Word64Or(), result, higherByte);
1081 jsgraph()->Int32Constant(shiftCount)); 1100 } else {
1082 shiftHigher = graph()->NewNode(shiftRightOpcode, value, 1101 shiftLower = graph()->NewNode(m->Word32Shl(), value,
1083 jsgraph()->Int32Constant(shiftCount)); 1102 jsgraph()->Int32Constant(shiftCount));
1084 lowerByte = graph()->NewNode( 1103 shiftHigher = graph()->NewNode(m->Word32Shr(), value,
1085 andOpcode, shiftLower, 1104 jsgraph()->Int32Constant(shiftCount));
1086 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) 1105 lowerByte = graph()->NewNode(
1087 << (valueSizeInBits - 8 - i))); 1106 m->Word32And(), shiftLower,
1088 higherByte = graph()->NewNode( 1107 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF)
1089 andOpcode, shiftHigher, 1108 << (valueSizeInBits - 8 - i)));
1090 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) << i)); 1109 higherByte = graph()->NewNode(
1110 m->Word32And(), shiftHigher,
1111 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) << i));
1112 result = graph()->NewNode(m->Word32Or(), result, lowerByte);
1113 result = graph()->NewNode(m->Word32Or(), result, higherByte);
1114 }
1091 } 1115 }
1092
1093 result = graph()->NewNode(orOpcode, result, lowerByte);
1094 result = graph()->NewNode(orOpcode, result, higherByte);
1095 } 1116 }
1096 1117
1097 if (isFloat) { 1118 if (isFloat) {
1098 switch (memtype.representation()) { 1119 switch (memtype.representation()) {
1099 case MachineRepresentation::kFloat64: 1120 case MachineRepresentation::kFloat64:
1100 result = graph()->NewNode(m->BitcastInt64ToFloat64(), result); 1121 result = graph()->NewNode(m->BitcastInt64ToFloat64(), result);
1101 break; 1122 break;
1102 case MachineRepresentation::kFloat32: 1123 case MachineRepresentation::kFloat32:
1103 result = graph()->NewNode(m->BitcastInt32ToFloat32(), result); 1124 result = graph()->NewNode(m->BitcastInt32ToFloat32(), result);
1104 break; 1125 break;
1105 default: 1126 default:
1106 UNREACHABLE(); 1127 UNREACHABLE();
1107 break; 1128 break;
1108 } 1129 }
1109 } 1130 }
1110 1131
1111 // We need to sign extend the value 1132 // We need to sign extend the value
1112 if (memtype.IsSigned()) { 1133 if (memtype.IsSigned()) {
1113 DCHECK(!isFloat); 1134 DCHECK(!isFloat);
1114 if (valueSizeInBits < 32) { 1135 if (valueSizeInBits < 32) {
1115 Node* shiftBitCount; 1136 Node* shiftBitCount;
1116 // Perform sign extension using following trick 1137 // Perform sign extension using following trick
1117 // result = (x << machine_width - type_width) >> (machine_width - 1138 // result = (x << machine_width - type_width) >> (machine_width -
1118 // type_width) 1139 // type_width)
1119 if (wasmtype == wasm::kAstI64) { 1140 if (wasmtype == wasm::kAstI64) {
1120 shiftBitCount = jsgraph()->Int32Constant(64 - valueSizeInBits); 1141 shiftBitCount = jsgraph()->Int32Constant(64 - valueSizeInBits);
1121 result = graph()->NewNode( 1142 result = graph()->NewNode(
1122 m->Word64Sar(), 1143 m->Word64Sar(),
1123 graph()->NewNode(m->Word64Shl(), result, shiftBitCount), 1144 graph()->NewNode(m->Word64Shl(),
1145 graph()->NewNode(m->ChangeInt32ToInt64(), result),
1146 shiftBitCount),
1124 shiftBitCount); 1147 shiftBitCount);
1125 } else if (wasmtype == wasm::kAstI32) { 1148 } else if (wasmtype == wasm::kAstI32) {
1126 shiftBitCount = jsgraph()->Int32Constant(32 - valueSizeInBits); 1149 shiftBitCount = jsgraph()->Int32Constant(32 - valueSizeInBits);
1127 result = graph()->NewNode( 1150 result = graph()->NewNode(
1128 m->Word32Sar(), 1151 m->Word32Sar(),
1129 graph()->NewNode(m->Word32Shl(), result, shiftBitCount), 1152 graph()->NewNode(m->Word32Shl(), result, shiftBitCount),
1130 shiftBitCount); 1153 shiftBitCount);
1131 } 1154 }
1132 } 1155 }
1133 } 1156 }
(...skipping 1842 matching lines...) Expand 10 before | Expand all | Expand 10 after
2976 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), 2999 load = graph()->NewNode(jsgraph()->machine()->Load(memtype),
2977 MemBuffer(offset), index, *effect_, *control_); 3000 MemBuffer(offset), index, *effect_, *control_);
2978 } else { 3001 } else {
2979 load = graph()->NewNode(jsgraph()->machine()->UnalignedLoad(memtype), 3002 load = graph()->NewNode(jsgraph()->machine()->UnalignedLoad(memtype),
2980 MemBuffer(offset), index, *effect_, *control_); 3003 MemBuffer(offset), index, *effect_, *control_);
2981 } 3004 }
2982 3005
2983 *effect_ = load; 3006 *effect_ = load;
2984 3007
2985 #if defined(V8_TARGET_BIG_ENDIAN) 3008 #if defined(V8_TARGET_BIG_ENDIAN)
2986 // TODO(john.yan) Implement byte swap turbofan operator
2987 // and use it if available for better performance
2988 load = BuildChangeEndianness(load, memtype, type); 3009 load = BuildChangeEndianness(load, memtype, type);
2989 #endif 3010 #endif
2990 3011
2991 if (type == wasm::kAstI64 && 3012 if (type == wasm::kAstI64 &&
2992 ElementSizeLog2Of(memtype.representation()) < 3) { 3013 ElementSizeLog2Of(memtype.representation()) < 3) {
2993 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes. 3014 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes.
2994 if (memtype.IsSigned()) { 3015 if (memtype.IsSigned()) {
2995 // sign extend 3016 // sign extend
2996 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); 3017 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load);
2997 } else { 3018 } else {
2998 // zero extend 3019 // zero extend
2999 load = 3020 load =
3000 graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), load); 3021 graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), load);
3001 } 3022 }
3002 } 3023 }
3003 3024
3004 return load; 3025 return load;
3005 } 3026 }
3006 3027
3007 3028
3008 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, 3029 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index,
3009 uint32_t offset, uint32_t alignment, Node* val, 3030 uint32_t offset, uint32_t alignment, Node* val,
3010 wasm::WasmCodePosition position) { 3031 wasm::WasmCodePosition position) {
3011 Node* store; 3032 Node* store;
3012 3033
3013 // WASM semantics throw on OOB. Introduce explicit bounds check. 3034 // WASM semantics throw on OOB. Introduce explicit bounds check.
3014 BoundsCheckMem(memtype, index, offset, position); 3035 BoundsCheckMem(memtype, index, offset, position);
3015 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); 3036 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier);
3037
3016 bool aligned = static_cast<int>(alignment) >= 3038 bool aligned = static_cast<int>(alignment) >=
3017 ElementSizeLog2Of(memtype.representation()); 3039 ElementSizeLog2Of(memtype.representation());
3018 3040
3019 #if defined(V8_TARGET_BIG_ENDIAN) 3041 #if defined(V8_TARGET_BIG_ENDIAN)
3020 // TODO(john.yan) Implement byte swap turbofan operator
3021 // and use it if available for better performance
3022 val = BuildChangeEndianness(val, memtype); 3042 val = BuildChangeEndianness(val, memtype);
3023 #endif 3043 #endif
3024 3044
3025 if (aligned || 3045 if (aligned ||
3026 jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) { 3046 jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) {
3027 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); 3047 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier);
3028 store = 3048 store =
3029 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), 3049 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset),
3030 index, val, *effect_, *control_); 3050 index, val, *effect_, *control_);
3031 } else { 3051 } else {
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after
3476 function_->code_start_offset), 3496 function_->code_start_offset),
3477 compile_ms); 3497 compile_ms);
3478 } 3498 }
3479 3499
3480 return code; 3500 return code;
3481 } 3501 }
3482 3502
3483 } // namespace compiler 3503 } // namespace compiler
3484 } // namespace internal 3504 } // namespace internal
3485 } // namespace v8 3505 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/verifier.cc ('k') | src/compiler/x64/instruction-selector-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698