dimreduce.mli 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. (** Dimension reduction: transform multi-dimensional arrays to one-dimensional
  2. arrays, and pass original array dimensions in function calls. *)
  3. (**
  4. This phase lowers multi-dimensional arrays to one-dimensional arrays. This
  5. transformation is done in two steps.
  6. In the first step, function calls and function parameter lists are modified.
  7. For function calls, array dimensions are passed as explicit arguments before
  8. the array argument itself. Naturally, function declarations need to be
  9. modified accordingly, adding explicit parameters for array dimensions.
  10. Similarly, dimensions of imported arrays are moved into new integer
  11. variables.
  12. In the second step, statements and expressions involving multi-dimensional
  13. array referencing are transformed such that they reference a one-dimensional
  14. array. Variable declarations with type [ArrayDims] are transformed into
  15. variables of type [Array], thus removing the dimensionality information.
  16. Allocation statements become one-dimensional allocations with a length that
  17. is the product of all array dimensions. Indexing multi-dimensional arrays is
  18. changed such that arrays are accessed in row-major order.
  19. Original code ([x], [y] and [z] are defined elsewhere):
  20. {v extern int[u] ext;
  21. void foo(int[a, b, c] p) \{
  22. int[5, 10, 3] q;
  23. q[x, y, z] = p[x, y, z];
  24. foo(q);
  25. \} v}
  26. Input for dimension reduction (we use [n], [m] and [k] for readability but
  27. in reality these are generated variables):
  28. {v extern int[__ext_0] ext; // dimensions are encoded in type
  29. void foo(int[a, b, c] p) \{
  30. int n; int m; int k; int[n, m, k] q; // n, m, k are added during desugaring
  31. n = 5;
  32. m = 10;
  33. k = 3;
  34. q = __allocate(n, m, k);
  35. q[x, y, z] = p[x, y, z];
  36. foo(q);
  37. \} v}
  38. step 1:
  39. {v extern int __ext_0; // imported dimensions moved to new variables
  40. extern int[__ext_0] ext;
  41. void foo(int a, int b, int c, int[a, b, c] p) \{ // array parameter
  42. int n; int m; int k; int[n, m, k] q;
  43. n = 5;
  44. m = 10;
  45. k = 3;
  46. q = __allocate(n, m, k);
  47. q[x, y, z] = p[x, y, z];
  48. foo(n, m, k, q); // array argument
  49. \} v}
  50. step 2:
  51. {v extern int __ext_0;
  52. extern int[] ext; // removing dimension information
  53. void foo(int a, int b, int c, int[] p) \{
  54. int n; int m; int k; int[] q; // removing dimension information
  55. n = 5;
  56. m = 10;
  57. k = 3;
  58. q = __allocate(n * m * k); // allocation
  59. q[((x * m) + y) * k + z] = p[((x * b) + y) * c + z]; // indexing
  60. foo(n, m, k, q);
  61. \} v}
  62. Note that when array dimensions are constant integer values, an array index
  63. may be simplified to a single constant value during contant propagation.
  64. *)
  65. (** Main phase function, called by {!Main}. *)
  66. val phase : Main.phase_func