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 |