bones-compiler 1.1.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. checksums.yaml +15 -0
  2. data/CHANGELOG +37 -0
  3. data/LICENSE +1 -1
  4. data/README.rdoc +95 -70
  5. data/Rakefile +78 -3
  6. data/VERSION +1 -1
  7. data/bin/adarwin +17 -0
  8. data/examples/benchmarks/PolyBench/2mm.c +104 -0
  9. data/examples/benchmarks/{3mm.c → PolyBench/3mm.c} +5 -2
  10. data/examples/benchmarks/{adi.c → PolyBench/adi.c} +6 -3
  11. data/examples/benchmarks/{atax.c → PolyBench/atax.c} +5 -2
  12. data/examples/benchmarks/{bicg.c → PolyBench/bicg.c} +5 -2
  13. data/examples/benchmarks/{cholesky.c → PolyBench/cholesky.c} +3 -0
  14. data/examples/benchmarks/{common.h → PolyBench/common.h} +2 -2
  15. data/examples/benchmarks/{correlation.c → PolyBench/correlation.c} +16 -7
  16. data/examples/benchmarks/{covariance.c → PolyBench/covariance.c} +7 -2
  17. data/examples/benchmarks/{doitgen.c → PolyBench/doitgen.c} +5 -2
  18. data/examples/benchmarks/{durbin.c → PolyBench/durbin.c} +3 -0
  19. data/examples/benchmarks/{dynprog.c → PolyBench/dynprog.c} +3 -0
  20. data/examples/benchmarks/{fdtd-2d-apml.c → PolyBench/fdtd-2d-apml.c} +3 -0
  21. data/examples/benchmarks/{fdtd-2d.c → PolyBench/fdtd-2d.c} +5 -2
  22. data/examples/benchmarks/{floyd-warshall.c → PolyBench/floyd-warshall.c} +3 -0
  23. data/examples/benchmarks/{gemm.c → PolyBench/gemm.c} +5 -2
  24. data/examples/benchmarks/{gemver.c → PolyBench/gemver.c} +5 -2
  25. data/examples/benchmarks/{gesummv.c → PolyBench/gesummv.c} +5 -2
  26. data/examples/benchmarks/{gramschmidt.c → PolyBench/gramschmidt.c} +3 -0
  27. data/examples/benchmarks/{jacobi-1d-imper.c → PolyBench/jacobi-1d-imper.c} +10 -2
  28. data/examples/benchmarks/{jacobi-2d-imper.c → PolyBench/jacobi-2d-imper.c} +8 -3
  29. data/examples/benchmarks/{lu.c → PolyBench/lu.c} +3 -0
  30. data/examples/benchmarks/{ludcmp.c → PolyBench/ludcmp.c} +3 -0
  31. data/examples/benchmarks/{mvt.c → PolyBench/mvt.c} +6 -2
  32. data/examples/benchmarks/{reg_detect.c → PolyBench/reg_detect.c} +3 -0
  33. data/examples/benchmarks/{seidel-2d.c → PolyBench/seidel-2d.c} +3 -0
  34. data/examples/benchmarks/{symm.c → PolyBench/symm.c} +3 -0
  35. data/examples/benchmarks/{syr2k.c → PolyBench/syr2k.c} +5 -2
  36. data/examples/benchmarks/{syrk.c → PolyBench/syrk.c} +7 -4
  37. data/examples/benchmarks/{trisolv.c → PolyBench/trisolv.c} +3 -0
  38. data/examples/benchmarks/{trmm.c → PolyBench/trmm.c} +3 -0
  39. data/examples/benchmarks/Rodinia/cfd.c +180 -0
  40. data/examples/benchmarks/Rodinia/hotspot.c +228 -0
  41. data/examples/benchmarks/Rodinia/kmeans.c +164 -0
  42. data/examples/benchmarks/Rodinia/srad.c +188 -0
  43. data/examples/benchmarks/other/common.h +0 -0
  44. data/examples/benchmarks/other/dct.c +58 -0
  45. data/examples/benchmarks/other/mm.c +50 -0
  46. data/examples/benchmarks/{saxpy.c → other/saxpy.c} +11 -7
  47. data/examples/chunk/{example1.c → example01.c} +0 -0
  48. data/examples/chunk/{example2.c → example02.c} +0 -0
  49. data/examples/chunk/{example3.c → example03.c} +0 -0
  50. data/examples/chunk/{example4.c → example04.c} +0 -0
  51. data/examples/chunk/{example5.c → example05.c} +0 -0
  52. data/examples/chunk/example06.c +45 -0
  53. data/examples/chunk/example07.c +49 -0
  54. data/examples/dependences/example01.c +42 -0
  55. data/examples/dependences/example02.c +40 -0
  56. data/examples/dependences/example03.c +43 -0
  57. data/examples/dependences/example04.c +44 -0
  58. data/examples/dependences/example05.c +42 -0
  59. data/examples/element/{example1.c → example01.c} +0 -0
  60. data/examples/element/{example2.c → example02.c} +2 -2
  61. data/examples/element/{example3.c → example03.c} +0 -0
  62. data/examples/element/{example4.c → example04.c} +0 -0
  63. data/examples/element/{example5.c → example05.c} +0 -0
  64. data/examples/element/{example6.c → example06.c} +0 -0
  65. data/examples/element/{example7.c → example07.c} +0 -0
  66. data/examples/element/{example8.c → example08.c} +0 -0
  67. data/examples/element/{example9.c → example09.c} +0 -0
  68. data/examples/element/example13.c +73 -0
  69. data/examples/fusion/example01.c +68 -0
  70. data/examples/fusion/example02.c +73 -0
  71. data/examples/fusion/example03.c +72 -0
  72. data/examples/fusion/example04.c +61 -0
  73. data/examples/fusion/example05.c +55 -0
  74. data/examples/neighbourhood/{example1.c → example01.c} +0 -0
  75. data/examples/neighbourhood/{example2.c → example02.c} +0 -0
  76. data/examples/neighbourhood/{example3.c → example03.c} +0 -0
  77. data/examples/neighbourhood/{example4.c → example04.c} +0 -0
  78. data/examples/neighbourhood/example05.c +44 -0
  79. data/examples/shared/{example1.c → example01.c} +0 -0
  80. data/examples/shared/{example2.c → example02.c} +0 -0
  81. data/examples/shared/{example3.c → example03.c} +0 -0
  82. data/examples/shared/{example4.c → example04.c} +0 -0
  83. data/examples/shared/{example5.c → example05.c} +0 -0
  84. data/lib/adarwin.rb +62 -0
  85. data/lib/adarwin/dependences.rb +268 -0
  86. data/lib/adarwin/engine.rb +277 -0
  87. data/lib/adarwin/fusion.rb +174 -0
  88. data/lib/adarwin/interval.rb +57 -0
  89. data/lib/adarwin/memorycopies.rb +153 -0
  90. data/lib/adarwin/nest.rb +225 -0
  91. data/lib/adarwin/preprocessor.rb +76 -0
  92. data/lib/adarwin/reference.rb +261 -0
  93. data/lib/bones.rb +4 -55
  94. data/lib/bones/algorithm.rb +77 -40
  95. data/lib/bones/copy.rb +26 -0
  96. data/lib/bones/engine.rb +147 -31
  97. data/lib/bones/preprocessor.rb +92 -12
  98. data/lib/bones/species.rb +4 -3
  99. data/lib/bones/structure.rb +14 -4
  100. data/lib/castaddon.rb +11 -6
  101. data/lib/castaddon/node_adarwin.rb +245 -0
  102. data/lib/castaddon/node_bones.rb +316 -0
  103. data/lib/castaddon/node_common.rb +289 -0
  104. data/lib/castaddon/transformations.rb +236 -0
  105. data/lib/common.rb +216 -0
  106. data/skeletons/CPU-C/common/header.c +3 -0
  107. data/skeletons/CPU-C/common/mem_global.c +0 -0
  108. data/skeletons/CPU-C/common/timer_2_start.c +11 -13
  109. data/skeletons/CPU-C/common/timer_2_stop.c +1 -1
  110. data/skeletons/CPU-C/common/timer_globals.c +29 -0
  111. data/skeletons/CPU-OPENCL-INTEL/common/globals.c +1 -1
  112. data/skeletons/CPU-OPENCL-INTEL/common/header.c +3 -0
  113. data/skeletons/CPU-OPENCL-INTEL/common/mem_copy_D2H.c +7 -2
  114. data/skeletons/CPU-OPENCL-INTEL/common/mem_copy_H2D.c +4 -2
  115. data/skeletons/CPU-OPENCL-INTEL/common/mem_global.c +0 -0
  116. data/skeletons/CPU-OPENCL-INTEL/common/mem_prologue.c +6 -3
  117. data/skeletons/CPU-OPENCL-INTEL/common/timer_2_stop.c +1 -1
  118. data/skeletons/CPU-OPENCL-INTEL/common/timer_globals.c +24 -0
  119. data/skeletons/CPU-OPENMP/common/globals.c +1 -0
  120. data/skeletons/CPU-OPENMP/common/header.c +3 -0
  121. data/skeletons/CPU-OPENMP/common/mem_global.c +0 -0
  122. data/skeletons/CPU-OPENMP/common/timer_1_start.c +0 -12
  123. data/skeletons/CPU-OPENMP/common/timer_2_stop.c +1 -1
  124. data/skeletons/CPU-OPENMP/common/timer_globals.c +33 -0
  125. data/skeletons/GPU-CUDA/common/globals.c +27 -3
  126. data/skeletons/GPU-CUDA/common/header.c +2 -0
  127. data/skeletons/GPU-CUDA/common/mem_async_alloc.c +6 -0
  128. data/skeletons/GPU-CUDA/common/mem_async_copyin.c +6 -0
  129. data/skeletons/GPU-CUDA/common/mem_async_copyout.c +6 -0
  130. data/skeletons/GPU-CUDA/common/mem_async_free.c +6 -0
  131. data/skeletons/GPU-CUDA/common/mem_copy_D2H.c +2 -1
  132. data/skeletons/GPU-CUDA/common/mem_copy_H2D.c +2 -1
  133. data/skeletons/GPU-CUDA/common/mem_global.c +1 -0
  134. data/skeletons/GPU-CUDA/common/mem_prologue.c +1 -2
  135. data/skeletons/GPU-CUDA/common/scheduler.c +86 -0
  136. data/skeletons/GPU-CUDA/common/timer_2_start.c +2 -4
  137. data/skeletons/GPU-CUDA/common/timer_2_stop.c +3 -5
  138. data/skeletons/GPU-CUDA/common/timer_globals.c +26 -0
  139. data/skeletons/GPU-CUDA/kernel/2xN-N-chunk-1-N-to-D-element.kernel.cu +5 -7
  140. data/skeletons/GPU-CUDA/kernel/N-N-chunk-1-N-to-D-element.kernel.cu +4 -6
  141. data/skeletons/GPU-CUDA/kernel/default.host.c +1 -1
  142. data/skeletons/GPU-CUDA/kernel/default.kernel.cu +6 -8
  143. data/skeletons/GPU-CUDA/skeletons.txt +6 -5
  144. data/{examples/benchmarks/2mm.c → test/examples/benchmarks/PolyBench/2mm_species.c} +19 -15
  145. data/test/examples/benchmarks/PolyBench/3mm_species.c +82 -0
  146. data/test/examples/benchmarks/PolyBench/adi_species.c +89 -0
  147. data/test/examples/benchmarks/PolyBench/atax_species.c +69 -0
  148. data/test/examples/benchmarks/PolyBench/bicg_species.c +71 -0
  149. data/test/examples/benchmarks/PolyBench/cholesky_species.c +68 -0
  150. data/test/examples/benchmarks/PolyBench/correlation_species.c +97 -0
  151. data/test/examples/benchmarks/PolyBench/covariance_species.c +78 -0
  152. data/test/examples/benchmarks/PolyBench/doitgen_species.c +67 -0
  153. data/test/examples/benchmarks/PolyBench/durbin_species.c +80 -0
  154. data/test/examples/benchmarks/PolyBench/dynprog_species.c +71 -0
  155. data/test/examples/benchmarks/PolyBench/fdtd-2d-apml_species.c +112 -0
  156. data/test/examples/benchmarks/PolyBench/fdtd-2d_species.c +78 -0
  157. data/test/examples/benchmarks/PolyBench/floyd-warshall_species.c +54 -0
  158. data/test/examples/benchmarks/PolyBench/gemm_species.c +73 -0
  159. data/test/examples/benchmarks/PolyBench/gemver_species.c +93 -0
  160. data/test/examples/benchmarks/PolyBench/gesummv_species.c +68 -0
  161. data/test/examples/benchmarks/PolyBench/gramschmidt_species.c +78 -0
  162. data/test/examples/benchmarks/PolyBench/jacobi-1d-imper_species.c +59 -0
  163. data/test/examples/benchmarks/PolyBench/jacobi-2d-imper_species.c +65 -0
  164. data/test/examples/benchmarks/PolyBench/lu_species.c +57 -0
  165. data/test/examples/benchmarks/PolyBench/ludcmp_species.c +89 -0
  166. data/test/examples/benchmarks/PolyBench/mvt_species.c +69 -0
  167. data/test/examples/benchmarks/PolyBench/reg_detect_species.c +86 -0
  168. data/test/examples/benchmarks/PolyBench/seidel-2d_species.c +53 -0
  169. data/test/examples/benchmarks/PolyBench/symm_species.c +74 -0
  170. data/test/examples/benchmarks/PolyBench/syr2k_species.c +69 -0
  171. data/test/examples/benchmarks/PolyBench/syrk_species.c +66 -0
  172. data/test/examples/benchmarks/PolyBench/trisolv_species.c +61 -0
  173. data/test/examples/benchmarks/PolyBench/trmm_species.c +61 -0
  174. data/test/examples/chunk/example01_species.c +58 -0
  175. data/test/examples/chunk/example02_species.c +48 -0
  176. data/test/examples/chunk/example03_species.c +63 -0
  177. data/test/examples/chunk/example04_species.c +58 -0
  178. data/test/examples/chunk/example05_species.c +56 -0
  179. data/test/examples/chunk/example06_species.c +49 -0
  180. data/test/examples/chunk/example07_species.c +53 -0
  181. data/test/examples/dependences/example01_species.c +46 -0
  182. data/test/examples/dependences/example02_species.c +44 -0
  183. data/test/examples/dependences/example03_species.c +47 -0
  184. data/test/examples/dependences/example04_species.c +48 -0
  185. data/test/examples/dependences/example05_species.c +46 -0
  186. data/test/examples/element/example01_species.c +50 -0
  187. data/test/examples/element/example02_species.c +50 -0
  188. data/test/examples/element/example03_species.c +62 -0
  189. data/test/examples/element/example04_species.c +53 -0
  190. data/test/examples/element/example05_species.c +59 -0
  191. data/test/examples/element/example06_species.c +50 -0
  192. data/test/examples/element/example07_species.c +58 -0
  193. data/test/examples/element/example08_species.c +49 -0
  194. data/test/examples/element/example09_species.c +52 -0
  195. data/test/examples/element/example10_species.c +54 -0
  196. data/test/examples/element/example11_species.c +51 -0
  197. data/test/examples/element/example12_species.c +60 -0
  198. data/test/examples/element/example13_species.c +77 -0
  199. data/test/examples/neighbourhood/example01_species.c +57 -0
  200. data/test/examples/neighbourhood/example02_species.c +56 -0
  201. data/test/examples/neighbourhood/example03_species.c +83 -0
  202. data/test/examples/neighbourhood/example04_species.c +55 -0
  203. data/test/examples/neighbourhood/example05_species.c +48 -0
  204. data/test/examples/shared/example01_species.c +49 -0
  205. data/test/examples/shared/example02_species.c +55 -0
  206. data/test/examples/shared/example03_species.c +59 -0
  207. data/test/examples/shared/example04_species.c +56 -0
  208. data/test/examples/shared/example05_species.c +52 -0
  209. metadata +193 -73
  210. data/examples/benchmarks/overview.txt +0 -38
  211. data/lib/castaddon/node.rb +0 -753
@@ -0,0 +1,289 @@
1
+
2
+ # This file provides the common methods that extend the CAST node
3
+ # class. These methods are used by both Bones and A-Darwin.
4
+ class C::Node
5
+
6
+ # This method searches for a variable name in the node and
7
+ # replaces it with the method's argument, which is given as
8
+ # a string. The node itself is modified. The method checks
9
+ # whether:
10
+ # * The node is a variable (+node.variable?+)
11
+ # * The variable has the correct name (+node.name == variable_name+)
12
+ # * The variable is not in a function call (+!node.parent.call?+)
13
+ def replace_variable(variable_name,replacement)
14
+ self.preorder do |node|
15
+ node.name = replacement if (node.variable?) && (node.name == variable_name) && (!node.parent.call?)
16
+ end
17
+ end
18
+
19
+ # This method searches for a target node and replaces it with
20
+ # a replacement node. Both the target node and the replacement
21
+ # node are given as arguments to the method. The method walks
22
+ # through the node and checks whether:
23
+ # * The node's class is the same as the target class (+node.class == target.class+)
24
+ # * The node has a parent (+node.parent != nil+)
25
+ # * The node is equal to the target node (+node.match?(target)+)
26
+ # If all checks are successful, the node will be replaced with
27
+ # the replacement node and the method will return immediately.
28
+ #
29
+ # The method returns itself if the target node cannot be
30
+ # found.
31
+ def search_and_replace_node(target,replacements)
32
+ if (self.class == target.class) && (self.match?(target))
33
+ return replacements
34
+ end
35
+ self.preorder do |node|
36
+ if (node.class == target.class) && (node.match?(target))
37
+ if (node.parent != nil)
38
+ node.replace_with(replacements)
39
+ else
40
+ return replacements
41
+ end
42
+ return self
43
+ end
44
+ end
45
+ return self
46
+ end
47
+
48
+ # This method is a small helper function to remove a node once.
49
+ def remove_once(target)
50
+ self.postorder do |node|
51
+ if node == target
52
+ node.detach
53
+ return self
54
+ end
55
+ end
56
+ return self
57
+ end
58
+
59
+ # This method is a small helper function which simply strips
60
+ # any outer brackets from a node. If no outer brackets are
61
+ # found, then nothing happens and the node itself is returned.
62
+ def strip_brackets
63
+ return (self.block?) ? self.stmts : self
64
+ end
65
+
66
+ # This method returns 'true' if the node is of the 'Variable'
67
+ # class. Otherwise, it returns 'false'.
68
+ def variable? ; (self.class == C::Variable) end
69
+
70
+ # This method returns 'true' if the node is of the 'Array'
71
+ # class. Otherwise, it returns 'false'.
72
+ def array?
73
+ return (self.class == C::Array)
74
+ end
75
+
76
+ # This method returns 'true' if the node is of the 'Pointer'
77
+ # class. Otherwise, it returns 'false'.
78
+ def pointer?
79
+ return (self.class == C::Pointer)
80
+ end
81
+
82
+ # This method returns 'true' if the node is of the 'Parameter'
83
+ # class. Otherwise, it returns 'false'.
84
+ def parameter?
85
+ return (self.class == C::Parameter)
86
+ end
87
+
88
+ # This method returns 'true' if the node is of the 'Declarator'
89
+ # class. Otherwise, it returns 'false'.
90
+ def declarator?
91
+ return (self.class == C::Declarator)
92
+ end
93
+
94
+ # This method returns 'true' if the node is of the 'Declaration'
95
+ # class. Otherwise, it returns 'false'.
96
+ def declaration?
97
+ return (self.class == C::Declaration)
98
+ end
99
+
100
+ # This method returns 'true' if the node is of the 'Index'
101
+ # class. Otherwise, it returns 'false'.
102
+ def index?
103
+ return (self.class == C::Index)
104
+ end
105
+
106
+ # This method returns 'true' if the node is of the 'Call'
107
+ # class. Otherwise, it returns 'false'.
108
+ def call?
109
+ return (self.class == C::Call)
110
+ end
111
+
112
+ # This method returns 'true' if the node is of the 'FunctionDef'
113
+ # class. Otherwise, it returns 'false'.
114
+ def function_definition?
115
+ return (self.class == C::FunctionDef)
116
+ end
117
+
118
+ # This method returns 'true' if the node is of the 'Declarator'
119
+ # class with its 'indirect_type' equal to 'Function' . Otherwise,
120
+ # it returns 'false'.
121
+ def function_declaration?
122
+ return (self.class == C::Declarator && self.indirect_type.class == C::Function)
123
+ end
124
+
125
+ # This method returns 'true' if the node is of the 'Block'
126
+ # class. Otherwise, it returns 'false'.
127
+ def block?
128
+ return (self.class == C::Block)
129
+ end
130
+
131
+ # This method returns 'true' if the node is of the 'For'
132
+ # class. Otherwise, it returns 'false'.
133
+ def for_statement?
134
+ return (self.class == C::For)
135
+ end
136
+
137
+ # This method returns 'true' if the node is of the 'If'
138
+ # class. Otherwise, it returns 'false'.
139
+ def if_statement?
140
+ return (self.class == C::If)
141
+ end
142
+
143
+ # This method returns 'true' if the node is of the 'And'
144
+ # class. Otherwise, it returns 'false'.
145
+ def and?
146
+ return (self.class == C::And)
147
+ end
148
+
149
+ # This method returns 'true' if the node is of the 'Or'
150
+ # class. Otherwise, it returns 'false'.
151
+ def or?
152
+ return (self.class == C::Or)
153
+ end
154
+
155
+ # This method returns 'true' if the node is of the 'Less'
156
+ # class. Otherwise, it returns 'false'.
157
+ def less?
158
+ return (self.class == C::Less)
159
+ end
160
+
161
+ # This method returns 'true' if the node is of the 'More'
162
+ # class. Otherwise, it returns 'false'.
163
+ def more?
164
+ return (self.class == C::More)
165
+ end
166
+
167
+ # This method returns 'true' if the node is of the 'LessOrEqual'
168
+ # class. Otherwise, it returns 'false'.
169
+ def less_or_equal?
170
+ return (self.class == C::LessOrEqual)
171
+ end
172
+
173
+ # This method returns 'true' if the node is of the 'MoreOrEqual'
174
+ # class. Otherwise, it returns 'false'.
175
+ def more_or_equal?
176
+ return (self.class == C::MoreOrEqual)
177
+ end
178
+
179
+ # This method returns 'true' if the node is of the 'Add'
180
+ # class. Otherwise, it returns 'false'.
181
+ def add?
182
+ return (self.class == C::Add)
183
+ end
184
+
185
+ # This method returns 'true' if the node is of the 'Subtract'
186
+ # class. Otherwise, it returns 'false'.
187
+ def subtract?
188
+ return (self.class == C::Subtract)
189
+ end
190
+
191
+ # This method returns 'true' if the node is of the 'AddAssign'
192
+ # class. Otherwise, it returns 'false'.
193
+ def addassign?
194
+ return (self.class == C::AddAssign)
195
+ end
196
+
197
+ # This method returns 'true' if the node is of the 'PostInc'
198
+ # class. Otherwise, it returns 'false'.
199
+ def postinc?
200
+ return (self.class == C::PostInc)
201
+ end
202
+
203
+ # This method returns 'true' if the node is of the 'PreInc'
204
+ # class. Otherwise, it returns 'false'.
205
+ def preinc?
206
+ return (self.class == C::PreInc)
207
+ end
208
+
209
+ # This method returns 'true' if the node is of the 'PostDec'
210
+ # class. Otherwise, it returns 'false'.
211
+ def postdec?
212
+ return (self.class == C::PostDec)
213
+ end
214
+
215
+ # This method returns 'true' if the node is of the 'PreDec'
216
+ # class. Otherwise, it returns 'false'.
217
+ def predec?
218
+ return (self.class == C::PreDec)
219
+ end
220
+
221
+ # This method returns 'true' if the node is of the 'IntLiteral'
222
+ # class. Otherwise, it returns 'false'.
223
+ def intliteral?
224
+ return (self.class == C::IntLiteral)
225
+ end
226
+
227
+ # This method returns 'true' if the node is of the 'Assign'
228
+ # class. Otherwise, it returns 'false'.
229
+ def assign?
230
+ return (self.class == C::Assign)
231
+ end
232
+
233
+ # This method returns 'true' if the node is of the 'Call'
234
+ # class. Otherwise, it returns 'false'.
235
+ def call?
236
+ return (self.class == C::Call)
237
+ end
238
+
239
+ # This method returns 'true' if the node is of the 'StringLiteral'
240
+ # class. Otherwise, it returns 'false'.
241
+ def string?
242
+ return (self.class == C::StringLiteral)
243
+ end
244
+
245
+ # This method returns 'true' if the node's class inherits
246
+ # from the 'BinaryExpression' class. Otherwise, it returns
247
+ # 'false'.
248
+ def binary_expression?
249
+ return (self.class.superclass == C::BinaryExpression)
250
+ end
251
+
252
+ # This method returns 'true' if the node's class inherits
253
+ # from the 'AssignmentExpression' class. Otherwise, it returns
254
+ # 'false'.
255
+ def assignment_expression?
256
+ return (self.class.superclass == C::AssignmentExpression)
257
+ end
258
+
259
+ # This method returns 'true' if the node is of the 'PostInc', 'PreInc'
260
+ # class or if it is of the 'Assign' class and adds with a value of 1.
261
+ # Otherwise, it returns 'false'.
262
+ def unit_increment?
263
+ return (self.class == C::PostInc) || (self.class == C::PreInc) || (self.class == C::Assign && self.rval.class == C::Add && self.rval.expr2.class == C::IntLiteral && self.rval.expr2.val == 1)
264
+ end
265
+
266
+ # This method returns 'true' if the node is performing an ALU
267
+ # operation. Otherwise, it returns 'false'.
268
+ def alu?
269
+ return add? || subtract? || addassign? || postinc? || postdec? || preinc? || predec? || binary_expression?
270
+ end
271
+
272
+ # This method returns 'true' if the node is of the 'ExpressionStatement'
273
+ # class. Otherwise, it returns 'false'.
274
+ def statement?
275
+ return (self.class == C::ExpressionStatement) || (self.class == C::Declaration)
276
+ end
277
+
278
+ # From this point on are the private methods.
279
+ private
280
+
281
+ # Override the existing 'indent' method to set the indent size
282
+ # manually.
283
+ def indent s, levels=1
284
+ space = INDENT
285
+ s.gsub(/^/, space)
286
+ end
287
+
288
+ end
289
+
@@ -0,0 +1,236 @@
1
+ # This class provides an extension to the CAST node class, which
2
+ # is a parent class for all other CAST classes. The extension
3
+ # consists of three different types of methods:
4
+ # * Methods starting with +transform_+, handling the major code transformations.
5
+ # * Methods to obtain information on variables, such as their direction and whether they are defined or not.
6
+ # * Helper methods, among others those that indicate whether a node is of a certain class.
7
+ class C::Node
8
+
9
+ # Method to enable the use of local memory for a list of
10
+ # array variables which is given as an argument to the method.
11
+ # The method walks through the node. First, it checks whether:
12
+ # * The node represents an array access (+node.index?+)
13
+ # * The node has a parent node (+node.parent+)
14
+ # Then, the method loops over all array variables. It checks
15
+ # one more thing: whether the array variable's name is the
16
+ # same as the name found in the array access node.
17
+ #
18
+ # If all conditions are met, the method performs two replacements:
19
+ # * The variable name is changed to correspond to local memory
20
+ # * The index names are changed to correspond to local indices
21
+ #
22
+ # The method performs the transformation on the node itself.
23
+ # Any old data is thus lost.
24
+ def transform_use_local_memory(arrays)
25
+ self.preorder do |node|
26
+ if (node.index?) && (node.parent)
27
+ arrays.each do |array|
28
+ if node.variable_name == array.name
29
+ node.variable_name = Bones::LOCAL_MEMORY+'_'+array.name
30
+ array.species.dimensions.each_with_index do |dimension,num_dimension|
31
+ node.replace_variable(Bones::GLOBAL_ID+'_'+num_dimension.to_s,Bones::LOCAL_ID+'_'+num_dimension.to_s)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ # This method transforms multi-dimensional arrays into 1D
40
+ # arrays. The target array variable list is given as argument.
41
+ # The method walks through the node. First, it checks whether:
42
+ # * The node represents an array access (+node.index?+)
43
+ # * The node has a parent node (+node.parent+)
44
+ # Then, the method loops over all array variables. It then
45
+ # checks two more things:
46
+ # * Whether the given name is the same as the name found in the array access node (+node.variable_name == array.name+)
47
+ # * Whether the dimensions of the given array are the same as the dimensions of the node (+node.dimension == array.dimension+)
48
+ #
49
+ # Then, the method is ready to perform the flattening. It
50
+ # first gets the index for the first dimension and then
51
+ # iterates over all remaining dimensions. For those dimensions,
52
+ # the index is multiplied by the size of the previous
53
+ # dimension.
54
+ #
55
+ # The method performs the transformation on the node itself.
56
+ # Any old data is thus lost.
57
+ def transform_flatten(array)
58
+ self.preorder do |node|
59
+ if (node.index?) && (node.parent)
60
+ if (node.variable_name == array.name) && (node.dimension == array.dimensions)
61
+
62
+ # Compute the new index
63
+ results = array.species.dimensions.each_with_index.map { |d,n| '('+node.index_at_dimension(n).to_s+')'+array.factors[n] }
64
+ replacement = array.name+'['+results.join(' + ')+']'
65
+
66
+ # Replace the node
67
+ node.replace_with(C::Index.parse(replacement))
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ # Method to transform array accesses into register accesses.
74
+ # This is only valid for the local loop body and could have
75
+ # been done by the actual compiler in a number of cases.
76
+ def transform_substitution(array,inout)
77
+ replacement = 'register_'+array.name
78
+ original_name = ''
79
+
80
+ # Change the variable names
81
+ self.stmts.preorder do |node|
82
+ if (node.index?) && (node.parent)
83
+
84
+ # First time replacement
85
+ if original_name == ''
86
+ if node.variable_name == array.name
87
+ node.replace_with(C::Variable.parse(replacement))
88
+ original_name = node.to_s
89
+ end
90
+
91
+ # Second, third, etc. replacement
92
+ else
93
+ if original_name == node.to_s
94
+ node.replace_with(C::Variable.parse(replacement))
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ # Add prologue and epilogue code
101
+ if original_name != ''
102
+ if inout
103
+ self.stmts[0].insert_prev(C::Declaration.parse(array.type_name+' '+replacement+'='+original_name+';'))
104
+ else
105
+ self.stmts[0].insert_prev(C::Declaration.parse(array.type_name+' '+replacement+';'))
106
+ end
107
+ self.stmts[self.stmts.length-1].insert_next(C::ExpressionStatement.parse(original_name+' = '+replacement+';'))
108
+ end
109
+ end
110
+
111
+ # Method to shuffle a 2D array access (e.g. transform from
112
+ # A[i][j] into A[j][i]).
113
+ def transform_shuffle(arrays)
114
+ arrays.each do |array|
115
+
116
+ # Change the variable names
117
+ self.stmts.preorder do |node|
118
+ if (node.index?) && (node.parent)
119
+ if node.variable_name == array.name && node.expr.index?
120
+ replacement = node.variable_name.to_s+'['+node.index.to_s+']['+node.expr.index.to_s+']'
121
+ node.replace_with(C::Index.parse(replacement))
122
+ end
123
+ end
124
+ end
125
+
126
+ end
127
+ end
128
+
129
+ # Method to merge the computations of multiple threads.
130
+ def transform_merge_threads(amount,excludes)
131
+ self.preorder do |node|
132
+ if node.statement?
133
+ replacement = C::NodeArray.new
134
+ amount.times do |i|
135
+ replacement.push(node.clone.rename_variables('_m'+i.to_s,excludes))
136
+ end
137
+ node.replace_with(replacement)
138
+ end
139
+ end
140
+ end
141
+ def rename_variables(suffix,excludes)
142
+ self.preorder do |node|
143
+ if (node.variable? || node.declarator?) && !(excludes.include?(node.name)) && (!node.parent.call?)
144
+ node.name = node.name+suffix
145
+ end
146
+ end
147
+ end
148
+
149
+ # This method provides the transformations necessary to
150
+ # perform reduction type of operations. The transformations
151
+ # involved in this function are on variable names and index
152
+ # locations. The argument +id+ specifies which transformation
153
+ # to be performed.
154
+ #
155
+ # Accepted inputs at this point: 2, 3 and 4 (CUDA/OPENCL)
156
+ # Also accepted input: 8 (CUDA), 9 (OPENCL) (to create an atomic version of the code)
157
+ # TODO: Complete the atomic support, e.g. add support for multiplications and ternary operators
158
+ def transform_reduction(input_variable,output_variable,id)
159
+
160
+ # Pre-process assign-add type constructions
161
+ if self.stmts[0].expr.addassign?
162
+ self.stmts[0].expr.replace_with(C::Assign.parse(self.stmts[0].expr.lval.to_s+'='+self.stmts[0].expr.lval.to_s+'+'+self.stmts[0].expr.rval.to_s))
163
+ end
164
+
165
+ # Create atomic code
166
+ if id == 8 || id == 9
167
+ function_name = (id == 8) ? 'atomicAdd' : 'atomic_add'
168
+ self.preorder do |node|
169
+ if node.assign?
170
+ if node.lval.index? && node.lval.variable_name == output_variable.name
171
+ if node.rval.add?
172
+ if node.rval.expr1.variable_name == output_variable.name
173
+ node.replace_with(C::Call.parse(function_name+'(&'+node.rval.expr1.to_s+','+node.rval.expr2.to_s+')'))
174
+ elsif node.rval.expr2.variable_name == output_variable.name
175
+ node.replace_with(C::Call.parse(function_name+'(&'+node.rval.expr2.to_s+','+node.rval.expr1.to_s+')'))
176
+ end
177
+ elsif node.rval.subtract?
178
+ if node.rval.expr1.variable_name == output_variable.name
179
+ node.replace_with(C::Call.parse(function_name+'(&'+node.rval.expr1.to_s+',-'+node.rval.expr2.to_s+')'))
180
+ elsif node.rval.expr2.variable_name == output_variable.name
181
+ node.replace_with(C::Call.parse(function_name+'(&'+node.rval.expr2.to_s+',-'+node.rval.expr1.to_s+')'))
182
+ end
183
+ else
184
+ raise_error('Unsupported atomic reduction operator: '+node.rval.type.inspect)
185
+ end
186
+ end
187
+ end
188
+ end
189
+ return self
190
+ else
191
+
192
+ # Split the statement into an operation, the input, and the output
193
+ results = []
194
+ operation = self.stmts[0].expr.rval.class
195
+ [self.stmts[0].expr.rval.expr1.detach,self.stmts[0].expr.rval.expr2.detach].each do |nodes|
196
+ nodes.preorder do |node|
197
+ if (node.index?)
198
+ results[0] = nodes if node.variable_name == input_variable.name
199
+ results[1] = nodes if node.variable_name == output_variable.name
200
+ end
201
+ end
202
+ end
203
+
204
+ # Process the input part
205
+ results[0].preorder do |node|
206
+ if (node.index?) && (node.variable_name == input_variable.name)
207
+ temporary = C::Variable.parse(Bones::VARIABLE_PREFIX+'temporary')
208
+ results[0] = C::Index.parse(Bones::LOCAL_MEMORY+'['+Bones::VARIABLE_PREFIX+'offset_id]') if id == 3
209
+ results[0] = temporary if id == 5
210
+ if id == 2 || id == 4
211
+ if node.parent
212
+ node.replace_with(temporary)
213
+ else
214
+ results[0] = temporary
215
+ end
216
+ end
217
+ end
218
+ end
219
+
220
+ # Process the output part
221
+ results[1] = C::Variable.parse(Bones::PRIVATE_MEMORY) if id == 2 || id == 5
222
+ results[1] = C::Index.parse(Bones::LOCAL_MEMORY+'['+Bones::LOCAL_ID+']') if id == 3
223
+ results[1] = '0' if id == 4
224
+
225
+ # Merge the results together with the operation
226
+ return C::Expression.parse(results[1].to_s+'+'+results[0].to_s) if id == 3 || id == 5
227
+ case operation.to_s
228
+ when 'C::Add' then return C::Expression.parse(results[1].to_s+'+'+results[0].to_s)
229
+ when 'C::Subtract' then return C::Expression.parse(results[1].to_s+'-'+results[0].to_s)
230
+ else raise_error('Unsupported reduction operation '+operation.to_s+'.')
231
+ end
232
+ end
233
+ end
234
+
235
+ end
236
+