PageRenderTime 28ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/deps/v8/test/cctest/compiler/test-branch-combine.cc

https://gitlab.com/MichelZuniga/node
C++ | 462 lines | 365 code | 83 blank | 14 comment | 48 complexity | 79fac1d236c1ebc23d097bb9fbc19f6d MD5 | raw 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. #include "src/v8.h"
  5. #include "test/cctest/cctest.h"
  6. #include "test/cctest/compiler/codegen-tester.h"
  7. #include "test/cctest/compiler/value-helper.h"
  8. #if V8_TURBOFAN_TARGET
  9. using namespace v8::internal;
  10. using namespace v8::internal::compiler;
  11. typedef RawMachineAssembler::Label MLabel;
  12. static IrOpcode::Value int32cmp_opcodes[] = {
  13. IrOpcode::kWord32Equal, IrOpcode::kInt32LessThan,
  14. IrOpcode::kInt32LessThanOrEqual, IrOpcode::kUint32LessThan,
  15. IrOpcode::kUint32LessThanOrEqual};
  16. TEST(BranchCombineWord32EqualZero_1) {
  17. // Test combining a branch with x == 0
  18. RawMachineAssemblerTester<int32_t> m(kMachInt32);
  19. int32_t eq_constant = -1033;
  20. int32_t ne_constant = 825118;
  21. Node* p0 = m.Parameter(0);
  22. MLabel blocka, blockb;
  23. m.Branch(m.Word32Equal(p0, m.Int32Constant(0)), &blocka, &blockb);
  24. m.Bind(&blocka);
  25. m.Return(m.Int32Constant(eq_constant));
  26. m.Bind(&blockb);
  27. m.Return(m.Int32Constant(ne_constant));
  28. FOR_INT32_INPUTS(i) {
  29. int32_t a = *i;
  30. int32_t expect = a == 0 ? eq_constant : ne_constant;
  31. CHECK_EQ(expect, m.Call(a));
  32. }
  33. }
  34. TEST(BranchCombineWord32EqualZero_chain) {
  35. // Test combining a branch with a chain of x == 0 == 0 == 0 ...
  36. int32_t eq_constant = -1133;
  37. int32_t ne_constant = 815118;
  38. for (int k = 0; k < 6; k++) {
  39. RawMachineAssemblerTester<int32_t> m(kMachInt32);
  40. Node* p0 = m.Parameter(0);
  41. MLabel blocka, blockb;
  42. Node* cond = p0;
  43. for (int j = 0; j < k; j++) {
  44. cond = m.Word32Equal(cond, m.Int32Constant(0));
  45. }
  46. m.Branch(cond, &blocka, &blockb);
  47. m.Bind(&blocka);
  48. m.Return(m.Int32Constant(eq_constant));
  49. m.Bind(&blockb);
  50. m.Return(m.Int32Constant(ne_constant));
  51. FOR_INT32_INPUTS(i) {
  52. int32_t a = *i;
  53. int32_t expect = (k & 1) == 1 ? (a == 0 ? eq_constant : ne_constant)
  54. : (a == 0 ? ne_constant : eq_constant);
  55. CHECK_EQ(expect, m.Call(a));
  56. }
  57. }
  58. }
  59. TEST(BranchCombineInt32LessThanZero_1) {
  60. // Test combining a branch with x < 0
  61. RawMachineAssemblerTester<int32_t> m(kMachInt32);
  62. int32_t eq_constant = -1433;
  63. int32_t ne_constant = 845118;
  64. Node* p0 = m.Parameter(0);
  65. MLabel blocka, blockb;
  66. m.Branch(m.Int32LessThan(p0, m.Int32Constant(0)), &blocka, &blockb);
  67. m.Bind(&blocka);
  68. m.Return(m.Int32Constant(eq_constant));
  69. m.Bind(&blockb);
  70. m.Return(m.Int32Constant(ne_constant));
  71. FOR_INT32_INPUTS(i) {
  72. int32_t a = *i;
  73. int32_t expect = a < 0 ? eq_constant : ne_constant;
  74. CHECK_EQ(expect, m.Call(a));
  75. }
  76. }
  77. TEST(BranchCombineUint32LessThan100_1) {
  78. // Test combining a branch with x < 100
  79. RawMachineAssemblerTester<int32_t> m(kMachUint32);
  80. int32_t eq_constant = 1471;
  81. int32_t ne_constant = 88845718;
  82. Node* p0 = m.Parameter(0);
  83. MLabel blocka, blockb;
  84. m.Branch(m.Uint32LessThan(p0, m.Int32Constant(100)), &blocka, &blockb);
  85. m.Bind(&blocka);
  86. m.Return(m.Int32Constant(eq_constant));
  87. m.Bind(&blockb);
  88. m.Return(m.Int32Constant(ne_constant));
  89. FOR_UINT32_INPUTS(i) {
  90. uint32_t a = *i;
  91. int32_t expect = a < 100 ? eq_constant : ne_constant;
  92. CHECK_EQ(expect, m.Call(a));
  93. }
  94. }
  95. TEST(BranchCombineUint32LessThanOrEqual100_1) {
  96. // Test combining a branch with x <= 100
  97. RawMachineAssemblerTester<int32_t> m(kMachUint32);
  98. int32_t eq_constant = 1479;
  99. int32_t ne_constant = 77845719;
  100. Node* p0 = m.Parameter(0);
  101. MLabel blocka, blockb;
  102. m.Branch(m.Uint32LessThanOrEqual(p0, m.Int32Constant(100)), &blocka, &blockb);
  103. m.Bind(&blocka);
  104. m.Return(m.Int32Constant(eq_constant));
  105. m.Bind(&blockb);
  106. m.Return(m.Int32Constant(ne_constant));
  107. FOR_UINT32_INPUTS(i) {
  108. uint32_t a = *i;
  109. int32_t expect = a <= 100 ? eq_constant : ne_constant;
  110. CHECK_EQ(expect, m.Call(a));
  111. }
  112. }
  113. TEST(BranchCombineZeroLessThanInt32_1) {
  114. // Test combining a branch with 0 < x
  115. RawMachineAssemblerTester<int32_t> m(kMachInt32);
  116. int32_t eq_constant = -2033;
  117. int32_t ne_constant = 225118;
  118. Node* p0 = m.Parameter(0);
  119. MLabel blocka, blockb;
  120. m.Branch(m.Int32LessThan(m.Int32Constant(0), p0), &blocka, &blockb);
  121. m.Bind(&blocka);
  122. m.Return(m.Int32Constant(eq_constant));
  123. m.Bind(&blockb);
  124. m.Return(m.Int32Constant(ne_constant));
  125. FOR_INT32_INPUTS(i) {
  126. int32_t a = *i;
  127. int32_t expect = 0 < a ? eq_constant : ne_constant;
  128. CHECK_EQ(expect, m.Call(a));
  129. }
  130. }
  131. TEST(BranchCombineInt32GreaterThanZero_1) {
  132. // Test combining a branch with x > 0
  133. RawMachineAssemblerTester<int32_t> m(kMachInt32);
  134. int32_t eq_constant = -1073;
  135. int32_t ne_constant = 825178;
  136. Node* p0 = m.Parameter(0);
  137. MLabel blocka, blockb;
  138. m.Branch(m.Int32GreaterThan(p0, m.Int32Constant(0)), &blocka, &blockb);
  139. m.Bind(&blocka);
  140. m.Return(m.Int32Constant(eq_constant));
  141. m.Bind(&blockb);
  142. m.Return(m.Int32Constant(ne_constant));
  143. FOR_INT32_INPUTS(i) {
  144. int32_t a = *i;
  145. int32_t expect = a > 0 ? eq_constant : ne_constant;
  146. CHECK_EQ(expect, m.Call(a));
  147. }
  148. }
  149. TEST(BranchCombineWord32EqualP) {
  150. // Test combining a branch with an Word32Equal.
  151. RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32);
  152. int32_t eq_constant = -1035;
  153. int32_t ne_constant = 825018;
  154. Node* p0 = m.Parameter(0);
  155. Node* p1 = m.Parameter(1);
  156. MLabel blocka, blockb;
  157. m.Branch(m.Word32Equal(p0, p1), &blocka, &blockb);
  158. m.Bind(&blocka);
  159. m.Return(m.Int32Constant(eq_constant));
  160. m.Bind(&blockb);
  161. m.Return(m.Int32Constant(ne_constant));
  162. FOR_INT32_INPUTS(i) {
  163. FOR_INT32_INPUTS(j) {
  164. int32_t a = *i;
  165. int32_t b = *j;
  166. int32_t expect = a == b ? eq_constant : ne_constant;
  167. CHECK_EQ(expect, m.Call(a, b));
  168. }
  169. }
  170. }
  171. TEST(BranchCombineWord32EqualI) {
  172. int32_t eq_constant = -1135;
  173. int32_t ne_constant = 925718;
  174. for (int left = 0; left < 2; left++) {
  175. FOR_INT32_INPUTS(i) {
  176. RawMachineAssemblerTester<int32_t> m(kMachInt32);
  177. int32_t a = *i;
  178. Node* p0 = m.Int32Constant(a);
  179. Node* p1 = m.Parameter(0);
  180. MLabel blocka, blockb;
  181. if (left == 1) m.Branch(m.Word32Equal(p0, p1), &blocka, &blockb);
  182. if (left == 0) m.Branch(m.Word32Equal(p1, p0), &blocka, &blockb);
  183. m.Bind(&blocka);
  184. m.Return(m.Int32Constant(eq_constant));
  185. m.Bind(&blockb);
  186. m.Return(m.Int32Constant(ne_constant));
  187. FOR_INT32_INPUTS(j) {
  188. int32_t b = *j;
  189. int32_t expect = a == b ? eq_constant : ne_constant;
  190. CHECK_EQ(expect, m.Call(b));
  191. }
  192. }
  193. }
  194. }
  195. TEST(BranchCombineInt32CmpP) {
  196. int32_t eq_constant = -1235;
  197. int32_t ne_constant = 725018;
  198. for (int op = 0; op < 2; op++) {
  199. RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32);
  200. Node* p0 = m.Parameter(0);
  201. Node* p1 = m.Parameter(1);
  202. MLabel blocka, blockb;
  203. if (op == 0) m.Branch(m.Int32LessThan(p0, p1), &blocka, &blockb);
  204. if (op == 1) m.Branch(m.Int32LessThanOrEqual(p0, p1), &blocka, &blockb);
  205. m.Bind(&blocka);
  206. m.Return(m.Int32Constant(eq_constant));
  207. m.Bind(&blockb);
  208. m.Return(m.Int32Constant(ne_constant));
  209. FOR_INT32_INPUTS(i) {
  210. FOR_INT32_INPUTS(j) {
  211. int32_t a = *i;
  212. int32_t b = *j;
  213. int32_t expect = 0;
  214. if (op == 0) expect = a < b ? eq_constant : ne_constant;
  215. if (op == 1) expect = a <= b ? eq_constant : ne_constant;
  216. CHECK_EQ(expect, m.Call(a, b));
  217. }
  218. }
  219. }
  220. }
  221. TEST(BranchCombineInt32CmpI) {
  222. int32_t eq_constant = -1175;
  223. int32_t ne_constant = 927711;
  224. for (int op = 0; op < 2; op++) {
  225. FOR_INT32_INPUTS(i) {
  226. RawMachineAssemblerTester<int32_t> m(kMachInt32);
  227. int32_t a = *i;
  228. Node* p0 = m.Int32Constant(a);
  229. Node* p1 = m.Parameter(0);
  230. MLabel blocka, blockb;
  231. if (op == 0) m.Branch(m.Int32LessThan(p0, p1), &blocka, &blockb);
  232. if (op == 1) m.Branch(m.Int32LessThanOrEqual(p0, p1), &blocka, &blockb);
  233. m.Bind(&blocka);
  234. m.Return(m.Int32Constant(eq_constant));
  235. m.Bind(&blockb);
  236. m.Return(m.Int32Constant(ne_constant));
  237. FOR_INT32_INPUTS(j) {
  238. int32_t b = *j;
  239. int32_t expect = 0;
  240. if (op == 0) expect = a < b ? eq_constant : ne_constant;
  241. if (op == 1) expect = a <= b ? eq_constant : ne_constant;
  242. CHECK_EQ(expect, m.Call(b));
  243. }
  244. }
  245. }
  246. }
  247. // Now come the sophisticated tests for many input shape combinations.
  248. // Materializes a boolean (1 or 0) from a comparison.
  249. class CmpMaterializeBoolGen : public BinopGen<int32_t> {
  250. public:
  251. CompareWrapper w;
  252. bool invert;
  253. CmpMaterializeBoolGen(IrOpcode::Value opcode, bool i)
  254. : w(opcode), invert(i) {}
  255. virtual void gen(RawMachineAssemblerTester<int32_t>* m, Node* a, Node* b) {
  256. Node* cond = w.MakeNode(m, a, b);
  257. if (invert) cond = m->Word32Equal(cond, m->Int32Constant(0));
  258. m->Return(cond);
  259. }
  260. virtual int32_t expected(int32_t a, int32_t b) {
  261. if (invert) return !w.Int32Compare(a, b) ? 1 : 0;
  262. return w.Int32Compare(a, b) ? 1 : 0;
  263. }
  264. };
  265. // Generates a branch and return one of two values from a comparison.
  266. class CmpBranchGen : public BinopGen<int32_t> {
  267. public:
  268. CompareWrapper w;
  269. bool invert;
  270. bool true_first;
  271. int32_t eq_constant;
  272. int32_t ne_constant;
  273. CmpBranchGen(IrOpcode::Value opcode, bool i, bool t, int32_t eq, int32_t ne)
  274. : w(opcode), invert(i), true_first(t), eq_constant(eq), ne_constant(ne) {}
  275. virtual void gen(RawMachineAssemblerTester<int32_t>* m, Node* a, Node* b) {
  276. MLabel blocka, blockb;
  277. Node* cond = w.MakeNode(m, a, b);
  278. if (invert) cond = m->Word32Equal(cond, m->Int32Constant(0));
  279. m->Branch(cond, &blocka, &blockb);
  280. if (true_first) {
  281. m->Bind(&blocka);
  282. m->Return(m->Int32Constant(eq_constant));
  283. m->Bind(&blockb);
  284. m->Return(m->Int32Constant(ne_constant));
  285. } else {
  286. m->Bind(&blockb);
  287. m->Return(m->Int32Constant(ne_constant));
  288. m->Bind(&blocka);
  289. m->Return(m->Int32Constant(eq_constant));
  290. }
  291. }
  292. virtual int32_t expected(int32_t a, int32_t b) {
  293. if (invert) return !w.Int32Compare(a, b) ? eq_constant : ne_constant;
  294. return w.Int32Compare(a, b) ? eq_constant : ne_constant;
  295. }
  296. };
  297. TEST(BranchCombineInt32CmpAllInputShapes_materialized) {
  298. for (size_t i = 0; i < arraysize(int32cmp_opcodes); i++) {
  299. CmpMaterializeBoolGen gen(int32cmp_opcodes[i], false);
  300. Int32BinopInputShapeTester tester(&gen);
  301. tester.TestAllInputShapes();
  302. }
  303. }
  304. TEST(BranchCombineInt32CmpAllInputShapes_inverted_materialized) {
  305. for (size_t i = 0; i < arraysize(int32cmp_opcodes); i++) {
  306. CmpMaterializeBoolGen gen(int32cmp_opcodes[i], true);
  307. Int32BinopInputShapeTester tester(&gen);
  308. tester.TestAllInputShapes();
  309. }
  310. }
  311. TEST(BranchCombineInt32CmpAllInputShapes_branch_true) {
  312. for (int i = 0; i < static_cast<int>(arraysize(int32cmp_opcodes)); i++) {
  313. CmpBranchGen gen(int32cmp_opcodes[i], false, false, 995 + i, -1011 - i);
  314. Int32BinopInputShapeTester tester(&gen);
  315. tester.TestAllInputShapes();
  316. }
  317. }
  318. TEST(BranchCombineInt32CmpAllInputShapes_branch_false) {
  319. for (int i = 0; i < static_cast<int>(arraysize(int32cmp_opcodes)); i++) {
  320. CmpBranchGen gen(int32cmp_opcodes[i], false, true, 795 + i, -2011 - i);
  321. Int32BinopInputShapeTester tester(&gen);
  322. tester.TestAllInputShapes();
  323. }
  324. }
  325. TEST(BranchCombineInt32CmpAllInputShapes_inverse_branch_true) {
  326. for (int i = 0; i < static_cast<int>(arraysize(int32cmp_opcodes)); i++) {
  327. CmpBranchGen gen(int32cmp_opcodes[i], true, false, 695 + i, -3011 - i);
  328. Int32BinopInputShapeTester tester(&gen);
  329. tester.TestAllInputShapes();
  330. }
  331. }
  332. TEST(BranchCombineInt32CmpAllInputShapes_inverse_branch_false) {
  333. for (int i = 0; i < static_cast<int>(arraysize(int32cmp_opcodes)); i++) {
  334. CmpBranchGen gen(int32cmp_opcodes[i], true, true, 595 + i, -4011 - i);
  335. Int32BinopInputShapeTester tester(&gen);
  336. tester.TestAllInputShapes();
  337. }
  338. }
  339. TEST(BranchCombineFloat64Compares) {
  340. double inf = V8_INFINITY;
  341. double nan = std::numeric_limits<double>::quiet_NaN();
  342. double inputs[] = {0.0, 1.0, -1.0, -inf, inf, nan};
  343. int32_t eq_constant = -1733;
  344. int32_t ne_constant = 915118;
  345. double input_a = 0.0;
  346. double input_b = 0.0;
  347. CompareWrapper cmps[] = {CompareWrapper(IrOpcode::kFloat64Equal),
  348. CompareWrapper(IrOpcode::kFloat64LessThan),
  349. CompareWrapper(IrOpcode::kFloat64LessThanOrEqual)};
  350. for (size_t c = 0; c < arraysize(cmps); c++) {
  351. CompareWrapper cmp = cmps[c];
  352. for (int invert = 0; invert < 2; invert++) {
  353. RawMachineAssemblerTester<int32_t> m;
  354. Node* a = m.LoadFromPointer(&input_a, kMachFloat64);
  355. Node* b = m.LoadFromPointer(&input_b, kMachFloat64);
  356. MLabel blocka, blockb;
  357. Node* cond = cmp.MakeNode(&m, a, b);
  358. if (invert) cond = m.Word32Equal(cond, m.Int32Constant(0));
  359. m.Branch(cond, &blocka, &blockb);
  360. m.Bind(&blocka);
  361. m.Return(m.Int32Constant(eq_constant));
  362. m.Bind(&blockb);
  363. m.Return(m.Int32Constant(ne_constant));
  364. for (size_t i = 0; i < arraysize(inputs); ++i) {
  365. for (size_t j = 0; j < arraysize(inputs); ++j) {
  366. input_a = inputs[i];
  367. input_b = inputs[j];
  368. int32_t expected =
  369. invert ? (cmp.Float64Compare(input_a, input_b) ? ne_constant
  370. : eq_constant)
  371. : (cmp.Float64Compare(input_a, input_b) ? eq_constant
  372. : ne_constant);
  373. CHECK_EQ(expected, m.Call());
  374. }
  375. }
  376. }
  377. }
  378. }
  379. #endif // V8_TURBOFAN_TARGET