V8 Project
instruction-selector-x64-unittest.cc
Go to the documentation of this file.
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
3 // found in the LICENSE file.
4 
6 
7 namespace v8 {
8 namespace internal {
9 namespace compiler {
10 
11 // -----------------------------------------------------------------------------
12 // Conversions.
13 
14 
15 TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter) {
16  StreamBuilder m(this, kMachFloat32, kMachFloat64);
17  m.Return(m.ChangeFloat32ToFloat64(m.Parameter(0)));
18  Stream s = m.Build();
19  ASSERT_EQ(1U, s.size());
20  EXPECT_EQ(kSSECvtss2sd, s[0]->arch_opcode());
21  EXPECT_EQ(1U, s[0]->InputCount());
22  EXPECT_EQ(1U, s[0]->OutputCount());
23 }
24 
25 
26 TEST_F(InstructionSelectorTest, ChangeInt32ToInt64WithParameter) {
27  StreamBuilder m(this, kMachInt64, kMachInt32);
28  m.Return(m.ChangeInt32ToInt64(m.Parameter(0)));
29  Stream s = m.Build();
30  ASSERT_EQ(1U, s.size());
31  EXPECT_EQ(kX64Movsxlq, s[0]->arch_opcode());
32 }
33 
34 
35 TEST_F(InstructionSelectorTest, ChangeUint32ToUint64WithParameter) {
36  StreamBuilder m(this, kMachUint64, kMachUint32);
37  m.Return(m.ChangeUint32ToUint64(m.Parameter(0)));
38  Stream s = m.Build();
39  ASSERT_EQ(1U, s.size());
40  EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
41 }
42 
43 
44 TEST_F(InstructionSelectorTest, TruncateFloat64ToFloat32WithParameter) {
45  StreamBuilder m(this, kMachFloat64, kMachFloat32);
46  m.Return(m.TruncateFloat64ToFloat32(m.Parameter(0)));
47  Stream s = m.Build();
48  ASSERT_EQ(1U, s.size());
49  EXPECT_EQ(kSSECvtsd2ss, s[0]->arch_opcode());
50  EXPECT_EQ(1U, s[0]->InputCount());
51  EXPECT_EQ(1U, s[0]->OutputCount());
52 }
53 
54 
55 TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithParameter) {
56  StreamBuilder m(this, kMachInt32, kMachInt64);
57  m.Return(m.TruncateInt64ToInt32(m.Parameter(0)));
58  Stream s = m.Build();
59  ASSERT_EQ(1U, s.size());
60  EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
61 }
62 
63 
64 // -----------------------------------------------------------------------------
65 // Better left operand for commutative binops
66 
67 TEST_F(InstructionSelectorTest, BetterLeftOperandTestAddBinop) {
68  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
69  Node* param1 = m.Parameter(0);
70  Node* param2 = m.Parameter(1);
71  Node* add = m.Int32Add(param1, param2);
72  m.Return(m.Int32Add(add, param1));
73  Stream s = m.Build();
74  ASSERT_EQ(2U, s.size());
75  EXPECT_EQ(kX64Add32, s[0]->arch_opcode());
76  ASSERT_EQ(2U, s[0]->InputCount());
77  ASSERT_TRUE(s[0]->InputAt(0)->IsUnallocated());
78  EXPECT_EQ(param2->id(), s.ToVreg(s[0]->InputAt(0)));
79 }
80 
81 
82 TEST_F(InstructionSelectorTest, BetterLeftOperandTestMulBinop) {
83  StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
84  Node* param1 = m.Parameter(0);
85  Node* param2 = m.Parameter(1);
86  Node* mul = m.Int32Mul(param1, param2);
87  m.Return(m.Int32Mul(mul, param1));
88  Stream s = m.Build();
89  ASSERT_EQ(2U, s.size());
90  EXPECT_EQ(kX64Imul32, s[0]->arch_opcode());
91  ASSERT_EQ(2U, s[0]->InputCount());
92  ASSERT_TRUE(s[0]->InputAt(0)->IsUnallocated());
93  EXPECT_EQ(param2->id(), s.ToVreg(s[0]->InputAt(0)));
94 }
95 
96 
97 // -----------------------------------------------------------------------------
98 // Loads and stores
99 
100 namespace {
101 
102 struct MemoryAccess {
106 };
107 
108 
109 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {
110  OStringStream ost;
111  ost << memacc.type;
112  return os << ost.c_str();
113 }
114 
115 
116 static const MemoryAccess kMemoryAccesses[] = {
117  {kMachInt8, kX64Movsxbl, kX64Movb},
118  {kMachUint8, kX64Movzxbl, kX64Movb},
119  {kMachInt16, kX64Movsxwl, kX64Movw},
120  {kMachUint16, kX64Movzxwl, kX64Movw},
121  {kMachInt32, kX64Movl, kX64Movl},
122  {kMachUint32, kX64Movl, kX64Movl},
123  {kMachInt64, kX64Movq, kX64Movq},
124  {kMachUint64, kX64Movq, kX64Movq},
125  {kMachFloat32, kX64Movss, kX64Movss},
126  {kMachFloat64, kX64Movsd, kX64Movsd}};
127 
128 } // namespace
129 
130 
131 typedef InstructionSelectorTestWithParam<MemoryAccess>
133 
134 
135 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
136  const MemoryAccess memacc = GetParam();
137  StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32);
138  m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1)));
139  Stream s = m.Build();
140  ASSERT_EQ(1U, s.size());
141  EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode());
142  EXPECT_EQ(2U, s[0]->InputCount());
143  EXPECT_EQ(1U, s[0]->OutputCount());
144 }
145 
146 
147 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) {
148  const MemoryAccess memacc = GetParam();
149  StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type);
150  m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2));
151  m.Return(m.Int32Constant(0));
152  Stream s = m.Build();
153  ASSERT_EQ(1U, s.size());
154  EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode());
155  EXPECT_EQ(3U, s[0]->InputCount());
156  EXPECT_EQ(0U, s[0]->OutputCount());
157 }
158 
159 
160 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
162  ::testing::ValuesIn(kMemoryAccesses));
163 
164 // -----------------------------------------------------------------------------
165 // AddressingMode for loads and stores.
166 
167 class AddressingModeUnitTest : public InstructionSelectorTest {
168  public:
171 
172  void Run(Node* base, Node* index, AddressingMode mode) {
173  Node* load = m->Load(kMachInt32, base, index);
174  m->Store(kMachInt32, base, index, load);
175  m->Return(m->Int32Constant(0));
176  Stream s = m->Build();
177  ASSERT_EQ(2U, s.size());
178  EXPECT_EQ(mode, s[0]->addressing_mode());
179  EXPECT_EQ(mode, s[1]->addressing_mode());
180  }
181 
182  Node* zero;
183  Node* null_ptr;
184  Node* non_zero;
185  Node* base_reg; // opaque value to generate base as register
186  Node* index_reg; // opaque value to generate index as register
187  Node* scales[4];
188  StreamBuilder* m;
189 
190  void Reset() {
191  delete m;
192  m = new StreamBuilder(this, kMachInt32, kMachInt32, kMachInt32);
193  zero = m->Int32Constant(0);
194  null_ptr = m->Int64Constant(0);
195  non_zero = m->Int32Constant(127);
196  base_reg = m->Parameter(0);
197  index_reg = m->Parameter(0);
198 
199  scales[0] = m->Int32Constant(1);
200  scales[1] = m->Int32Constant(2);
201  scales[2] = m->Int32Constant(4);
202  scales[3] = m->Int32Constant(8);
203  }
204 };
205 
206 
207 TEST_F(AddressingModeUnitTest, AddressingMode_MR) {
208  Node* base = base_reg;
209  Node* index = zero;
210  Run(base, index, kMode_MR);
211 }
212 
213 
214 TEST_F(AddressingModeUnitTest, AddressingMode_MRI) {
215  Node* base = base_reg;
216  Node* index = non_zero;
217  Run(base, index, kMode_MRI);
218 }
219 
220 
221 TEST_F(AddressingModeUnitTest, AddressingMode_MR1) {
222  Node* base = base_reg;
223  Node* index = index_reg;
224  Run(base, index, kMode_MR1);
225 }
226 
227 
228 TEST_F(AddressingModeUnitTest, AddressingMode_MRN) {
229  AddressingMode expected[] = {kMode_MR1, kMode_MR2, kMode_MR4, kMode_MR8};
230  for (size_t i = 0; i < arraysize(scales); ++i) {
231  Reset();
232  Node* base = base_reg;
233  Node* index = m->Int32Mul(index_reg, scales[i]);
234  Run(base, index, expected[i]);
235  }
236 }
237 
238 
239 TEST_F(AddressingModeUnitTest, AddressingMode_MR1I) {
240  Node* base = base_reg;
241  Node* index = m->Int32Add(index_reg, non_zero);
242  Run(base, index, kMode_MR1I);
243 }
244 
245 
246 TEST_F(AddressingModeUnitTest, AddressingMode_MRNI) {
247  AddressingMode expected[] = {kMode_MR1I, kMode_MR2I, kMode_MR4I, kMode_MR8I};
248  for (size_t i = 0; i < arraysize(scales); ++i) {
249  Reset();
250  Node* base = base_reg;
251  Node* index = m->Int32Add(m->Int32Mul(index_reg, scales[i]), non_zero);
252  Run(base, index, expected[i]);
253  }
254 }
255 
256 
257 TEST_F(AddressingModeUnitTest, AddressingMode_M1) {
258  Node* base = null_ptr;
259  Node* index = index_reg;
260  Run(base, index, kMode_M1);
261 }
262 
263 
264 TEST_F(AddressingModeUnitTest, AddressingMode_MN) {
265  AddressingMode expected[] = {kMode_M1, kMode_M2, kMode_M4, kMode_M8};
266  for (size_t i = 0; i < arraysize(scales); ++i) {
267  Reset();
268  Node* base = null_ptr;
269  Node* index = m->Int32Mul(index_reg, scales[i]);
270  Run(base, index, expected[i]);
271  }
272 }
273 
274 
275 TEST_F(AddressingModeUnitTest, AddressingMode_M1I) {
276  Node* base = null_ptr;
277  Node* index = m->Int32Add(index_reg, non_zero);
278  Run(base, index, kMode_M1I);
279 }
280 
281 
282 TEST_F(AddressingModeUnitTest, AddressingMode_MNI) {
283  AddressingMode expected[] = {kMode_M1I, kMode_M2I, kMode_M4I, kMode_M8I};
284  for (size_t i = 0; i < arraysize(scales); ++i) {
285  Reset();
286  Node* base = null_ptr;
287  Node* index = m->Int32Add(m->Int32Mul(index_reg, scales[i]), non_zero);
288  Run(base, index, expected[i]);
289  }
290 }
291 
292 } // namespace compiler
293 } // namespace internal
294 } // namespace v8
const char * c_str() const
Definition: ostreams.h:84
void Run(Node *base, Node *index, AddressingMode mode)
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define arraysize(array)
Definition: macros.h:86
std::ostream & operator<<(std::ostream &os, const MachineType &type)
static const MemoryAccess kMemoryAccesses[]
TEST_P(InstructionSelectorDPITest, Parameters)
InstructionSelectorTestWithParam< MemoryAccess > InstructionSelectorMemoryAccessTest
INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorDPITest, ::testing::ValuesIn(kDPIs))
TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter)
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20