| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/instruction-selector-impl.h" | 5 #include "src/compiler/instruction-selector-impl.h" |
| 6 #include "src/compiler/node-matchers.h" | 6 #include "src/compiler/node-matchers.h" |
| 7 | 7 |
| 8 namespace v8 { | 8 namespace v8 { |
| 9 namespace internal { | 9 namespace internal { |
| 10 namespace compiler { | 10 namespace compiler { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 opcode = kX64Movl; | 65 opcode = kX64Movl; |
| 66 break; | 66 break; |
| 67 case kRepTagged: // Fall through. | 67 case kRepTagged: // Fall through. |
| 68 case kRepWord64: | 68 case kRepWord64: |
| 69 opcode = kX64Movq; | 69 opcode = kX64Movq; |
| 70 break; | 70 break; |
| 71 default: | 71 default: |
| 72 UNREACHABLE(); | 72 UNREACHABLE(); |
| 73 return; | 73 return; |
| 74 } | 74 } |
| 75 if (g.CanBeImmediate(base)) { | 75 if (g.CanBeImmediate(index)) { |
| 76 // load [%base + #index] |
| 77 Emit(opcode | AddressingModeField::encode(kMode_MRI), |
| 78 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); |
| 79 } else if (g.CanBeImmediate(base)) { |
| 76 // load [#base + %index] | 80 // load [#base + %index] |
| 77 Emit(opcode | AddressingModeField::encode(kMode_MRI), | 81 Emit(opcode | AddressingModeField::encode(kMode_MRI), |
| 78 g.DefineAsRegister(node), g.UseRegister(index), g.UseImmediate(base)); | 82 g.DefineAsRegister(node), g.UseRegister(index), g.UseImmediate(base)); |
| 79 } else if (g.CanBeImmediate(index)) { | |
| 80 // load [%base + #index] | |
| 81 Emit(opcode | AddressingModeField::encode(kMode_MRI), | |
| 82 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); | |
| 83 } else { | 83 } else { |
| 84 // load [%base + %index*1] | 84 // load [%base + %index*1] |
| 85 Emit(opcode | AddressingModeField::encode(kMode_MR1), | 85 Emit(opcode | AddressingModeField::encode(kMode_MR1), |
| 86 g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index)); | 86 g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index)); |
| 87 } | 87 } |
| 88 } | 88 } |
| 89 | 89 |
| 90 | 90 |
| 91 void InstructionSelector::VisitStore(Node* node) { | 91 void InstructionSelector::VisitStore(Node* node) { |
| 92 X64OperandGenerator g(this); | 92 X64OperandGenerator g(this); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 case kRepTagged: // Fall through. | 129 case kRepTagged: // Fall through. |
| 130 case kRepWord64: | 130 case kRepWord64: |
| 131 opcode = kX64Movq; | 131 opcode = kX64Movq; |
| 132 break; | 132 break; |
| 133 default: | 133 default: |
| 134 UNREACHABLE(); | 134 UNREACHABLE(); |
| 135 return; | 135 return; |
| 136 } | 136 } |
| 137 InstructionOperand* value_operand = | 137 InstructionOperand* value_operand = |
| 138 g.CanBeImmediate(value) ? g.UseImmediate(value) : g.UseRegister(value); | 138 g.CanBeImmediate(value) ? g.UseImmediate(value) : g.UseRegister(value); |
| 139 if (g.CanBeImmediate(base)) { | 139 if (g.CanBeImmediate(index)) { |
| 140 // store [%base + #index], %|#value |
| 141 Emit(opcode | AddressingModeField::encode(kMode_MRI), nullptr, |
| 142 g.UseRegister(base), g.UseImmediate(index), value_operand); |
| 143 } else if (g.CanBeImmediate(base)) { |
| 140 // store [#base + %index], %|#value | 144 // store [#base + %index], %|#value |
| 141 Emit(opcode | AddressingModeField::encode(kMode_MRI), nullptr, | 145 Emit(opcode | AddressingModeField::encode(kMode_MRI), nullptr, |
| 142 g.UseRegister(index), g.UseImmediate(base), value_operand); | 146 g.UseRegister(index), g.UseImmediate(base), value_operand); |
| 143 } else if (g.CanBeImmediate(index)) { | |
| 144 // store [%base + #index], %|#value | |
| 145 Emit(opcode | AddressingModeField::encode(kMode_MRI), nullptr, | |
| 146 g.UseRegister(base), g.UseImmediate(index), value_operand); | |
| 147 } else { | 147 } else { |
| 148 // store [%base + %index*1], %|#value | 148 // store [%base + %index*1], %|#value |
| 149 Emit(opcode | AddressingModeField::encode(kMode_MR1), nullptr, | 149 Emit(opcode | AddressingModeField::encode(kMode_MR1), nullptr, |
| 150 g.UseRegister(base), g.UseRegister(index), value_operand); | 150 g.UseRegister(base), g.UseRegister(index), value_operand); |
| 151 } | 151 } |
| 152 } | 152 } |
| 153 | 153 |
| 154 | 154 |
| 155 void InstructionSelector::VisitCheckedLoad(Node* node) { |
| 156 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); |
| 157 MachineType typ = TypeOf(OpParameter<MachineType>(node)); |
| 158 X64OperandGenerator g(this); |
| 159 Node* const buffer = node->InputAt(0); |
| 160 Node* const offset = node->InputAt(1); |
| 161 Node* const length = node->InputAt(2); |
| 162 ArchOpcode opcode; |
| 163 switch (rep) { |
| 164 case kRepWord8: |
| 165 opcode = typ == kTypeInt32 ? kCheckedLoadInt8 : kCheckedLoadUint8; |
| 166 break; |
| 167 case kRepWord16: |
| 168 opcode = typ == kTypeInt32 ? kCheckedLoadInt16 : kCheckedLoadUint16; |
| 169 break; |
| 170 case kRepWord32: |
| 171 opcode = kCheckedLoadWord32; |
| 172 break; |
| 173 case kRepFloat32: |
| 174 opcode = kCheckedLoadFloat32; |
| 175 break; |
| 176 case kRepFloat64: |
| 177 opcode = kCheckedLoadFloat64; |
| 178 break; |
| 179 default: |
| 180 UNREACHABLE(); |
| 181 return; |
| 182 } |
| 183 if (offset->opcode() == IrOpcode::kInt32Add && CanCover(node, offset)) { |
| 184 Int32Matcher mlength(length); |
| 185 Int32BinopMatcher moffset(offset); |
| 186 if (mlength.HasValue() && moffset.right().HasValue() && |
| 187 mlength.Value() > moffset.right().Value()) { |
| 188 InstructionOperand* offset_operand = g.UseRegister(moffset.left().node()); |
| 189 InstructionOperand* length_operand = |
| 190 g.TempImmediate(mlength.Value() - moffset.right().Value()); |
| 191 Emit(opcode | AddressingModeField::encode(kMode_MR1I), |
| 192 g.DefineAsRegister(node), offset_operand, length_operand, |
| 193 g.UseRegister(buffer), offset_operand, |
| 194 g.UseImmediate(moffset.right().node())); |
| 195 return; |
| 196 } |
| 197 } |
| 198 InstructionOperand* offset_operand = g.UseRegister(offset); |
| 199 InstructionOperand* length_operand = |
| 200 g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length); |
| 201 Emit(opcode | AddressingModeField::encode(kMode_MR1), |
| 202 g.DefineAsRegister(node), offset_operand, length_operand, |
| 203 g.UseRegister(buffer), offset_operand); |
| 204 } |
| 205 |
| 206 |
| 207 void InstructionSelector::VisitCheckedStore(Node* node) { |
| 208 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); |
| 209 X64OperandGenerator g(this); |
| 210 Node* const buffer = node->InputAt(0); |
| 211 Node* const offset = node->InputAt(1); |
| 212 Node* const length = node->InputAt(2); |
| 213 Node* const value = node->InputAt(3); |
| 214 ArchOpcode opcode; |
| 215 switch (rep) { |
| 216 case kRepWord8: |
| 217 opcode = kCheckedStoreWord8; |
| 218 break; |
| 219 case kRepWord16: |
| 220 opcode = kCheckedStoreWord16; |
| 221 break; |
| 222 case kRepWord32: |
| 223 opcode = kCheckedStoreWord32; |
| 224 break; |
| 225 case kRepFloat32: |
| 226 opcode = kCheckedStoreFloat32; |
| 227 break; |
| 228 case kRepFloat64: |
| 229 opcode = kCheckedStoreFloat64; |
| 230 break; |
| 231 default: |
| 232 UNREACHABLE(); |
| 233 return; |
| 234 } |
| 235 InstructionOperand* value_operand = |
| 236 g.CanBeImmediate(value) ? g.UseImmediate(value) : g.UseRegister(value); |
| 237 if (offset->opcode() == IrOpcode::kInt32Add && CanCover(node, offset)) { |
| 238 Int32Matcher mlength(length); |
| 239 Int32BinopMatcher moffset(offset); |
| 240 if (mlength.HasValue() && moffset.right().HasValue() && |
| 241 mlength.Value() > moffset.right().Value()) { |
| 242 InstructionOperand* offset_operand = g.UseRegister(moffset.left().node()); |
| 243 InstructionOperand* length_operand = |
| 244 g.TempImmediate(mlength.Value() - moffset.right().Value()); |
| 245 Emit(opcode | AddressingModeField::encode(kMode_MR1I), nullptr, |
| 246 offset_operand, length_operand, value_operand, g.UseRegister(buffer), |
| 247 offset_operand, g.UseImmediate(moffset.right().node())); |
| 248 return; |
| 249 } |
| 250 } |
| 251 InstructionOperand* offset_operand = g.UseRegister(offset); |
| 252 InstructionOperand* length_operand = |
| 253 g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length); |
| 254 Emit(opcode | AddressingModeField::encode(kMode_MR1), nullptr, offset_operand, |
| 255 length_operand, value_operand, g.UseRegister(buffer), offset_operand); |
| 256 } |
| 257 |
| 258 |
| 155 // Shared routine for multiple binary operations. | 259 // Shared routine for multiple binary operations. |
| 156 static void VisitBinop(InstructionSelector* selector, Node* node, | 260 static void VisitBinop(InstructionSelector* selector, Node* node, |
| 157 InstructionCode opcode, FlagsContinuation* cont) { | 261 InstructionCode opcode, FlagsContinuation* cont) { |
| 158 X64OperandGenerator g(selector); | 262 X64OperandGenerator g(selector); |
| 159 Int32BinopMatcher m(node); | 263 Int32BinopMatcher m(node); |
| 160 Node* left = m.left().node(); | 264 Node* left = m.left().node(); |
| 161 Node* right = m.right().node(); | 265 Node* right = m.right().node(); |
| 162 InstructionOperand* inputs[4]; | 266 InstructionOperand* inputs[4]; |
| 163 size_t input_count = 0; | 267 size_t input_count = 0; |
| 164 InstructionOperand* outputs[2]; | 268 InstructionOperand* outputs[2]; |
| (...skipping 1024 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1189 MachineOperatorBuilder::kFloat64Ceil | | 1293 MachineOperatorBuilder::kFloat64Ceil | |
| 1190 MachineOperatorBuilder::kFloat64RoundTruncate | | 1294 MachineOperatorBuilder::kFloat64RoundTruncate | |
| 1191 MachineOperatorBuilder::kWord32ShiftIsSafe; | 1295 MachineOperatorBuilder::kWord32ShiftIsSafe; |
| 1192 } | 1296 } |
| 1193 return MachineOperatorBuilder::kNoFlags; | 1297 return MachineOperatorBuilder::kNoFlags; |
| 1194 } | 1298 } |
| 1195 | 1299 |
| 1196 } // namespace compiler | 1300 } // namespace compiler |
| 1197 } // namespace internal | 1301 } // namespace internal |
| 1198 } // namespace v8 | 1302 } // namespace v8 |
| OLD | NEW |