memcopy.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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. for(let i = 100; i >= 5; i--) {
  56. a[i] = src[i];
  57. }
  58. }
  59. };
  60. },
  61. function() {
  62. let results = [];
  63. let start = 0, end = 10;
  64. return {
  65. start: start,
  66. end: end,
  67. runner: function testMultipleMemcopy(arrayGen, src) {
  68. let a = arrayGen(), b = arrayGen(), c = arrayGen();
  69. // Currently this is not a valid memcopy pattern (would it be more performant?)
  70. for(let i = 0; i < 10; i++) {
  71. a[i] = b[i] = c[i] = src[i];
  72. }
  73. results.push([a, b, c]);
  74. },
  75. check: function() {
  76. let base = results[0];
  77. for(let i = 1; i < results.length; ++i) {
  78. for(let j = 0; j < 3; ++j) {
  79. compareResult("testMultipleMemcopy", base[j], results[i][j], start, end);
  80. }
  81. }
  82. }
  83. };
  84. },
  85. function() {
  86. return {
  87. start: 0,
  88. end: 10,
  89. test: function preIncr(a, src) {
  90. let ri = -1;
  91. for(let i = 0; i < 10; ++i) {
  92. a[++ri] = src[ri];
  93. }
  94. }
  95. };
  96. },
  97. function() {
  98. return {
  99. start: -50,
  100. end: 10,
  101. loop: 10, // Run this a few times to cause rejit,
  102. test: function testNegativeStartIndex(a, src) {
  103. for(let i = -50; i < 10; i++) {
  104. // This should bailout on MemOp because the index will be negative
  105. a[i] = src[i];
  106. }
  107. }
  108. };
  109. },
  110. function() {
  111. return {
  112. start: 0,
  113. end: 128,
  114. test: function bug4468518(a, src) {
  115. let x = 0;
  116. for(let i = 0; i < 128; i++) {
  117. let m = src[i];
  118. x += m;
  119. a[i] = m;
  120. }
  121. return x;
  122. }
  123. };
  124. }
  125. ];
  126. let passed = true;
  127. function compareResult(name, a, b, start, end, start2) {
  128. for(let i = start, j = start2 || start; i < end; ++i, ++j) {
  129. if(a[i] !== b[j]) {
  130. print(`Error ${name}: a[${i}](${a[i]}) !== b[${j}](${b[j]})`);
  131. passed = false;
  132. return false;
  133. }
  134. }
  135. return true;
  136. }
  137. const isFloatTest = WScript.Arguments[0] === "float";
  138. function makeArray(size = 10) {
  139. let a = new Array(size);
  140. for(let i = 0; i < size; ++i) {
  141. a[i] = isFloatTest ? 0.5 : 0;
  142. }
  143. if (isFloatTest) {
  144. return eval(`[${a.join(", ")}]`);
  145. }
  146. return a;
  147. }
  148. let arrayGenerators = [
  149. makeArray,
  150. ];
  151. function makeFloatArray(size = 10) {
  152. const arrayValues = new Array(size);
  153. for(let i = 0; i < size; ++i) {
  154. arrayValues[i] = Math.random() / Math.random() * (Math.random() < 0.2 ? -1 : 1);
  155. }
  156. return eval(`[${arrayValues.join(", ")}]`);
  157. }
  158. function makeSource(size = 10) {
  159. if (isFloatTest) return makeFloatArray(size);
  160. let s = new Array(size);
  161. for(let i = 0; i < size; ++i) {
  162. s[i] = i;
  163. }
  164. return s;
  165. }
  166. for(let testCase of testCases) {
  167. let results = [];
  168. let testInfo = testCase();
  169. let name = testInfo.runner && testInfo.runner.name || testInfo.test && testInfo.test.name || "Unknown";
  170. let src;
  171. if(!testInfo.makeSource) {
  172. if (testInfo.size !== undefined) {
  173. src = makeSource(testInfo.size);
  174. } else if(
  175. testInfo.start !== undefined &&
  176. testInfo.end !== undefined
  177. ) {
  178. src = makeSource(testInfo.end - testInfo.start);
  179. }
  180. }
  181. function run(gen) {
  182. if(testInfo.makeSource) {
  183. src = testInfo.makeSource();
  184. }
  185. if(testInfo.runner) {
  186. let result = testInfo.runner(gen, src);
  187. results.push(result);
  188. } else {
  189. let newArray = gen(testInfo.size || testInfo.end - testInfo.start);
  190. testInfo.test(newArray, src);
  191. results.push(newArray);
  192. }
  193. }
  194. // Run once for the interpreter
  195. run(makeArray);
  196. for(let gen of arrayGenerators) {
  197. if(testInfo.loop | 0) {
  198. for(let i = 0; i < testInfo.loop; ++i) {
  199. run(gen);
  200. }
  201. } else {
  202. run(gen);
  203. }
  204. }
  205. if(testInfo.check) {
  206. testInfo.check(results);
  207. } else {
  208. let base = results[0]; // result from the interpreter
  209. for(let i = 1; i < results.length; ++i) {
  210. compareResult(name, base, results[i], testInfo.start, testInfo.end);
  211. }
  212. }
  213. }
  214. if(passed) {
  215. print("PASSED");
  216. } else {
  217. print("FAILED");
  218. }