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

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

Issue 2472703002: MIPS[64]: Use immediate constants in Add, And, Or and Xor instructions in turbofan (Closed)
Patch Set: Created 4 years, 1 month 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
« no previous file with comments | « no previous file | src/compiler/mips64/instruction-selector-mips64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/base/adapters.h" 5 #include "src/base/adapters.h"
6 #include "src/base/bits.h" 6 #include "src/base/bits.h"
7 #include "src/compiler/instruction-selector-impl.h" 7 #include "src/compiler/instruction-selector-impl.h"
8 #include "src/compiler/node-matchers.h" 8 #include "src/compiler/node-matchers.h"
9 #include "src/compiler/node-properties.h" 9 #include "src/compiler/node-properties.h"
10 10
(...skipping 22 matching lines...) Expand all
33 33
34 bool CanBeImmediate(Node* node, InstructionCode opcode) { 34 bool CanBeImmediate(Node* node, InstructionCode opcode) {
35 Int32Matcher m(node); 35 Int32Matcher m(node);
36 if (!m.HasValue()) return false; 36 if (!m.HasValue()) return false;
37 int32_t value = m.Value(); 37 int32_t value = m.Value();
38 switch (ArchOpcodeField::decode(opcode)) { 38 switch (ArchOpcodeField::decode(opcode)) {
39 case kMipsShl: 39 case kMipsShl:
40 case kMipsSar: 40 case kMipsSar:
41 case kMipsShr: 41 case kMipsShr:
42 return is_uint5(value); 42 return is_uint5(value);
43 case kMipsAdd:
44 case kMipsAnd:
45 case kMipsOr:
46 case kMipsSub:
43 case kMipsXor: 47 case kMipsXor:
44 return is_uint16(value); 48 return is_uint16(value);
45 case kMipsLdc1: 49 case kMipsLdc1:
46 case kMipsSdc1: 50 case kMipsSdc1:
47 case kCheckedLoadFloat64: 51 case kCheckedLoadFloat64:
48 case kCheckedStoreFloat64: 52 case kCheckedStoreFloat64:
49 return std::numeric_limits<int16_t>::min() <= (value + kIntSize) && 53 return std::numeric_limits<int16_t>::min() <= (value + kIntSize) &&
50 std::numeric_limits<int16_t>::max() >= (value + kIntSize); 54 std::numeric_limits<int16_t>::max() >= (value + kIntSize);
51 default: 55 default:
52 return is_int16(value); 56 return is_int16(value);
(...skipping 26 matching lines...) Expand all
79 83
80 84
81 static void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, 85 static void VisitRRO(InstructionSelector* selector, ArchOpcode opcode,
82 Node* node) { 86 Node* node) {
83 MipsOperandGenerator g(selector); 87 MipsOperandGenerator g(selector);
84 selector->Emit(opcode, g.DefineAsRegister(node), 88 selector->Emit(opcode, g.DefineAsRegister(node),
85 g.UseRegister(node->InputAt(0)), 89 g.UseRegister(node->InputAt(0)),
86 g.UseOperand(node->InputAt(1), opcode)); 90 g.UseOperand(node->InputAt(1), opcode));
87 } 91 }
88 92
93 bool TryMatchImmediate(InstructionSelector* selector,
94 InstructionCode* opcode_return, Node* node,
95 size_t* input_count_return, InstructionOperand* inputs) {
96 MipsOperandGenerator g(selector);
97 if (g.CanBeImmediate(node, *opcode_return)) {
98 *opcode_return |= AddressingModeField::encode(kMode_MRI);
99 inputs[0] = g.UseImmediate(node);
100 *input_count_return = 1;
101 return true;
102 }
103 return false;
104 }
89 105
90 static void VisitBinop(InstructionSelector* selector, Node* node, 106 static void VisitBinop(InstructionSelector* selector, Node* node,
91 InstructionCode opcode, FlagsContinuation* cont) { 107 InstructionCode opcode, bool has_reverse_opcode,
108 InstructionCode reverse_opcode,
109 FlagsContinuation* cont) {
92 MipsOperandGenerator g(selector); 110 MipsOperandGenerator g(selector);
93 Int32BinopMatcher m(node); 111 Int32BinopMatcher m(node);
94 InstructionOperand inputs[4]; 112 InstructionOperand inputs[4];
95 size_t input_count = 0; 113 size_t input_count = 0;
96 InstructionOperand outputs[2]; 114 InstructionOperand outputs[2];
97 size_t output_count = 0; 115 size_t output_count = 0;
98 116
99 inputs[input_count++] = g.UseRegister(m.left().node()); 117 if (TryMatchImmediate(selector, &opcode, m.right().node(), &input_count,
100 inputs[input_count++] = g.UseOperand(m.right().node(), opcode); 118 &inputs[1])) {
119 inputs[0] = g.UseRegister(m.left().node());
120 input_count++;
121 }
122 if (has_reverse_opcode &&
123 TryMatchImmediate(selector, &reverse_opcode, m.left().node(),
124 &input_count, &inputs[1])) {
125 inputs[0] = g.UseRegister(m.right().node());
126 opcode = reverse_opcode;
127 input_count++;
128 } else {
129 inputs[input_count++] = g.UseRegister(m.left().node());
130 inputs[input_count++] = g.UseOperand(m.right().node(), opcode);
131 }
101 132
102 if (cont->IsBranch()) { 133 if (cont->IsBranch()) {
103 inputs[input_count++] = g.Label(cont->true_block()); 134 inputs[input_count++] = g.Label(cont->true_block());
104 inputs[input_count++] = g.Label(cont->false_block()); 135 inputs[input_count++] = g.Label(cont->false_block());
105 } 136 }
106 137
107 if (cont->IsDeoptimize()) { 138 if (cont->IsDeoptimize()) {
108 // If we can deoptimize as a result of the binop, we need to make sure that 139 // If we can deoptimize as a result of the binop, we need to make sure that
109 // the deopt inputs are not overwritten by the binop result. One way 140 // the deopt inputs are not overwritten by the binop result. One way
110 // to achieve that is to declare the output register as same-as-first. 141 // to achieve that is to declare the output register as same-as-first.
(...skipping 12 matching lines...) Expand all
123 154
124 opcode = cont->Encode(opcode); 155 opcode = cont->Encode(opcode);
125 if (cont->IsDeoptimize()) { 156 if (cont->IsDeoptimize()) {
126 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, 157 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs,
127 cont->reason(), cont->frame_state()); 158 cont->reason(), cont->frame_state());
128 } else { 159 } else {
129 selector->Emit(opcode, output_count, outputs, input_count, inputs); 160 selector->Emit(opcode, output_count, outputs, input_count, inputs);
130 } 161 }
131 } 162 }
132 163
164 static void VisitBinop(InstructionSelector* selector, Node* node,
165 InstructionCode opcode, bool has_reverse_opcode,
166 InstructionCode reverse_opcode) {
167 FlagsContinuation cont;
168 VisitBinop(selector, node, opcode, has_reverse_opcode, reverse_opcode, &cont);
169 }
170
171 static void VisitBinop(InstructionSelector* selector, Node* node,
172 InstructionCode opcode, FlagsContinuation* cont) {
173 VisitBinop(selector, node, opcode, false, kArchNop, cont);
174 }
133 175
134 static void VisitBinop(InstructionSelector* selector, Node* node, 176 static void VisitBinop(InstructionSelector* selector, Node* node,
135 InstructionCode opcode) { 177 InstructionCode opcode) {
136 FlagsContinuation cont; 178 VisitBinop(selector, node, opcode, false, kArchNop);
137 VisitBinop(selector, node, opcode, &cont);
138 } 179 }
139 180
140 181
141 void InstructionSelector::VisitLoad(Node* node) { 182 void InstructionSelector::VisitLoad(Node* node) {
142 LoadRepresentation load_rep = LoadRepresentationOf(node->op()); 183 LoadRepresentation load_rep = LoadRepresentationOf(node->op());
143 MipsOperandGenerator g(this); 184 MipsOperandGenerator g(this);
144 Node* base = node->InputAt(0); 185 Node* base = node->InputAt(0);
145 Node* index = node->InputAt(1); 186 Node* index = node->InputAt(1);
146 187
147 ArchOpcode opcode = kArchNop; 188 ArchOpcode opcode = kArchNop;
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 uint32_t shift = base::bits::CountPopulation32(~mask); 351 uint32_t shift = base::bits::CountPopulation32(~mask);
311 uint32_t msb = base::bits::CountLeadingZeros32(~mask); 352 uint32_t msb = base::bits::CountLeadingZeros32(~mask);
312 if (shift != 0 && shift != 32 && msb + shift == 32) { 353 if (shift != 0 && shift != 32 && msb + shift == 32) {
313 // Insert zeros for (x >> K) << K => x & ~(2^K - 1) expression reduction 354 // Insert zeros for (x >> K) << K => x & ~(2^K - 1) expression reduction
314 // and remove constant loading of invereted mask. 355 // and remove constant loading of invereted mask.
315 Emit(kMipsIns, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()), 356 Emit(kMipsIns, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
316 g.TempImmediate(0), g.TempImmediate(shift)); 357 g.TempImmediate(0), g.TempImmediate(shift));
317 return; 358 return;
318 } 359 }
319 } 360 }
320 VisitBinop(this, node, kMipsAnd); 361 VisitBinop(this, node, kMipsAnd, true, kMipsAnd);
321 } 362 }
322 363
323 364
324 void InstructionSelector::VisitWord32Or(Node* node) { 365 void InstructionSelector::VisitWord32Or(Node* node) {
325 VisitBinop(this, node, kMipsOr); 366 VisitBinop(this, node, kMipsOr, true, kMipsOr);
326 } 367 }
327 368
328 369
329 void InstructionSelector::VisitWord32Xor(Node* node) { 370 void InstructionSelector::VisitWord32Xor(Node* node) {
330 Int32BinopMatcher m(node); 371 Int32BinopMatcher m(node);
331 if (m.left().IsWord32Or() && CanCover(node, m.left().node()) && 372 if (m.left().IsWord32Or() && CanCover(node, m.left().node()) &&
332 m.right().Is(-1)) { 373 m.right().Is(-1)) {
333 Int32BinopMatcher mleft(m.left().node()); 374 Int32BinopMatcher mleft(m.left().node());
334 if (!mleft.right().HasValue()) { 375 if (!mleft.right().HasValue()) {
335 MipsOperandGenerator g(this); 376 MipsOperandGenerator g(this);
336 Emit(kMipsNor, g.DefineAsRegister(node), 377 Emit(kMipsNor, g.DefineAsRegister(node),
337 g.UseRegister(mleft.left().node()), 378 g.UseRegister(mleft.left().node()),
338 g.UseRegister(mleft.right().node())); 379 g.UseRegister(mleft.right().node()));
339 return; 380 return;
340 } 381 }
341 } 382 }
342 if (m.right().Is(-1)) { 383 if (m.right().Is(-1)) {
343 // Use Nor for bit negation and eliminate constant loading for xori. 384 // Use Nor for bit negation and eliminate constant loading for xori.
344 MipsOperandGenerator g(this); 385 MipsOperandGenerator g(this);
345 Emit(kMipsNor, g.DefineAsRegister(node), g.UseRegister(m.left().node()), 386 Emit(kMipsNor, g.DefineAsRegister(node), g.UseRegister(m.left().node()),
346 g.TempImmediate(0)); 387 g.TempImmediate(0));
347 return; 388 return;
348 } 389 }
349 VisitBinop(this, node, kMipsXor); 390 VisitBinop(this, node, kMipsXor, true, kMipsXor);
350 } 391 }
351 392
352 393
353 void InstructionSelector::VisitWord32Shl(Node* node) { 394 void InstructionSelector::VisitWord32Shl(Node* node) {
354 Int32BinopMatcher m(node); 395 Int32BinopMatcher m(node);
355 if (m.left().IsWord32And() && CanCover(node, m.left().node()) && 396 if (m.left().IsWord32And() && CanCover(node, m.left().node()) &&
356 m.right().IsInRange(1, 31)) { 397 m.right().IsInRange(1, 31)) {
357 MipsOperandGenerator g(this); 398 MipsOperandGenerator g(this);
358 Int32BinopMatcher mleft(m.left().node()); 399 Int32BinopMatcher mleft(m.left().node());
359 // Match Word32Shl(Word32And(x, mask), imm) to Shl where the mask is 400 // Match Word32Shl(Word32And(x, mask), imm) to Shl where the mask is
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 CanCover(node, m.right().node()) && CanCover(node, m.left().node())) { 609 CanCover(node, m.right().node()) && CanCover(node, m.left().node())) {
569 Int32BinopMatcher mleft(m.left().node()); 610 Int32BinopMatcher mleft(m.left().node());
570 if (mleft.right().HasValue()) { 611 if (mleft.right().HasValue()) {
571 int32_t shift_value = static_cast<int32_t>(mleft.right().Value()); 612 int32_t shift_value = static_cast<int32_t>(mleft.right().Value());
572 Emit(kMipsLsa, g.DefineAsRegister(node), g.UseRegister(m.right().node()), 613 Emit(kMipsLsa, g.DefineAsRegister(node), g.UseRegister(m.right().node()),
573 g.UseRegister(mleft.left().node()), g.TempImmediate(shift_value)); 614 g.UseRegister(mleft.left().node()), g.TempImmediate(shift_value));
574 return; 615 return;
575 } 616 }
576 } 617 }
577 618
578 VisitBinop(this, node, kMipsAdd); 619 VisitBinop(this, node, kMipsAdd, true, kMipsAdd);
579 } 620 }
580 621
581 622
582 void InstructionSelector::VisitInt32Sub(Node* node) { 623 void InstructionSelector::VisitInt32Sub(Node* node) {
583 VisitBinop(this, node, kMipsSub); 624 VisitBinop(this, node, kMipsSub);
584 } 625 }
585 626
586 627
587 void InstructionSelector::VisitInt32Mul(Node* node) { 628 void InstructionSelector::VisitInt32Mul(Node* node) {
588 MipsOperandGenerator g(this); 629 MipsOperandGenerator g(this);
(...skipping 1218 matching lines...) Expand 10 before | Expand all | Expand 10 after
1807 DCHECK(IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r1) || 1848 DCHECK(IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r1) ||
1808 IsMipsArchVariant(kMips32r2)); 1849 IsMipsArchVariant(kMips32r2));
1809 return MachineOperatorBuilder::AlignmentRequirements:: 1850 return MachineOperatorBuilder::AlignmentRequirements::
1810 NoUnalignedAccessSupport(); 1851 NoUnalignedAccessSupport();
1811 } 1852 }
1812 } 1853 }
1813 1854
1814 } // namespace compiler 1855 } // namespace compiler
1815 } // namespace internal 1856 } // namespace internal
1816 } // namespace v8 1857 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/compiler/mips64/instruction-selector-mips64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698