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

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 ahaas 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
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 "src/isolate-inl.h" 7 #include "src/isolate-inl.h"
8 8
9 #include "src/base/platform/elapsed-timer.h" 9 #include "src/base/platform/elapsed-timer.h"
10 #include "src/base/platform/platform.h" 10 #include "src/base/platform/platform.h"
(...skipping 988 matching lines...) Expand 10 before | Expand all | Expand 10 after
999 int64_t masked = (match.Value() & kMask64); 999 int64_t masked = (match.Value() & kMask64);
1000 if (match.Value() != masked) node = jsgraph()->Int64Constant(masked); 1000 if (match.Value() != masked) node = jsgraph()->Int64Constant(masked);
1001 } else { 1001 } else {
1002 node = graph()->NewNode(jsgraph()->machine()->Word64And(), node, 1002 node = graph()->NewNode(jsgraph()->machine()->Word64And(), node,
1003 jsgraph()->Int64Constant(kMask64)); 1003 jsgraph()->Int64Constant(kMask64));
1004 } 1004 }
1005 } 1005 }
1006 return node; 1006 return node;
1007 } 1007 }
1008 1008
1009 static bool ReverseBytesSupported(MachineOperatorBuilder* m,
1010 size_t size_in_bytes) {
1011 switch (size_in_bytes) {
1012 case 4:
1013 return m->Word32ReverseBytes().IsSupported();
1014 case 8:
1015 return m->Word64ReverseBytes().IsSupported();
1016 default:
1017 break;
1018 }
1019 return false;
1020 }
1021
1009 Node* WasmGraphBuilder::BuildChangeEndianness(Node* node, MachineType memtype, 1022 Node* WasmGraphBuilder::BuildChangeEndianness(Node* node, MachineType memtype,
1010 wasm::LocalType wasmtype) { 1023 wasm::LocalType wasmtype) {
1011 Node* result; 1024 Node* result;
1012 Node* value = node; 1025 Node* value = node;
1013 const Operator* shiftLeftOpcode; 1026 const Operator* shiftLeftOpcode;
1014 const Operator* shiftRightOpcode; 1027 const Operator* shiftRightOpcode;
1015 const Operator* andOpcode; 1028 const Operator* andOpcode;
1016 const Operator* orOpcode; 1029 const Operator* orOpcode;
1017 MachineOperatorBuilder* m = jsgraph()->machine(); 1030 MachineOperatorBuilder* m = jsgraph()->machine();
1018 int valueSizeInBytes = 1 << ElementSizeLog2Of(memtype.representation()); 1031 int valueSizeInBytes = 1 << ElementSizeLog2Of(memtype.representation());
1019 int valueSizeInBits = 8 * valueSizeInBytes; 1032 int valueSizeInBits = 8 * valueSizeInBytes;
1020 bool isFloat = false; 1033 bool isFloat = false;
1021 1034
1022 switch (memtype.representation()) { 1035 switch (memtype.representation()) {
ahaas 2016/07/29 04:15:18 it seems to me that pre-calculating shiftLeftOpcod
john.yan 2016/07/29 17:12:03 xxxOpcode is now removed.
1023 case MachineRepresentation::kFloat64: 1036 case MachineRepresentation::kFloat64:
1024 value = graph()->NewNode(m->BitcastFloat64ToInt64(), node); 1037 value = graph()->NewNode(m->BitcastFloat64ToInt64(), node);
1025 isFloat = true; 1038 isFloat = true;
1026 case MachineRepresentation::kWord64: 1039 case MachineRepresentation::kWord64:
1027 shiftLeftOpcode = m->Word64Shl(); 1040 shiftLeftOpcode = m->Word64Shl();
1028 shiftRightOpcode = m->Word64Shr(); 1041 shiftRightOpcode = m->Word64Shr();
1029 andOpcode = m->Word64And(); 1042 andOpcode = m->Word64And();
1030 orOpcode = m->Word64Or(); 1043 orOpcode = m->Word64Or();
1031 result = jsgraph()->Int64Constant(0); 1044 result = jsgraph()->Int64Constant(0);
1032 break; 1045 break;
(...skipping 13 matching lines...) Expand all
1046 return node; 1059 return node;
1047 break; 1060 break;
1048 default: 1061 default:
1049 UNREACHABLE(); 1062 UNREACHABLE();
1050 break; 1063 break;
1051 } 1064 }
1052 1065
1053 int i; 1066 int i;
1054 uint32_t shiftCount; 1067 uint32_t shiftCount;
1055 1068
1056 for (i = 0, shiftCount = valueSizeInBits - 8; i < valueSizeInBits / 2; 1069 if (ReverseBytesSupported(m, valueSizeInBytes < 4 ? 4 : valueSizeInBytes)) {
1057 i += 8, shiftCount -= 16) { 1070 switch (valueSizeInBytes) {
1058 Node* shiftLower; 1071 case 1:
ahaas 2016/07/29 04:15:18 nit: you could remove this case, it should be unre
john.yan 2016/07/29 17:12:03 Done.
1059 Node* shiftHigher; 1072 break;
1060 Node* lowerByte; 1073 case 2:
1061 Node* higherByte; 1074 result =
1075 graph()->NewNode(m->Word32ReverseBytes().op(),
1076 graph()->NewNode(shiftLeftOpcode, value,
1077 jsgraph()->Int32Constant(16)));
1078 break;
1079 case 4:
1080 result = graph()->NewNode(m->Word32ReverseBytes().op(), value);
1081 break;
1082 case 8:
1083 result = graph()->NewNode(m->Word64ReverseBytes().op(), value);
1084 break;
1085 default:
1086 UNREACHABLE();
1087 }
1088 } else {
1089 for (i = 0, shiftCount = valueSizeInBits - 8; i < valueSizeInBits / 2;
1090 i += 8, shiftCount -= 16) {
1091 Node* shiftLower;
1092 Node* shiftHigher;
1093 Node* lowerByte;
1094 Node* higherByte;
1062 1095
1063 DCHECK(shiftCount > 0); 1096 DCHECK(shiftCount > 0);
1064 DCHECK((shiftCount + 8) % 16 == 0); 1097 DCHECK((shiftCount + 8) % 16 == 0);
1065 1098
1066 if (valueSizeInBits > 32) { 1099 if (valueSizeInBits > 32) {
1067 shiftLower = graph()->NewNode(shiftLeftOpcode, value, 1100 shiftLower = graph()->NewNode(shiftLeftOpcode, value,
1068 jsgraph()->Int64Constant(shiftCount)); 1101 jsgraph()->Int64Constant(shiftCount));
1069 shiftHigher = graph()->NewNode(shiftRightOpcode, value, 1102 shiftHigher = graph()->NewNode(shiftRightOpcode, value,
1070 jsgraph()->Int64Constant(shiftCount)); 1103 jsgraph()->Int64Constant(shiftCount));
1071 lowerByte = graph()->NewNode( 1104 lowerByte = graph()->NewNode(
1072 andOpcode, shiftLower, 1105 andOpcode, shiftLower,
1073 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) 1106 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF)
1074 << (valueSizeInBits - 8 - i))); 1107 << (valueSizeInBits - 8 - i)));
1075 higherByte = graph()->NewNode( 1108 higherByte = graph()->NewNode(
1076 andOpcode, shiftHigher, 1109 andOpcode, shiftHigher,
1077 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) << i)); 1110 jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) << i));
1078 } else { 1111 } else {
1079 shiftLower = graph()->NewNode(shiftLeftOpcode, value, 1112 shiftLower = graph()->NewNode(shiftLeftOpcode, value,
1080 jsgraph()->Int32Constant(shiftCount)); 1113 jsgraph()->Int32Constant(shiftCount));
1081 shiftHigher = graph()->NewNode(shiftRightOpcode, value, 1114 shiftHigher = graph()->NewNode(shiftRightOpcode, value,
1082 jsgraph()->Int32Constant(shiftCount)); 1115 jsgraph()->Int32Constant(shiftCount));
1083 lowerByte = graph()->NewNode( 1116 lowerByte = graph()->NewNode(
1084 andOpcode, shiftLower, 1117 andOpcode, shiftLower,
1085 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) 1118 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF)
1086 << (valueSizeInBits - 8 - i))); 1119 << (valueSizeInBits - 8 - i)));
1087 higherByte = graph()->NewNode( 1120 higherByte = graph()->NewNode(
1088 andOpcode, shiftHigher, 1121 andOpcode, shiftHigher,
1089 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) << i)); 1122 jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) << i));
1123 }
1124
1125 result = graph()->NewNode(orOpcode, result, lowerByte);
1126 result = graph()->NewNode(orOpcode, result, higherByte);
1090 } 1127 }
1091
1092 result = graph()->NewNode(orOpcode, result, lowerByte);
1093 result = graph()->NewNode(orOpcode, result, higherByte);
1094 } 1128 }
1095 1129
1096 if (isFloat) { 1130 if (isFloat) {
1097 switch (memtype.representation()) { 1131 switch (memtype.representation()) {
1098 case MachineRepresentation::kFloat64: 1132 case MachineRepresentation::kFloat64:
1099 result = graph()->NewNode(m->BitcastInt64ToFloat64(), result); 1133 result = graph()->NewNode(m->BitcastInt64ToFloat64(), result);
1100 break; 1134 break;
1101 case MachineRepresentation::kFloat32: 1135 case MachineRepresentation::kFloat32:
1102 result = graph()->NewNode(m->BitcastInt32ToFloat32(), result); 1136 result = graph()->NewNode(m->BitcastInt32ToFloat32(), result);
1103 break; 1137 break;
1104 default: 1138 default:
1105 UNREACHABLE(); 1139 UNREACHABLE();
1106 break; 1140 break;
1107 } 1141 }
1108 } 1142 }
1109 1143
1110 // We need to sign extend the value 1144 // We need to sign extend the value
1111 if (memtype.IsSigned()) { 1145 if (memtype.IsSigned()) {
1112 DCHECK(!isFloat); 1146 DCHECK(!isFloat);
1113 if (valueSizeInBits < 32) { 1147 if (valueSizeInBits < 32) {
1114 Node* shiftBitCount; 1148 Node* shiftBitCount;
1115 // Perform sign extension using following trick 1149 // Perform sign extension using following trick
1116 // result = (x << machine_width - type_width) >> (machine_width - 1150 // result = (x << machine_width - type_width) >> (machine_width -
1117 // type_width) 1151 // type_width)
1118 if (wasmtype == wasm::kAstI64) { 1152 if (wasmtype == wasm::kAstI64) {
1119 shiftBitCount = jsgraph()->Int32Constant(64 - valueSizeInBits); 1153 shiftBitCount = jsgraph()->Int32Constant(64 - valueSizeInBits);
1120 result = graph()->NewNode( 1154 result = graph()->NewNode(
1121 m->Word64Sar(), 1155 m->Word64Sar(),
1122 graph()->NewNode(m->Word64Shl(), result, shiftBitCount), 1156 graph()->NewNode(m->Word64Shl(),
1157 graph()->NewNode(m->ChangeInt32ToInt64(), result),
1158 shiftBitCount),
1123 shiftBitCount); 1159 shiftBitCount);
1124 } else if (wasmtype == wasm::kAstI32) { 1160 } else if (wasmtype == wasm::kAstI32) {
1125 shiftBitCount = jsgraph()->Int32Constant(32 - valueSizeInBits); 1161 shiftBitCount = jsgraph()->Int32Constant(32 - valueSizeInBits);
1126 result = graph()->NewNode( 1162 result = graph()->NewNode(
1127 m->Word32Sar(), 1163 m->Word32Sar(),
1128 graph()->NewNode(m->Word32Shl(), result, shiftBitCount), 1164 graph()->NewNode(m->Word32Shl(), result, shiftBitCount),
1129 shiftBitCount); 1165 shiftBitCount);
1130 } 1166 }
1131 } 1167 }
1132 } 1168 }
(...skipping 1942 matching lines...) Expand 10 before | Expand all | Expand 10 after
3075 3111
3076 if (aligned || 3112 if (aligned ||
3077 jsgraph()->machine()->UnalignedLoadSupported(memtype, alignment)) { 3113 jsgraph()->machine()->UnalignedLoadSupported(memtype, alignment)) {
3078 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), 3114 load = graph()->NewNode(jsgraph()->machine()->Load(memtype),
3079 MemBuffer(offset), index, *effect_, *control_); 3115 MemBuffer(offset), index, *effect_, *control_);
3080 *effect_ = load; 3116 *effect_ = load;
3081 } else { 3117 } else {
3082 load = BuildUnalignedLoad(type, memtype, index, offset, alignment); 3118 load = BuildUnalignedLoad(type, memtype, index, offset, alignment);
3083 } 3119 }
3084 #if defined(V8_TARGET_BIG_ENDIAN) 3120 #if defined(V8_TARGET_BIG_ENDIAN)
3085 // TODO(john.yan) Implement byte swap turbofan operator
3086 // and use it if available for better performance
3087 load = BuildChangeEndianness(load, memtype, type); 3121 load = BuildChangeEndianness(load, memtype, type);
3088 #endif 3122 #endif
3089 3123
3090 if (type == wasm::kAstI64 && 3124 if (type == wasm::kAstI64 &&
3091 ElementSizeLog2Of(memtype.representation()) < 3) { 3125 ElementSizeLog2Of(memtype.representation()) < 3) {
3092 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes. 3126 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes.
3093 if (memtype.IsSigned()) { 3127 if (memtype.IsSigned()) {
3094 // sign extend 3128 // sign extend
3095 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); 3129 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load);
3096 } else { 3130 } else {
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
3196 } 3230 }
3197 3231
3198 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, 3232 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index,
3199 uint32_t offset, uint32_t alignment, Node* val, 3233 uint32_t offset, uint32_t alignment, Node* val,
3200 wasm::WasmCodePosition position) { 3234 wasm::WasmCodePosition position) {
3201 Node* store; 3235 Node* store;
3202 3236
3203 // WASM semantics throw on OOB. Introduce explicit bounds check. 3237 // WASM semantics throw on OOB. Introduce explicit bounds check.
3204 BoundsCheckMem(memtype, index, offset, position); 3238 BoundsCheckMem(memtype, index, offset, position);
3205 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); 3239 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier);
3240
3206 bool aligned = static_cast<int>(alignment) >= 3241 bool aligned = static_cast<int>(alignment) >=
3207 ElementSizeLog2Of(memtype.representation()); 3242 ElementSizeLog2Of(memtype.representation());
3208 3243
3209 #if defined(V8_TARGET_BIG_ENDIAN) 3244 #if defined(V8_TARGET_BIG_ENDIAN)
3210 // TODO(john.yan) Implement byte swap turbofan operator
3211 // and use it if available for better performance
3212 val = BuildChangeEndianness(val, memtype); 3245 val = BuildChangeEndianness(val, memtype);
3213 #endif 3246 #endif
3214 3247
3215 if (aligned || 3248 if (aligned ||
3216 jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) { 3249 jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) {
3217 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); 3250 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier);
3218 store = 3251 store =
3219 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), 3252 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset),
3220 index, val, *effect_, *control_); 3253 index, val, *effect_, *control_);
3221 *effect_ = store; 3254 *effect_ = store;
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after
3661 function_->code_start_offset), 3694 function_->code_start_offset),
3662 compile_ms); 3695 compile_ms);
3663 } 3696 }
3664 3697
3665 return code; 3698 return code;
3666 } 3699 }
3667 3700
3668 } // namespace compiler 3701 } // namespace compiler
3669 } // namespace internal 3702 } // namespace internal
3670 } // namespace v8 3703 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698