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

Side by Side Diff: src/compiler/ia32/instruction-selector-ia32.cc

Issue 613643002: [turbofan] add new ia32 addressing modes (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 2 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 | Annotate | Revision Log
OLDNEW
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 #include "src/compiler/node-properties-inl.h" 7 #include "src/compiler/node-properties-inl.h"
8 8
9 namespace v8 { 9 namespace v8 {
10 namespace internal { 10 namespace internal {
(...skipping 26 matching lines...) Expand all
37 return false; 37 return false;
38 } 38 }
39 } 39 }
40 40
41 bool CanBeBetterLeftOperand(Node* node) const { 41 bool CanBeBetterLeftOperand(Node* node) const {
42 return !selector()->IsLive(node); 42 return !selector()->IsLive(node);
43 } 43 }
44 }; 44 };
45 45
46 46
47 class AddressingModeMatcher {
48 public:
49 AddressingModeMatcher(IA32OperandGenerator* g, Node* base, Node* index)
50 : base_operand_(NULL),
51 index_operand_(NULL),
52 displacement_operand_(NULL),
53 mode_(kMode_None) {
54 Int32Matcher index_imm(index);
55 if (index_imm.HasValue()) {
56 int32_t displacement = index_imm.Value();
57 // Compute base operand and fold base immediate into displacement.
58 Int32Matcher base_imm(base);
59 if (!base_imm.HasValue()) {
60 base_operand_ = g->UseRegister(base);
61 } else {
62 displacement += base_imm.Value();
63 }
64 if (displacement != 0 || base_operand_ == NULL) {
65 displacement_operand_ = g->TempImmediate(displacement);
66 }
67 if (base_operand_ == NULL) {
68 mode_ = kMode_MI;
69 } else {
70 if (displacement == 0) {
71 mode_ = kMode_MR;
72 } else {
73 mode_ = kMode_MRI;
74 }
75 }
76 } else {
77 // Compute index and displacement.
78 IndexAndDisplacementMatcher matcher(index);
79 index_operand_ = g->UseRegister(matcher.index_node());
80 int32_t displacement = matcher.displacement();
81 // Compute base operand and fold base immediate into displacement.
82 Int32Matcher base_imm(base);
83 if (!base_imm.HasValue()) {
84 base_operand_ = g->UseRegister(base);
85 } else {
86 displacement += base_imm.Value();
87 }
88 // Compute displacement operand.
89 if (displacement != 0) {
90 displacement_operand_ = g->TempImmediate(displacement);
91 }
92 // Compute mode with scale factor one.
93 if (base_operand_ == NULL) {
94 if (displacement_operand_ == NULL) {
95 mode_ = kMode_M1;
96 } else {
97 mode_ = kMode_M1I;
98 }
99 } else {
100 if (displacement_operand_ == NULL) {
101 mode_ = kMode_MR1;
102 } else {
103 mode_ = kMode_MR1I;
104 }
105 }
106 // Adjust mode to actual scale factor.
107 mode_ = GetMode(mode_, matcher.power());
108 // Don't emit instructions with scale factor 1 if there's no base.
109 if (mode_ == kMode_M1) {
110 mode_ = kMode_MR;
111 } else if (mode_ == kMode_M1I) {
112 mode_ = kMode_MRI;
113 }
114 }
115 DCHECK_NE(kMode_None, mode_);
116 }
117
118 AddressingMode GetMode(AddressingMode one, int power) {
119 return static_cast<AddressingMode>(static_cast<int>(one) + power);
120 }
121
122 size_t SetInputs(InstructionOperand** inputs) {
123 size_t input_count = 0;
124 // Compute inputs_ and input_count.
125 if (base_operand_ != NULL) {
126 inputs[input_count++] = base_operand_;
127 }
128 if (index_operand_ != NULL) {
129 inputs[input_count++] = index_operand_;
130 }
131 if (displacement_operand_ != NULL) {
132 inputs[input_count++] = displacement_operand_;
133 }
134 DCHECK_NE(input_count, 0);
135 return input_count;
136 }
137
138 static const int kMaxInputCount = 3;
139 InstructionOperand* base_operand_;
140 InstructionOperand* index_operand_;
141 InstructionOperand* displacement_operand_;
142 AddressingMode mode_;
143 };
144
145
47 void InstructionSelector::VisitLoad(Node* node) { 146 void InstructionSelector::VisitLoad(Node* node) {
48 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); 147 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node));
49 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); 148 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node));
50 IA32OperandGenerator g(this);
51 Node* base = node->InputAt(0); 149 Node* base = node->InputAt(0);
52 Node* index = node->InputAt(1); 150 Node* index = node->InputAt(1);
53 151
54 ArchOpcode opcode; 152 ArchOpcode opcode;
55 // TODO(titzer): signed/unsigned small loads 153 // TODO(titzer): signed/unsigned small loads
56 switch (rep) { 154 switch (rep) {
57 case kRepFloat32: 155 case kRepFloat32:
58 opcode = kIA32Movss; 156 opcode = kIA32Movss;
59 break; 157 break;
60 case kRepFloat64: 158 case kRepFloat64:
61 opcode = kIA32Movsd; 159 opcode = kIA32Movsd;
62 break; 160 break;
63 case kRepBit: // Fall through. 161 case kRepBit: // Fall through.
64 case kRepWord8: 162 case kRepWord8:
65 opcode = typ == kTypeInt32 ? kIA32Movsxbl : kIA32Movzxbl; 163 opcode = typ == kTypeInt32 ? kIA32Movsxbl : kIA32Movzxbl;
66 break; 164 break;
67 case kRepWord16: 165 case kRepWord16:
68 opcode = typ == kTypeInt32 ? kIA32Movsxwl : kIA32Movzxwl; 166 opcode = typ == kTypeInt32 ? kIA32Movsxwl : kIA32Movzxwl;
69 break; 167 break;
70 case kRepTagged: // Fall through. 168 case kRepTagged: // Fall through.
71 case kRepWord32: 169 case kRepWord32:
72 opcode = kIA32Movl; 170 opcode = kIA32Movl;
73 break; 171 break;
74 default: 172 default:
75 UNREACHABLE(); 173 UNREACHABLE();
76 return; 174 return;
77 } 175 }
78 if (g.CanBeImmediate(base)) { 176
79 if (Int32Matcher(index).Is(0)) { // load [#base + #0] 177 IA32OperandGenerator g(this);
80 Emit(opcode | AddressingModeField::encode(kMode_MI), 178 AddressingModeMatcher matcher(&g, base, index);
81 g.DefineAsRegister(node), g.UseImmediate(base)); 179 InstructionCode code = opcode | AddressingModeField::encode(matcher.mode_);
82 } else { // load [#base + %index] 180 InstructionOperand* outputs[] = {g.DefineAsRegister(node)};
83 Emit(opcode | AddressingModeField::encode(kMode_MRI), 181 InstructionOperand* inputs[AddressingModeMatcher::kMaxInputCount];
84 g.DefineAsRegister(node), g.UseRegister(index), 182 size_t input_count = matcher.SetInputs(inputs);
85 g.UseImmediate(base)); 183 Emit(code, 1, outputs, input_count, inputs);
86 }
87 } else if (g.CanBeImmediate(index)) { // load [%base + #index]
88 Emit(opcode | AddressingModeField::encode(kMode_MRI),
89 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index));
90 } else { // load [%base + %index + K]
91 Emit(opcode | AddressingModeField::encode(kMode_MR1I),
92 g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
93 }
94 // TODO(turbofan): addressing modes [r+r*{2,4,8}+K]
95 } 184 }
96 185
97 186
98 void InstructionSelector::VisitStore(Node* node) { 187 void InstructionSelector::VisitStore(Node* node) {
99 IA32OperandGenerator g(this); 188 IA32OperandGenerator g(this);
100 Node* base = node->InputAt(0); 189 Node* base = node->InputAt(0);
101 Node* index = node->InputAt(1); 190 Node* index = node->InputAt(1);
102 Node* value = node->InputAt(2); 191 Node* value = node->InputAt(2);
103 192
104 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); 193 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node);
105 MachineType rep = RepresentationOf(store_rep.machine_type()); 194 MachineType rep = RepresentationOf(store_rep.machine_type());
106 if (store_rep.write_barrier_kind() == kFullWriteBarrier) { 195 if (store_rep.write_barrier_kind() == kFullWriteBarrier) {
107 DCHECK_EQ(kRepTagged, rep); 196 DCHECK_EQ(kRepTagged, rep);
108 // TODO(dcarney): refactor RecordWrite function to take temp registers 197 // TODO(dcarney): refactor RecordWrite function to take temp registers
109 // and pass them here instead of using fixed regs 198 // and pass them here instead of using fixed regs
110 // TODO(dcarney): handle immediate indices. 199 // TODO(dcarney): handle immediate indices.
111 InstructionOperand* temps[] = {g.TempRegister(ecx), g.TempRegister(edx)}; 200 InstructionOperand* temps[] = {g.TempRegister(ecx), g.TempRegister(edx)};
112 Emit(kIA32StoreWriteBarrier, NULL, g.UseFixed(base, ebx), 201 Emit(kIA32StoreWriteBarrier, NULL, g.UseFixed(base, ebx),
113 g.UseFixed(index, ecx), g.UseFixed(value, edx), arraysize(temps), 202 g.UseFixed(index, ecx), g.UseFixed(value, edx), arraysize(temps),
114 temps); 203 temps);
115 return; 204 return;
116 } 205 }
117 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind()); 206 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind());
118 InstructionOperand* val; 207
119 if (g.CanBeImmediate(value)) {
120 val = g.UseImmediate(value);
121 } else if (rep == kRepWord8 || rep == kRepBit) {
122 val = g.UseByteRegister(value);
123 } else {
124 val = g.UseRegister(value);
125 }
126 ArchOpcode opcode; 208 ArchOpcode opcode;
127 switch (rep) { 209 switch (rep) {
128 case kRepFloat32: 210 case kRepFloat32:
129 opcode = kIA32Movss; 211 opcode = kIA32Movss;
130 break; 212 break;
131 case kRepFloat64: 213 case kRepFloat64:
132 opcode = kIA32Movsd; 214 opcode = kIA32Movsd;
133 break; 215 break;
134 case kRepBit: // Fall through. 216 case kRepBit: // Fall through.
135 case kRepWord8: 217 case kRepWord8:
136 opcode = kIA32Movb; 218 opcode = kIA32Movb;
137 break; 219 break;
138 case kRepWord16: 220 case kRepWord16:
139 opcode = kIA32Movw; 221 opcode = kIA32Movw;
140 break; 222 break;
141 case kRepTagged: // Fall through. 223 case kRepTagged: // Fall through.
142 case kRepWord32: 224 case kRepWord32:
143 opcode = kIA32Movl; 225 opcode = kIA32Movl;
144 break; 226 break;
145 default: 227 default:
146 UNREACHABLE(); 228 UNREACHABLE();
147 return; 229 return;
148 } 230 }
149 if (g.CanBeImmediate(base)) { 231
150 if (Int32Matcher(index).Is(0)) { // store [#base], %|#value 232 InstructionOperand* val;
151 Emit(opcode | AddressingModeField::encode(kMode_MI), NULL, 233 if (g.CanBeImmediate(value)) {
152 g.UseImmediate(base), val); 234 val = g.UseImmediate(value);
153 } else { // store [#base + %index], %|#value 235 } else if (rep == kRepWord8 || rep == kRepBit) {
154 Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL, 236 val = g.UseByteRegister(value);
155 g.UseRegister(index), g.UseImmediate(base), val); 237 } else {
156 } 238 val = g.UseRegister(value);
157 } else if (g.CanBeImmediate(index)) { // store [%base + #index], %|#value
158 Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL,
159 g.UseRegister(base), g.UseImmediate(index), val);
160 } else { // store [%base + %index], %|#value
161 Emit(opcode | AddressingModeField::encode(kMode_MR1I), NULL,
162 g.UseRegister(base), g.UseRegister(index), val);
163 } 239 }
164 // TODO(turbofan): addressing modes [r+r*{2,4,8}+K] 240
241 AddressingModeMatcher matcher(&g, base, index);
242 InstructionCode code = opcode | AddressingModeField::encode(matcher.mode_);
243 InstructionOperand* inputs[AddressingModeMatcher::kMaxInputCount + 1];
244 size_t input_count = matcher.SetInputs(inputs);
245 inputs[input_count++] = val;
246 Emit(code, 0, static_cast<InstructionOperand**>(NULL), input_count, inputs);
165 } 247 }
166 248
167 249
168 // Shared routine for multiple binary operations. 250 // Shared routine for multiple binary operations.
169 static void VisitBinop(InstructionSelector* selector, Node* node, 251 static void VisitBinop(InstructionSelector* selector, Node* node,
170 InstructionCode opcode, FlagsContinuation* cont) { 252 InstructionCode opcode, FlagsContinuation* cont) {
171 IA32OperandGenerator g(selector); 253 IA32OperandGenerator g(selector);
172 Int32BinopMatcher m(node); 254 Int32BinopMatcher m(node);
173 Node* left = m.left().node(); 255 Node* left = m.left().node();
174 Node* right = m.right().node(); 256 Node* right = m.right().node();
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 call_instr->MarkAsCall(); 658 call_instr->MarkAsCall();
577 if (deoptimization != NULL) { 659 if (deoptimization != NULL) {
578 DCHECK(continuation != NULL); 660 DCHECK(continuation != NULL);
579 call_instr->MarkAsControl(); 661 call_instr->MarkAsControl();
580 } 662 }
581 } 663 }
582 664
583 } // namespace compiler 665 } // namespace compiler
584 } // namespace internal 666 } // namespace internal
585 } // namespace v8 667 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/ia32/instruction-codes-ia32.h ('k') | src/compiler/ia32/instruction-selector-ia32-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698