bones-compiler 1.1.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
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
+