memcopy.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. // Compares the value set by interpreter with the jitted code
  6. // need to run with -mic:1 -off:simplejit -off:jitloopbody -off:inline -off:globopt:1.18-1.30
  7. // Run locally with -trace:memop -trace:bailout to help find bugs
  8. let testCases = [
  9. function() {
  10. return {
  11. start: 0,
  12. end: 100,
  13. test: function testBasic(a, src) {
  14. for(let i = 0; i < 100; i++) {
  15. a[i] = src[i];
  16. }
  17. }
  18. };
  19. },
  20. function() {
  21. return {
  22. start: 0,
  23. end: 100,
  24. test: function testChangedIndex(a, src) {
  25. // This is an invalid memcopy
  26. for(let i = 0; i < 100;) {
  27. a[i] = src[++i];
  28. }
  29. }
  30. };
  31. },
  32. function() {
  33. let src = new Array(100);
  34. for(let i = 0; i < 100; ++i) {
  35. src[i] = i;
  36. }
  37. return {
  38. start: 0,
  39. end: 100,
  40. test: function testLdSlot(a) {
  41. // Invalid pattern, src is not considered invariant
  42. for(let i = 0; i < 100; ++i) {
  43. a[i] = src[i];
  44. }
  45. }
  46. };
  47. },
  48. function() {
  49. let start = 5, end = 101;
  50. return {
  51. start: start,
  52. end: end,
  53. size: end,
  54. test: function testReverse(a, src) {
  55. // Currently this is not a valid memcopy pattern
  56. for(let i = 100; i >= 5; i--) {
  57. a[i] = src[i];
  58. }
  59. }
  60. };
  61. },
  62. function() {
  63. let results = [];
  64. let start = 0, end = 10;
  65. return {
  66. start: start,
  67. end: end,
  68. runner: function testMultipleMemcopy(arrayGen, src) {
  69. let a = arrayGen(), b = arrayGen(), c = arrayGen();
  70. // Currently this is not a valid memcopy pattern (would it be more performant?)
  71. for(let i = 0; i < 10; i++) {
  72. a[i] = b[i] = c[i] = src[i];
  73. }
  74. results.push([a, b, c]);
  75. },
  76. check: function() {
  77. let base = results[0];
  78. for(let i = 1; i < results.length; ++i) {
  79. for(let j = 0; j < 3; ++j) {
  80. compareResult("testMultipleMemcopy", base[j], results[i][j], start, end);
  81. }
  82. }
  83. }
  84. };
  85. },
  86. function() {
  87. return {
  88. start: 0,
  89. end: 10,
  90. test: function preIncr(a, src) {
  91. let ri = -1;
  92. for(let i = 0; i < 10; ++i) {
  93. a[++ri] = src[ri];
  94. }
  95. }
  96. };
  97. },
  98. function() {
  99. return {
  100. start: -50,
  101. end: 10,
  102. loop: 10, // Run this a few times to cause rejit,
  103. test: function testNegativeStartIndex(a, src) {
  104. for(let i = -50; i < 10; i++) {
  105. // This should bailout on MemOp because the index will be negative
  106. a[i] = src[i];
  107. }
  108. }
  109. };
  110. },
  111. function() {
  112. return {
  113. start: 0,
  114. end: 128,
  115. test: function bug4468518(a, src) {
  116. let x = 0;
  117. for(let i = 0; i < 128; i++) {
  118. let m = src[i];
  119. x += m;
  120. a[i] = m;
  121. }
  122. return x;
  123. }
  124. };
  125. }
  126. ];
  127. let passed = true;
  128. function compareResult(name, a, b, start, end, start2) {
  129. for(let i = start, j = start2 || start; i < end; ++i, ++j) {
  130. if(a[i] !== b[j]) {
  131. print(`Error ${name}: a[${i}](${a[i]}) !== b[${j}](${b[j]})`);
  132. passed = false;
  133. return false;
  134. }
  135. }
  136. return true;
  137. }
  138. function makeArray(size) {
  139. size = size || 10;
  140. let a = new Array(size);
  141. for(let i = 0; i < size; ++i) {
  142. a[i] = 0;
  143. }
  144. return a;
  145. }
  146. let arrayGenerators = [
  147. makeArray,
  148. ];
  149. function makeSource(size) {
  150. let s = new Array(size);
  151. for(let i = 0; i < size; ++i) {
  152. s[i] = i;
  153. }
  154. return s;
  155. }
  156. for(let testCase of testCases) {
  157. let results = [];
  158. let testInfo = testCase();
  159. let name = testInfo.runner && testInfo.runner.name || testInfo.test && testInfo.test.name || "Unknown";
  160. let src;
  161. if(!testInfo.makeSource) {
  162. if (testInfo.size !== undefined) {
  163. src = makeSource(testInfo.size);
  164. } else if(
  165. testInfo.start !== undefined &&
  166. testInfo.end !== undefined
  167. ) {
  168. src = makeSource(testInfo.end - testInfo.start);
  169. }
  170. }
  171. function run(gen) {
  172. if(testInfo.makeSource) {
  173. src = testInfo.makeSource();
  174. }
  175. if(testInfo.runner) {
  176. let result = testInfo.runner(gen, src);
  177. results.push(result);
  178. } else {
  179. let newArray = gen(testInfo.size);
  180. newArray.fill(1);
  181. testInfo.test(newArray, src);
  182. results.push(newArray);
  183. }
  184. }
  185. // Run once for the interpreter
  186. run(makeArray);
  187. for(let gen of arrayGenerators) {
  188. if(testInfo.loop | 0) {
  189. for(let i = 0; i < testInfo.loop; ++i) {
  190. run(gen);
  191. }
  192. } else {
  193. run(gen);
  194. }
  195. }
  196. if(testInfo.check) {
  197. testInfo.check(results);
  198. } else {
  199. let base = results[0]; // result from the interpreter
  200. for(let i = 1; i < results.length; ++i) {
  201. compareResult(name, base, results[i], testInfo.start, testInfo.end);
  202. }
  203. }
  204. }
  205. if(passed) {
  206. print("PASSED");
  207. } else {
  208. print("FAILED");
  209. }