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.
6 #include "test/cctest/cctest.h"
8 #include "src/base/utils/random-number-generator.h"
9 #include "src/compiler/structured-machine-assembler.h"
10 #include "test/cctest/compiler/codegen-tester.h"
11 #include "test/cctest/compiler/value-helper.h"
13 #if V8_TURBOFAN_TARGET
15 using namespace v8::internal::compiler;
17 typedef StructuredMachineAssembler::IfBuilder IfBuilder;
18 typedef StructuredMachineAssembler::LoopBuilder Loop;
24 class StructuredMachineAssemblerFriend {
26 static bool VariableAlive(StructuredMachineAssembler* m,
27 const Variable& var) {
28 CHECK(m->current_environment_ != NULL);
29 int offset = var.offset_;
30 return offset < static_cast<int>(m->CurrentVars()->size()) &&
31 m->CurrentVars()->at(offset) != NULL;
36 } // namespace v8::internal::compiler
40 StructuredMachineAssemblerTester<int32_t> m;
42 int32_t constant = 0x86c2bb16;
44 Variable v1 = m.NewVariable(m.Int32Constant(constant));
45 Variable v2 = m.NewVariable(v1.Get());
48 CHECK_EQ(constant, m.Call());
53 StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
55 int32_t constant = 0xc4a3e3a6;
58 cond.If(m.Parameter(0)).Then();
59 m.Return(m.Int32Constant(constant));
61 m.Return(m.Word32Not(m.Int32Constant(constant)));
63 CHECK_EQ(~constant, m.Call(0));
64 CHECK_EQ(constant, m.Call(1));
68 TEST(RunSimpleIfVariable) {
69 StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
71 int32_t constant = 0xdb6f20c2;
72 Variable var = m.NewVariable(m.Int32Constant(constant));
75 cond.If(m.Parameter(0)).Then();
76 var.Set(m.Word32Not(var.Get()));
80 CHECK_EQ(constant, m.Call(0));
81 CHECK_EQ(~constant, m.Call(1));
86 StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
88 int32_t constant = 0xfc5eadf4;
91 cond.If(m.Parameter(0)).Else();
92 m.Return(m.Int32Constant(constant));
94 m.Return(m.Word32Not(m.Int32Constant(constant)));
96 CHECK_EQ(constant, m.Call(0));
97 CHECK_EQ(~constant, m.Call(1));
101 TEST(RunSimpleIfElse) {
102 StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
104 int32_t constant = 0xaa9c8cd3;
107 cond.If(m.Parameter(0)).Then();
108 m.Return(m.Int32Constant(constant));
110 m.Return(m.Word32Not(m.Int32Constant(constant)));
113 CHECK_EQ(~constant, m.Call(0));
114 CHECK_EQ(constant, m.Call(1));
118 TEST(RunSimpleIfElseVariable) {
119 StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
121 int32_t constant = 0x67b6f39c;
122 Variable var = m.NewVariable(m.Int32Constant(constant));
125 cond.If(m.Parameter(0)).Then();
126 var.Set(m.Word32Not(m.Word32Not(var.Get())));
128 var.Set(m.Word32Not(var.Get()));
132 CHECK_EQ(~constant, m.Call(0));
133 CHECK_EQ(constant, m.Call(1));
137 TEST(RunSimpleIfNoThenElse) {
138 StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
140 int32_t constant = 0xd5e550ed;
143 cond.If(m.Parameter(0));
145 m.Return(m.Int32Constant(constant));
147 CHECK_EQ(constant, m.Call(0));
148 CHECK_EQ(constant, m.Call(1));
152 TEST(RunSimpleConjunctionVariable) {
153 StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
155 int32_t constant = 0xf8fb9ec6;
156 Variable var = m.NewVariable(m.Int32Constant(constant));
159 cond.If(m.Int32Constant(1)).And();
160 var.Set(m.Word32Not(var.Get()));
161 cond.If(m.Parameter(0)).Then();
162 var.Set(m.Word32Not(m.Word32Not(var.Get())));
164 var.Set(m.Word32Not(var.Get()));
168 CHECK_EQ(constant, m.Call(0));
169 CHECK_EQ(~constant, m.Call(1));
173 TEST(RunSimpleDisjunctionVariable) {
174 StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
176 int32_t constant = 0x118f6ffc;
177 Variable var = m.NewVariable(m.Int32Constant(constant));
180 cond.If(m.Int32Constant(0)).Or();
181 var.Set(m.Word32Not(var.Get()));
182 cond.If(m.Parameter(0)).Then();
183 var.Set(m.Word32Not(m.Word32Not(var.Get())));
185 var.Set(m.Word32Not(var.Get()));
189 CHECK_EQ(constant, m.Call(0));
190 CHECK_EQ(~constant, m.Call(1));
195 StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
200 FOR_INT32_INPUTS(i) {
201 Node* c = m.Int32Constant(*i);
203 cond.If(m.Word32Equal(m.Parameter(0), c)).Then();
208 cond.If(m.Word32Equal(m.Parameter(0), c)).Then();
213 m.Return(m.Int32Constant(333));
215 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, m.Call(*i)); }
219 enum IfBuilderBranchType { kSkipBranch, kBranchFallsThrough, kBranchReturns };
222 static IfBuilderBranchType all_branch_types[] = {
223 kSkipBranch, kBranchFallsThrough, kBranchReturns};
226 static void RunIfBuilderDisjunction(size_t max, IfBuilderBranchType then_type,
227 IfBuilderBranchType else_type) {
228 StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
230 std::vector<int32_t> inputs = ValueHelper::int32_vector();
231 std::vector<int32_t>::const_iterator i = inputs.begin();
232 int32_t hit = 0x8c723c9a;
233 int32_t miss = 0x88a6b9f3;
235 Node* p0 = m.Parameter(0);
237 for (size_t j = 0; j < max; j++, ++i) {
238 CHECK(i != inputs.end()); // Thank you STL.
239 if (j > 0) cond.Or();
240 cond.If(m.Word32Equal(p0, m.Int32Constant(*i)));
245 case kBranchFallsThrough:
250 m.Return(m.Int32Constant(hit));
256 case kBranchFallsThrough:
261 m.Return(m.Int32Constant(miss));
265 if (then_type != kBranchReturns || else_type != kBranchReturns) {
266 m.Return(m.Int32Constant(miss));
269 if (then_type != kBranchReturns) hit = miss;
272 for (size_t j = 0; i != inputs.end(); j++, ++i) {
273 int32_t result = m.Call(*i);
274 CHECK_EQ(j < max ? hit : miss, result);
279 TEST(RunIfBuilderDisjunction) {
280 size_t len = ValueHelper::int32_vector().size() - 1;
281 size_t max = len > 10 ? 10 : len - 1;
282 for (size_t i = 0; i < ARRAY_SIZE(all_branch_types); i++) {
283 for (size_t j = 0; j < ARRAY_SIZE(all_branch_types); j++) {
284 for (size_t size = 1; size < max; size++) {
285 RunIfBuilderDisjunction(size, all_branch_types[i], all_branch_types[j]);
287 RunIfBuilderDisjunction(len, all_branch_types[i], all_branch_types[j]);
293 static void RunIfBuilderConjunction(size_t max, IfBuilderBranchType then_type,
294 IfBuilderBranchType else_type) {
295 StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
297 std::vector<int32_t> inputs = ValueHelper::int32_vector();
298 std::vector<int32_t>::const_iterator i = inputs.begin();
299 int32_t hit = 0xa0ceb9ca;
300 int32_t miss = 0x226cafaa;
303 Node* p0 = m.Parameter(0);
304 for (size_t j = 0; j < max; j++, ++i) {
305 if (j > 0) cond.And();
306 cond.If(m.Word32NotEqual(p0, m.Int32Constant(*i)));
311 case kBranchFallsThrough:
316 m.Return(m.Int32Constant(hit));
322 case kBranchFallsThrough:
327 m.Return(m.Int32Constant(miss));
331 if (then_type != kBranchReturns || else_type != kBranchReturns) {
332 m.Return(m.Int32Constant(miss));
335 if (then_type != kBranchReturns) hit = miss;
338 for (size_t j = 0; i != inputs.end(); j++, ++i) {
339 int32_t result = m.Call(*i);
340 CHECK_EQ(j >= max ? hit : miss, result);
345 TEST(RunIfBuilderConjunction) {
346 size_t len = ValueHelper::int32_vector().size() - 1;
347 size_t max = len > 10 ? 10 : len - 1;
348 for (size_t i = 0; i < ARRAY_SIZE(all_branch_types); i++) {
349 for (size_t j = 0; j < ARRAY_SIZE(all_branch_types); j++) {
350 for (size_t size = 1; size < max; size++) {
351 RunIfBuilderConjunction(size, all_branch_types[i], all_branch_types[j]);
353 RunIfBuilderConjunction(len, all_branch_types[i], all_branch_types[j]);
359 static void RunDisjunctionVariables(int disjunctions, bool explicit_then,
360 bool explicit_else) {
361 StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
363 int32_t constant = 0x65a09535;
365 Node* cmp_val = m.Int32Constant(constant);
366 Node* one = m.Int32Constant(1);
367 Variable var = m.NewVariable(m.Parameter(0));
370 cond.If(m.Word32Equal(var.Get(), cmp_val));
371 for (int i = 0; i < disjunctions; i++) {
373 var.Set(m.Int32Add(var.Get(), one));
374 cond.If(m.Word32Equal(var.Get(), cmp_val));
381 var.Set(m.Int32Add(var.Get(), one));
386 int adds = disjunctions + (explicit_else ? 1 : 0);
387 int32_t input = constant - 2 * adds;
388 for (int i = 0; i < adds; i++) {
389 CHECK_EQ(input + adds, m.Call(input));
392 for (int i = 0; i < adds + 1; i++) {
393 CHECK_EQ(constant, m.Call(input));
396 for (int i = 0; i < adds; i++) {
397 CHECK_EQ(input + adds, m.Call(input));
403 TEST(RunDisjunctionVariables) {
404 for (int disjunctions = 0; disjunctions < 10; disjunctions++) {
405 RunDisjunctionVariables(disjunctions, false, false);
406 RunDisjunctionVariables(disjunctions, false, true);
407 RunDisjunctionVariables(disjunctions, true, false);
408 RunDisjunctionVariables(disjunctions, true, true);
413 static void RunConjunctionVariables(int conjunctions, bool explicit_then,
414 bool explicit_else) {
415 StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
417 int32_t constant = 0x2c7f4b45;
418 Node* cmp_val = m.Int32Constant(constant);
419 Node* one = m.Int32Constant(1);
420 Variable var = m.NewVariable(m.Parameter(0));
423 cond.If(m.Word32NotEqual(var.Get(), cmp_val));
424 for (int i = 0; i < conjunctions; i++) {
426 var.Set(m.Int32Add(var.Get(), one));
427 cond.If(m.Word32NotEqual(var.Get(), cmp_val));
431 var.Set(m.Int32Add(var.Get(), one));
439 int adds = conjunctions + (explicit_then ? 1 : 0);
440 int32_t input = constant - 2 * adds;
441 for (int i = 0; i < adds; i++) {
442 CHECK_EQ(input + adds, m.Call(input));
445 for (int i = 0; i < adds + 1; i++) {
446 CHECK_EQ(constant, m.Call(input));
449 for (int i = 0; i < adds; i++) {
450 CHECK_EQ(input + adds, m.Call(input));
456 TEST(RunConjunctionVariables) {
457 for (int conjunctions = 0; conjunctions < 10; conjunctions++) {
458 RunConjunctionVariables(conjunctions, false, false);
459 RunConjunctionVariables(conjunctions, false, true);
460 RunConjunctionVariables(conjunctions, true, false);
461 RunConjunctionVariables(conjunctions, true, true);
466 TEST(RunSimpleNestedIf) {
467 StructuredMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32);
468 const size_t NUM_VALUES = 7;
469 std::vector<int32_t> inputs = ValueHelper::int32_vector();
470 CHECK(inputs.size() >= NUM_VALUES);
471 Node* values[NUM_VALUES];
472 for (size_t j = 0; j < NUM_VALUES; j++) {
473 values[j] = m.Int32Constant(inputs[j]);
477 if_0.If(m.Word32Equal(m.Parameter(0), values[0])).Then();
480 if_1.If(m.Word32Equal(m.Parameter(1), values[1])).Then();
481 { m.Return(values[3]); }
483 { m.Return(values[4]); }
488 if_1.If(m.Word32Equal(m.Parameter(1), values[2])).Then();
489 { m.Return(values[5]); }
491 { m.Return(values[6]); }
495 int32_t result = m.Call(inputs[0], inputs[1]);
496 CHECK_EQ(inputs[3], result);
498 result = m.Call(inputs[0], inputs[1] + 1);
499 CHECK_EQ(inputs[4], result);
501 result = m.Call(inputs[0] + 1, inputs[2]);
502 CHECK_EQ(inputs[5], result);
504 result = m.Call(inputs[0] + 1, inputs[2] + 1);
505 CHECK_EQ(inputs[6], result);
509 TEST(RunUnreachableBlockAfterIf) {
510 StructuredMachineAssemblerTester<int32_t> m;
513 cond.If(m.Int32Constant(0)).Then();
514 m.Return(m.Int32Constant(1));
516 m.Return(m.Int32Constant(2));
518 // This is unreachable.
519 m.Return(m.Int32Constant(3));
520 CHECK_EQ(2, m.Call());
524 TEST(RunUnreachableBlockAfterLoop) {
525 StructuredMachineAssemblerTester<int32_t> m;
528 m.Return(m.Int32Constant(1));
530 // This is unreachable.
531 m.Return(m.Int32Constant(3));
532 CHECK_EQ(1, m.Call());
536 TEST(RunSimpleLoop) {
537 StructuredMachineAssemblerTester<int32_t> m;
538 int32_t constant = 0x120c1f85;
541 m.Return(m.Int32Constant(constant));
543 CHECK_EQ(constant, m.Call());
547 TEST(RunSimpleLoopBreak) {
548 StructuredMachineAssemblerTester<int32_t> m;
549 int32_t constant = 0x10ddb0a6;
554 m.Return(m.Int32Constant(constant));
555 CHECK_EQ(constant, m.Call());
559 TEST(RunCountToTen) {
560 StructuredMachineAssemblerTester<int32_t> m;
561 Variable i = m.NewVariable(m.Int32Constant(0));
562 Node* ten = m.Int32Constant(10);
563 Node* one = m.Int32Constant(1);
568 cond.If(m.Word32Equal(i.Get(), ten)).Then();
571 i.Set(m.Int32Add(i.Get(), one));
574 CHECK_EQ(10, m.Call());
578 TEST(RunCountToTenAcc) {
579 StructuredMachineAssemblerTester<int32_t> m;
580 int32_t constant = 0xf27aed64;
581 Variable i = m.NewVariable(m.Int32Constant(0));
582 Variable var = m.NewVariable(m.Int32Constant(constant));
583 Node* ten = m.Int32Constant(10);
584 Node* one = m.Int32Constant(1);
589 cond.If(m.Word32Equal(i.Get(), ten)).Then();
592 i.Set(m.Int32Add(i.Get(), one));
593 var.Set(m.Int32Add(var.Get(), i.Get()));
597 CHECK_EQ(constant + 10 + 9 * 5, m.Call());
601 TEST(RunSimpleNestedLoop) {
602 StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
604 Node* zero = m.Int32Constant(0);
605 Node* one = m.Int32Constant(1);
606 Node* two = m.Int32Constant(2);
607 Node* three = m.Int32Constant(3);
614 cond.If(m.Word32Equal(m.Parameter(0), one)).Then();
621 cond.If(m.Word32Equal(m.Parameter(0), two)).Then();
624 cond.If(m.Word32Equal(m.Parameter(0), three)).Then();
635 CHECK_EQ(0, m.Call(1));
636 CHECK_EQ(1, m.Call(2));
637 CHECK_EQ(2, m.Call(3));
638 CHECK_EQ(3, m.Call(4));
643 StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
646 Node* zero = m.Int32Constant(0);
647 Node* one = m.Int32Constant(1);
648 Node* two = m.Int32Constant(2);
651 Variable cnt = m.NewVariable(m.Parameter(0));
652 // if (cnt < 2) return i
655 lt2.If(m.Int32LessThan(cnt.Get(), two)).Then();
659 cnt.Set(m.Int32Sub(cnt.Get(), two));
661 Variable res = m.NewVariable(one);
665 Variable prv_0 = m.NewVariable(one);
666 Variable prv_1 = m.NewVariable(one);
667 // while (cnt != 0) {
671 nz.If(m.Word32Equal(cnt.Get(), zero)).Then();
674 // res = prv_0 + prv_1
677 res.Set(m.Int32Add(prv_0.Get(), prv_1.Get()));
678 prv_0.Set(prv_1.Get());
679 prv_1.Set(res.Get());
681 cnt.Set(m.Int32Sub(cnt.Get(), one));
685 int32_t values[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144};
686 for (size_t i = 0; i < ARRAY_SIZE(values); i++) {
687 CHECK_EQ(values[i], m.Call(static_cast<int32_t>(i)));
692 static int VariableIntroduction() {
695 for (int i = 0; i < 10; i++) {
696 for (int j = i; j < 10; j++) {
697 for (int k = j; k < 10; k++) {
709 TEST(RunVariableIntroduction) {
710 StructuredMachineAssemblerTester<int32_t> m;
711 Node* zero = m.Int32Constant(0);
712 Node* one = m.Int32Constant(1);
713 // Use an IfBuilder to get out of start block.
719 Node* ten = m.Int32Constant(10);
721 m.NewVariable(zero); // Introduce variable outside of start block.
724 Variable ret = m.NewVariable(zero); // Introduce loop variable.
729 i1.If(m.Word32Equal(v0.Get(), ten)).Then();
732 Variable v1 = m.NewVariable(v0.Get()); // Introduce loop variable.
737 i2.If(m.Word32Equal(v1.Get(), ten)).Then();
740 Variable v2 = m.NewVariable(v1.Get()); // Introduce loop variable.
745 i3.If(m.Word32Equal(v2.Get(), ten)).Then();
748 ret.Set(m.Int32Add(ret.Get(), one));
749 v2.Set(m.Int32Add(v2.Get(), one));
751 ret.Set(m.Int32Add(ret.Get(), one));
752 v1.Set(m.Int32Add(v1.Get(), one));
754 ret.Set(m.Int32Add(ret.Get(), one));
755 v0.Set(m.Int32Add(v0.Get(), one));
757 m.Return(ret.Get()); // Return loop variable.
759 CHECK_EQ(VariableIntroduction(), m.Call());
763 TEST(RunIfBuilderVariableLiveness) {
764 StructuredMachineAssemblerTester<int32_t> m;
765 typedef i::compiler::StructuredMachineAssemblerFriend F;
766 Node* zero = m.Int32Constant(0);
767 Variable v_outer = m.NewVariable(zero);
769 cond.If(zero).Then();
770 Variable v_then = m.NewVariable(zero);
771 CHECK(F::VariableAlive(&m, v_outer));
772 CHECK(F::VariableAlive(&m, v_then));
774 Variable v_else = m.NewVariable(zero);
775 CHECK(F::VariableAlive(&m, v_outer));
776 CHECK(F::VariableAlive(&m, v_else));
777 CHECK(!F::VariableAlive(&m, v_then));
779 CHECK(F::VariableAlive(&m, v_outer));
780 CHECK(!F::VariableAlive(&m, v_then));
781 CHECK(!F::VariableAlive(&m, v_else));
785 TEST(RunSimpleExpression1) {
786 StructuredMachineAssemblerTester<int32_t> m;
788 int32_t constant = 0x0c2974ef;
789 Node* zero = m.Int32Constant(0);
790 Node* one = m.Int32Constant(1);
792 // if (((1 && 1) && 1) && 1) return constant; return 0;
795 cond.OpenParen().If(one).And();
796 cond.If(one).CloseParen().And();
797 cond.If(one).CloseParen().And();
799 m.Return(m.Int32Constant(constant));
803 CHECK_EQ(constant, m.Call());
807 TEST(RunSimpleExpression2) {
808 StructuredMachineAssemblerTester<int32_t> m;
810 int32_t constant = 0x2eddc11b;
811 Node* zero = m.Int32Constant(0);
812 Node* one = m.Int32Constant(1);
814 // if (((0 || 1) && 1) && 1) return constant; return 0;
817 cond.OpenParen().If(zero).Or();
818 cond.If(one).CloseParen().And();
819 cond.If(one).CloseParen().And();
821 m.Return(m.Int32Constant(constant));
825 CHECK_EQ(constant, m.Call());
829 TEST(RunSimpleExpression3) {
830 StructuredMachineAssemblerTester<int32_t> m;
832 int32_t constant = 0x9ed5e9ef;
833 Node* zero = m.Int32Constant(0);
834 Node* one = m.Int32Constant(1);
836 // if (1 && ((0 || 1) && 1) && 1) return constant; return 0;
840 cond.OpenParen().If(zero).Or();
841 cond.If(one).CloseParen().And();
842 cond.If(one).CloseParen().And();
844 m.Return(m.Int32Constant(constant));
848 CHECK_EQ(constant, m.Call());
852 TEST(RunSimpleExpressionVariable1) {
853 StructuredMachineAssemblerTester<int32_t> m;
855 int32_t constant = 0x4b40a986;
856 Node* one = m.Int32Constant(1);
857 Variable var = m.NewVariable(m.Int32Constant(constant));
859 // if (var.Get() && ((!var || var) && var) && var) {} return var;
860 // incrementing var in each environment.
862 cond.If(var.Get()).And();
863 var.Set(m.Int32Add(var.Get(), one));
864 cond.OpenParen().OpenParen().If(m.Word32BinaryNot(var.Get())).Or();
865 var.Set(m.Int32Add(var.Get(), one));
866 cond.If(var.Get()).CloseParen().And();
867 var.Set(m.Int32Add(var.Get(), one));
868 cond.If(var.Get()).CloseParen().And();
869 var.Set(m.Int32Add(var.Get(), one));
874 CHECK_EQ(constant + 4, m.Call());
878 class QuicksortHelper : public StructuredMachineAssemblerTester<int32_t> {
881 : StructuredMachineAssemblerTester<int32_t>(
882 MachineOperatorBuilder::pointer_rep(), kMachineWord32,
883 MachineOperatorBuilder::pointer_rep(), kMachineWord32),
886 one_(Int32Constant(1)),
887 stack_frame_size_(Int32Constant(kFrameVariables * 4)),
888 left_offset_(Int32Constant(0 * 4)),
889 right_offset_(Int32Constant(1 * 4)) {
893 int32_t DoCall(int32_t* input, int32_t input_length) {
894 int32_t stack_space[20];
896 int32_t return_val = Call(input, input_length, stack_space,
897 static_cast<int32_t>(ARRAY_SIZE(stack_space)));
898 // Ran out of stack space.
899 if (return_val != 0) return return_val;
901 int32_t last = input[0];
902 for (int32_t i = 0; i < input_length; i++) {
903 CHECK(last <= input[i]);
910 void Inc32(const Variable& var) { var.Set(Int32Add(var.Get(), one_)); }
911 Node* Index(Node* index) { return Word32Shl(index, Int32Constant(2)); }
912 Node* ArrayLoad(Node* index) {
913 return Load(kMachineWord32, input_, Index(index));
915 void Swap(Node* a_index, Node* b_index) {
916 Node* a = ArrayLoad(a_index);
917 Node* b = ArrayLoad(b_index);
918 Store(kMachineWord32, input_, Index(a_index), b);
919 Store(kMachineWord32, input_, Index(b_index), a);
921 void AddToCallStack(const Variable& fp, Node* left, Node* right) {
923 // Stack limit check.
924 IfBuilder cond(this);
925 cond.If(IntPtrLessThanOrEqual(fp.Get(), stack_limit_)).Then();
926 Return(Int32Constant(-1));
928 Store(kMachineWord32, fp.Get(), left_offset_, left);
929 Store(kMachineWord32, fp.Get(), right_offset_, right);
930 fp.Set(IntPtrAdd(fp.Get(), ConvertInt32ToIntPtr(stack_frame_size_)));
933 Variable left = NewVariable(Int32Constant(0));
935 NewVariable(Int32Sub(Parameter(kInputLengthParameter), one_));
936 input_ = Parameter(kInputParameter);
937 Node* top_of_stack = Parameter(kStackParameter);
938 stack_limit_ = IntPtrSub(
939 top_of_stack, ConvertInt32ToIntPtr(Parameter(kStackLengthParameter)));
940 Variable fp = NewVariable(top_of_stack);
942 Loop outermost(this);
943 // Edge case - 2 element array.
945 IfBuilder cond(this);
946 cond.If(Word32Equal(left.Get(), Int32Sub(right.Get(), one_))).And();
947 cond.If(Int32LessThanOrEqual(ArrayLoad(right.Get()),
948 ArrayLoad(left.Get()))).Then();
949 Swap(left.Get(), right.Get());
952 IfBuilder cond(this);
953 // Algorithm complete condition.
954 cond.If(WordEqual(top_of_stack, fp.Get())).And();
955 cond.If(Int32LessThanOrEqual(Int32Sub(right.Get(), one_), left.Get()))
958 // 'Recursion' exit condition. Pop frame and continue.
960 cond.If(Int32LessThanOrEqual(Int32Sub(right.Get(), one_), left.Get()))
962 fp.Set(IntPtrSub(fp.Get(), ConvertInt32ToIntPtr(stack_frame_size_)));
963 left.Set(Load(kMachineWord32, fp.Get(), left_offset_));
964 right.Set(Load(kMachineWord32, fp.Get(), right_offset_));
965 outermost.Continue();
968 Variable store_index = NewVariable(left.Get());
971 Int32Div(Int32Add(left.Get(), right.Get()), Int32Constant(2));
972 Node* pivot = ArrayLoad(pivot_index);
973 Swap(pivot_index, right.Get());
974 Variable i = NewVariable(left.Get());
976 Loop partition(this);
978 IfBuilder cond(this);
979 // Parition complete.
980 cond.If(Word32Equal(i.Get(), right.Get())).Then();
984 cond.If(Int32LessThanOrEqual(ArrayLoad(i.Get()), pivot)).Then();
985 Swap(i.Get(), store_index.Get());
989 } // End partition loop.
990 Swap(store_index.Get(), right.Get());
992 // 'Recurse' left and right halves of partition.
993 // Tail recurse second one.
994 AddToCallStack(fp, left.Get(), Int32Sub(store_index.Get(), one_));
995 left.Set(Int32Add(store_index.Get(), one_));
996 } // End outermost loop.
997 Return(Int32Constant(0));
1000 static const int kFrameVariables = 2; // left, right
1001 // Parameter offsets.
1002 static const int kInputParameter = 0;
1003 static const int kInputLengthParameter = 1;
1004 static const int kStackParameter = 2;
1005 static const int kStackLengthParameter = 3;
1012 Node* const stack_frame_size_;
1013 Node* const left_offset_;
1014 Node* const right_offset_;
1018 TEST(RunSimpleQuicksort) {
1020 int32_t inputs[] = {9, 7, 1, 8, 11};
1021 CHECK_EQ(0, m.DoCall(inputs, ARRAY_SIZE(inputs)));
1025 TEST(RunRandomQuicksort) {
1028 v8::base::RandomNumberGenerator rng;
1029 static const int kMaxLength = 40;
1030 int32_t inputs[kMaxLength];
1032 for (int length = 1; length < kMaxLength; length++) {
1033 for (int i = 0; i < 70; i++) {
1034 // Randomize inputs.
1035 for (int j = 0; j < length; j++) {
1036 inputs[j] = rng.NextInt(10) - 5;
1038 CHECK_EQ(0, m.DoCall(inputs, length));
1044 TEST(MultipleScopes) {
1045 StructuredMachineAssemblerTester<int32_t> m;
1046 for (int i = 0; i < 10; i++) {
1048 b.If(m.Int32Constant(0)).Then();
1049 m.NewVariable(m.Int32Constant(0));
1051 m.Return(m.Int32Constant(0));
1052 CHECK_EQ(0, m.Call());