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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 inputs[(*input_count)++] = UseImmediate(displacement); | 60 inputs[(*input_count)++] = UseImmediate(displacement); |
61 mode = kMode_MRI; | 61 mode = kMode_MRI; |
62 } | 62 } |
63 } | 63 } |
64 } else { | 64 } else { |
65 DCHECK(index != NULL); | 65 DCHECK(index != NULL); |
66 DCHECK(scale_exponent >= 0 && scale_exponent <= 3); | 66 DCHECK(scale_exponent >= 0 && scale_exponent <= 3); |
67 inputs[(*input_count)++] = UseRegister(index); | 67 inputs[(*input_count)++] = UseRegister(index); |
68 if (displacement != NULL) { | 68 if (displacement != NULL) { |
69 inputs[(*input_count)++] = UseImmediate(displacement); | 69 inputs[(*input_count)++] = UseImmediate(displacement); |
70 static const AddressingMode kMnI_modes[] = {kMode_M1I, kMode_M2I, | 70 static const AddressingMode kMnI_modes[] = {kMode_MRI, kMode_M2I, |
71 kMode_M4I, kMode_M8I}; | 71 kMode_M4I, kMode_M8I}; |
72 mode = kMnI_modes[scale_exponent]; | 72 mode = kMnI_modes[scale_exponent]; |
73 } else { | 73 } else { |
74 static const AddressingMode kMn_modes[] = {kMode_M1, kMode_MR1, | 74 static const AddressingMode kMn_modes[] = {kMode_MR, kMode_MR1, |
75 kMode_M4, kMode_M8}; | 75 kMode_M4, kMode_M8}; |
76 mode = kMn_modes[scale_exponent]; | 76 mode = kMn_modes[scale_exponent]; |
77 if (mode == kMode_MR1) { | 77 if (mode == kMode_MR1) { |
78 // [%r1 + %r1*1] has a smaller encoding than [%r1*2+0] | 78 // [%r1 + %r1*1] has a smaller encoding than [%r1*2+0] |
79 inputs[(*input_count)++] = UseRegister(index); | 79 inputs[(*input_count)++] = UseRegister(index); |
80 } | 80 } |
81 } | 81 } |
82 } | 82 } |
83 return mode; | 83 return mode; |
84 } | 84 } |
85 | 85 |
| 86 AddressingMode GetEffectiveAddressMemoryOperand(Node* operand, |
| 87 InstructionOperand* inputs[], |
| 88 size_t* input_count) { |
| 89 BaseWithIndexAndDisplacement64Matcher m(operand, true); |
| 90 DCHECK(m.matches()); |
| 91 if ((m.displacement() == NULL || CanBeImmediate(m.displacement()))) { |
| 92 return GenerateMemoryOperandInputs(m.index(), m.scale(), m.base(), |
| 93 m.displacement(), inputs, input_count); |
| 94 } else { |
| 95 inputs[(*input_count)++] = UseRegister(operand->InputAt(0)); |
| 96 inputs[(*input_count)++] = UseRegister(operand->InputAt(1)); |
| 97 return kMode_MR1; |
| 98 } |
| 99 } |
| 100 |
86 bool CanBeBetterLeftOperand(Node* node) const { | 101 bool CanBeBetterLeftOperand(Node* node) const { |
87 return !selector()->IsLive(node); | 102 return !selector()->IsLive(node); |
88 } | 103 } |
89 }; | 104 }; |
90 | 105 |
91 | 106 |
92 void InstructionSelector::VisitLoad(Node* node) { | 107 void InstructionSelector::VisitLoad(Node* node) { |
93 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); | 108 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); |
94 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); | 109 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); |
95 X64OperandGenerator g(this); | 110 X64OperandGenerator g(this); |
96 Node* const base = node->InputAt(0); | |
97 Node* const index = node->InputAt(1); | |
98 | 111 |
99 ArchOpcode opcode; | 112 ArchOpcode opcode; |
100 switch (rep) { | 113 switch (rep) { |
101 case kRepFloat32: | 114 case kRepFloat32: |
102 opcode = kX64Movss; | 115 opcode = kX64Movss; |
103 break; | 116 break; |
104 case kRepFloat64: | 117 case kRepFloat64: |
105 opcode = kX64Movsd; | 118 opcode = kX64Movsd; |
106 break; | 119 break; |
107 case kRepBit: // Fall through. | 120 case kRepBit: // Fall through. |
108 case kRepWord8: | 121 case kRepWord8: |
109 opcode = typ == kTypeInt32 ? kX64Movsxbl : kX64Movzxbl; | 122 opcode = typ == kTypeInt32 ? kX64Movsxbl : kX64Movzxbl; |
110 break; | 123 break; |
111 case kRepWord16: | 124 case kRepWord16: |
112 opcode = typ == kTypeInt32 ? kX64Movsxwl : kX64Movzxwl; | 125 opcode = typ == kTypeInt32 ? kX64Movsxwl : kX64Movzxwl; |
113 break; | 126 break; |
114 case kRepWord32: | 127 case kRepWord32: |
115 opcode = kX64Movl; | 128 opcode = kX64Movl; |
116 break; | 129 break; |
117 case kRepTagged: // Fall through. | 130 case kRepTagged: // Fall through. |
118 case kRepWord64: | 131 case kRepWord64: |
119 opcode = kX64Movq; | 132 opcode = kX64Movq; |
120 break; | 133 break; |
121 default: | 134 default: |
122 UNREACHABLE(); | 135 UNREACHABLE(); |
123 return; | 136 return; |
124 } | 137 } |
125 if (g.CanBeImmediate(index)) { | 138 |
126 // load [%base + #index] | 139 InstructionOperand* outputs[1]; |
127 Emit(opcode | AddressingModeField::encode(kMode_MRI), | 140 outputs[0] = g.DefineAsRegister(node); |
128 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); | 141 InstructionOperand* inputs[3]; |
129 } else if (g.CanBeImmediate(base)) { | 142 size_t input_count = 0; |
130 // load [#base + %index] | 143 AddressingMode mode = |
131 Emit(opcode | AddressingModeField::encode(kMode_MRI), | 144 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); |
132 g.DefineAsRegister(node), g.UseRegister(index), g.UseImmediate(base)); | 145 InstructionCode code = opcode | AddressingModeField::encode(mode); |
133 } else { | 146 Emit(code, 1, outputs, input_count, inputs); |
134 // load [%base + %index*1] | |
135 Emit(opcode | AddressingModeField::encode(kMode_MR1), | |
136 g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index)); | |
137 } | |
138 } | 147 } |
139 | 148 |
140 | 149 |
141 void InstructionSelector::VisitStore(Node* node) { | 150 void InstructionSelector::VisitStore(Node* node) { |
142 X64OperandGenerator g(this); | 151 X64OperandGenerator g(this); |
143 Node* base = node->InputAt(0); | 152 Node* base = node->InputAt(0); |
144 Node* index = node->InputAt(1); | 153 Node* index = node->InputAt(1); |
145 Node* value = node->InputAt(2); | 154 Node* value = node->InputAt(2); |
146 | 155 |
147 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); | 156 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); |
(...skipping 29 matching lines...) Expand all Loading... |
177 opcode = kX64Movl; | 186 opcode = kX64Movl; |
178 break; | 187 break; |
179 case kRepTagged: // Fall through. | 188 case kRepTagged: // Fall through. |
180 case kRepWord64: | 189 case kRepWord64: |
181 opcode = kX64Movq; | 190 opcode = kX64Movq; |
182 break; | 191 break; |
183 default: | 192 default: |
184 UNREACHABLE(); | 193 UNREACHABLE(); |
185 return; | 194 return; |
186 } | 195 } |
| 196 InstructionOperand* inputs[4]; |
| 197 size_t input_count = 0; |
| 198 AddressingMode mode = |
| 199 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); |
| 200 InstructionCode code = opcode | AddressingModeField::encode(mode); |
187 InstructionOperand* value_operand = | 201 InstructionOperand* value_operand = |
188 g.CanBeImmediate(value) ? g.UseImmediate(value) : g.UseRegister(value); | 202 g.CanBeImmediate(value) ? g.UseImmediate(value) : g.UseRegister(value); |
189 if (g.CanBeImmediate(index)) { | 203 inputs[input_count++] = value_operand; |
190 // store [%base + #index], %|#value | 204 Emit(code, 0, static_cast<InstructionOperand**>(NULL), input_count, inputs); |
191 Emit(opcode | AddressingModeField::encode(kMode_MRI), nullptr, | |
192 g.UseRegister(base), g.UseImmediate(index), value_operand); | |
193 } else if (g.CanBeImmediate(base)) { | |
194 // store [#base + %index], %|#value | |
195 Emit(opcode | AddressingModeField::encode(kMode_MRI), nullptr, | |
196 g.UseRegister(index), g.UseImmediate(base), value_operand); | |
197 } else { | |
198 // store [%base + %index*1], %|#value | |
199 Emit(opcode | AddressingModeField::encode(kMode_MR1), nullptr, | |
200 g.UseRegister(base), g.UseRegister(index), value_operand); | |
201 } | |
202 } | 205 } |
203 | 206 |
204 | 207 |
205 void InstructionSelector::VisitCheckedLoad(Node* node) { | 208 void InstructionSelector::VisitCheckedLoad(Node* node) { |
206 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); | 209 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); |
207 MachineType typ = TypeOf(OpParameter<MachineType>(node)); | 210 MachineType typ = TypeOf(OpParameter<MachineType>(node)); |
208 X64OperandGenerator g(this); | 211 X64OperandGenerator g(this); |
209 Node* const buffer = node->InputAt(0); | 212 Node* const buffer = node->InputAt(0); |
210 Node* const offset = node->InputAt(1); | 213 Node* const offset = node->InputAt(1); |
211 Node* const length = node->InputAt(2); | 214 Node* const length = node->InputAt(2); |
(...skipping 1102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1314 MachineOperatorBuilder::kFloat64Ceil | | 1317 MachineOperatorBuilder::kFloat64Ceil | |
1315 MachineOperatorBuilder::kFloat64RoundTruncate | | 1318 MachineOperatorBuilder::kFloat64RoundTruncate | |
1316 MachineOperatorBuilder::kWord32ShiftIsSafe; | 1319 MachineOperatorBuilder::kWord32ShiftIsSafe; |
1317 } | 1320 } |
1318 return MachineOperatorBuilder::kNoFlags; | 1321 return MachineOperatorBuilder::kNoFlags; |
1319 } | 1322 } |
1320 | 1323 |
1321 } // namespace compiler | 1324 } // namespace compiler |
1322 } // namespace internal | 1325 } // namespace internal |
1323 } // namespace v8 | 1326 } // namespace v8 |
OLD | NEW |