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.
- checksums.yaml +15 -0
- data/CHANGELOG +37 -0
- data/LICENSE +1 -1
- data/README.rdoc +95 -70
- data/Rakefile +78 -3
- data/VERSION +1 -1
- data/bin/adarwin +17 -0
- data/examples/benchmarks/PolyBench/2mm.c +104 -0
- data/examples/benchmarks/{3mm.c → PolyBench/3mm.c} +5 -2
- data/examples/benchmarks/{adi.c → PolyBench/adi.c} +6 -3
- data/examples/benchmarks/{atax.c → PolyBench/atax.c} +5 -2
- data/examples/benchmarks/{bicg.c → PolyBench/bicg.c} +5 -2
- data/examples/benchmarks/{cholesky.c → PolyBench/cholesky.c} +3 -0
- data/examples/benchmarks/{common.h → PolyBench/common.h} +2 -2
- data/examples/benchmarks/{correlation.c → PolyBench/correlation.c} +16 -7
- data/examples/benchmarks/{covariance.c → PolyBench/covariance.c} +7 -2
- data/examples/benchmarks/{doitgen.c → PolyBench/doitgen.c} +5 -2
- data/examples/benchmarks/{durbin.c → PolyBench/durbin.c} +3 -0
- data/examples/benchmarks/{dynprog.c → PolyBench/dynprog.c} +3 -0
- data/examples/benchmarks/{fdtd-2d-apml.c → PolyBench/fdtd-2d-apml.c} +3 -0
- data/examples/benchmarks/{fdtd-2d.c → PolyBench/fdtd-2d.c} +5 -2
- data/examples/benchmarks/{floyd-warshall.c → PolyBench/floyd-warshall.c} +3 -0
- data/examples/benchmarks/{gemm.c → PolyBench/gemm.c} +5 -2
- data/examples/benchmarks/{gemver.c → PolyBench/gemver.c} +5 -2
- data/examples/benchmarks/{gesummv.c → PolyBench/gesummv.c} +5 -2
- data/examples/benchmarks/{gramschmidt.c → PolyBench/gramschmidt.c} +3 -0
- data/examples/benchmarks/{jacobi-1d-imper.c → PolyBench/jacobi-1d-imper.c} +10 -2
- data/examples/benchmarks/{jacobi-2d-imper.c → PolyBench/jacobi-2d-imper.c} +8 -3
- data/examples/benchmarks/{lu.c → PolyBench/lu.c} +3 -0
- data/examples/benchmarks/{ludcmp.c → PolyBench/ludcmp.c} +3 -0
- data/examples/benchmarks/{mvt.c → PolyBench/mvt.c} +6 -2
- data/examples/benchmarks/{reg_detect.c → PolyBench/reg_detect.c} +3 -0
- data/examples/benchmarks/{seidel-2d.c → PolyBench/seidel-2d.c} +3 -0
- data/examples/benchmarks/{symm.c → PolyBench/symm.c} +3 -0
- data/examples/benchmarks/{syr2k.c → PolyBench/syr2k.c} +5 -2
- data/examples/benchmarks/{syrk.c → PolyBench/syrk.c} +7 -4
- data/examples/benchmarks/{trisolv.c → PolyBench/trisolv.c} +3 -0
- data/examples/benchmarks/{trmm.c → PolyBench/trmm.c} +3 -0
- data/examples/benchmarks/Rodinia/cfd.c +180 -0
- data/examples/benchmarks/Rodinia/hotspot.c +228 -0
- data/examples/benchmarks/Rodinia/kmeans.c +164 -0
- data/examples/benchmarks/Rodinia/srad.c +188 -0
- data/examples/benchmarks/other/common.h +0 -0
- data/examples/benchmarks/other/dct.c +58 -0
- data/examples/benchmarks/other/mm.c +50 -0
- data/examples/benchmarks/{saxpy.c → other/saxpy.c} +11 -7
- data/examples/chunk/{example1.c → example01.c} +0 -0
- data/examples/chunk/{example2.c → example02.c} +0 -0
- data/examples/chunk/{example3.c → example03.c} +0 -0
- data/examples/chunk/{example4.c → example04.c} +0 -0
- data/examples/chunk/{example5.c → example05.c} +0 -0
- data/examples/chunk/example06.c +45 -0
- data/examples/chunk/example07.c +49 -0
- data/examples/dependences/example01.c +42 -0
- data/examples/dependences/example02.c +40 -0
- data/examples/dependences/example03.c +43 -0
- data/examples/dependences/example04.c +44 -0
- data/examples/dependences/example05.c +42 -0
- data/examples/element/{example1.c → example01.c} +0 -0
- data/examples/element/{example2.c → example02.c} +2 -2
- data/examples/element/{example3.c → example03.c} +0 -0
- data/examples/element/{example4.c → example04.c} +0 -0
- data/examples/element/{example5.c → example05.c} +0 -0
- data/examples/element/{example6.c → example06.c} +0 -0
- data/examples/element/{example7.c → example07.c} +0 -0
- data/examples/element/{example8.c → example08.c} +0 -0
- data/examples/element/{example9.c → example09.c} +0 -0
- data/examples/element/example13.c +73 -0
- data/examples/fusion/example01.c +68 -0
- data/examples/fusion/example02.c +73 -0
- data/examples/fusion/example03.c +72 -0
- data/examples/fusion/example04.c +61 -0
- data/examples/fusion/example05.c +55 -0
- data/examples/neighbourhood/{example1.c → example01.c} +0 -0
- data/examples/neighbourhood/{example2.c → example02.c} +0 -0
- data/examples/neighbourhood/{example3.c → example03.c} +0 -0
- data/examples/neighbourhood/{example4.c → example04.c} +0 -0
- data/examples/neighbourhood/example05.c +44 -0
- data/examples/shared/{example1.c → example01.c} +0 -0
- data/examples/shared/{example2.c → example02.c} +0 -0
- data/examples/shared/{example3.c → example03.c} +0 -0
- data/examples/shared/{example4.c → example04.c} +0 -0
- data/examples/shared/{example5.c → example05.c} +0 -0
- data/lib/adarwin.rb +62 -0
- data/lib/adarwin/dependences.rb +268 -0
- data/lib/adarwin/engine.rb +277 -0
- data/lib/adarwin/fusion.rb +174 -0
- data/lib/adarwin/interval.rb +57 -0
- data/lib/adarwin/memorycopies.rb +153 -0
- data/lib/adarwin/nest.rb +225 -0
- data/lib/adarwin/preprocessor.rb +76 -0
- data/lib/adarwin/reference.rb +261 -0
- data/lib/bones.rb +4 -55
- data/lib/bones/algorithm.rb +77 -40
- data/lib/bones/copy.rb +26 -0
- data/lib/bones/engine.rb +147 -31
- data/lib/bones/preprocessor.rb +92 -12
- data/lib/bones/species.rb +4 -3
- data/lib/bones/structure.rb +14 -4
- data/lib/castaddon.rb +11 -6
- data/lib/castaddon/node_adarwin.rb +245 -0
- data/lib/castaddon/node_bones.rb +316 -0
- data/lib/castaddon/node_common.rb +289 -0
- data/lib/castaddon/transformations.rb +236 -0
- data/lib/common.rb +216 -0
- data/skeletons/CPU-C/common/header.c +3 -0
- data/skeletons/CPU-C/common/mem_global.c +0 -0
- data/skeletons/CPU-C/common/timer_2_start.c +11 -13
- data/skeletons/CPU-C/common/timer_2_stop.c +1 -1
- data/skeletons/CPU-C/common/timer_globals.c +29 -0
- data/skeletons/CPU-OPENCL-INTEL/common/globals.c +1 -1
- data/skeletons/CPU-OPENCL-INTEL/common/header.c +3 -0
- data/skeletons/CPU-OPENCL-INTEL/common/mem_copy_D2H.c +7 -2
- data/skeletons/CPU-OPENCL-INTEL/common/mem_copy_H2D.c +4 -2
- data/skeletons/CPU-OPENCL-INTEL/common/mem_global.c +0 -0
- data/skeletons/CPU-OPENCL-INTEL/common/mem_prologue.c +6 -3
- data/skeletons/CPU-OPENCL-INTEL/common/timer_2_stop.c +1 -1
- data/skeletons/CPU-OPENCL-INTEL/common/timer_globals.c +24 -0
- data/skeletons/CPU-OPENMP/common/globals.c +1 -0
- data/skeletons/CPU-OPENMP/common/header.c +3 -0
- data/skeletons/CPU-OPENMP/common/mem_global.c +0 -0
- data/skeletons/CPU-OPENMP/common/timer_1_start.c +0 -12
- data/skeletons/CPU-OPENMP/common/timer_2_stop.c +1 -1
- data/skeletons/CPU-OPENMP/common/timer_globals.c +33 -0
- data/skeletons/GPU-CUDA/common/globals.c +27 -3
- data/skeletons/GPU-CUDA/common/header.c +2 -0
- data/skeletons/GPU-CUDA/common/mem_async_alloc.c +6 -0
- data/skeletons/GPU-CUDA/common/mem_async_copyin.c +6 -0
- data/skeletons/GPU-CUDA/common/mem_async_copyout.c +6 -0
- data/skeletons/GPU-CUDA/common/mem_async_free.c +6 -0
- data/skeletons/GPU-CUDA/common/mem_copy_D2H.c +2 -1
- data/skeletons/GPU-CUDA/common/mem_copy_H2D.c +2 -1
- data/skeletons/GPU-CUDA/common/mem_global.c +1 -0
- data/skeletons/GPU-CUDA/common/mem_prologue.c +1 -2
- data/skeletons/GPU-CUDA/common/scheduler.c +86 -0
- data/skeletons/GPU-CUDA/common/timer_2_start.c +2 -4
- data/skeletons/GPU-CUDA/common/timer_2_stop.c +3 -5
- data/skeletons/GPU-CUDA/common/timer_globals.c +26 -0
- data/skeletons/GPU-CUDA/kernel/2xN-N-chunk-1-N-to-D-element.kernel.cu +5 -7
- data/skeletons/GPU-CUDA/kernel/N-N-chunk-1-N-to-D-element.kernel.cu +4 -6
- data/skeletons/GPU-CUDA/kernel/default.host.c +1 -1
- data/skeletons/GPU-CUDA/kernel/default.kernel.cu +6 -8
- data/skeletons/GPU-CUDA/skeletons.txt +6 -5
- data/{examples/benchmarks/2mm.c → test/examples/benchmarks/PolyBench/2mm_species.c} +19 -15
- data/test/examples/benchmarks/PolyBench/3mm_species.c +82 -0
- data/test/examples/benchmarks/PolyBench/adi_species.c +89 -0
- data/test/examples/benchmarks/PolyBench/atax_species.c +69 -0
- data/test/examples/benchmarks/PolyBench/bicg_species.c +71 -0
- data/test/examples/benchmarks/PolyBench/cholesky_species.c +68 -0
- data/test/examples/benchmarks/PolyBench/correlation_species.c +97 -0
- data/test/examples/benchmarks/PolyBench/covariance_species.c +78 -0
- data/test/examples/benchmarks/PolyBench/doitgen_species.c +67 -0
- data/test/examples/benchmarks/PolyBench/durbin_species.c +80 -0
- data/test/examples/benchmarks/PolyBench/dynprog_species.c +71 -0
- data/test/examples/benchmarks/PolyBench/fdtd-2d-apml_species.c +112 -0
- data/test/examples/benchmarks/PolyBench/fdtd-2d_species.c +78 -0
- data/test/examples/benchmarks/PolyBench/floyd-warshall_species.c +54 -0
- data/test/examples/benchmarks/PolyBench/gemm_species.c +73 -0
- data/test/examples/benchmarks/PolyBench/gemver_species.c +93 -0
- data/test/examples/benchmarks/PolyBench/gesummv_species.c +68 -0
- data/test/examples/benchmarks/PolyBench/gramschmidt_species.c +78 -0
- data/test/examples/benchmarks/PolyBench/jacobi-1d-imper_species.c +59 -0
- data/test/examples/benchmarks/PolyBench/jacobi-2d-imper_species.c +65 -0
- data/test/examples/benchmarks/PolyBench/lu_species.c +57 -0
- data/test/examples/benchmarks/PolyBench/ludcmp_species.c +89 -0
- data/test/examples/benchmarks/PolyBench/mvt_species.c +69 -0
- data/test/examples/benchmarks/PolyBench/reg_detect_species.c +86 -0
- data/test/examples/benchmarks/PolyBench/seidel-2d_species.c +53 -0
- data/test/examples/benchmarks/PolyBench/symm_species.c +74 -0
- data/test/examples/benchmarks/PolyBench/syr2k_species.c +69 -0
- data/test/examples/benchmarks/PolyBench/syrk_species.c +66 -0
- data/test/examples/benchmarks/PolyBench/trisolv_species.c +61 -0
- data/test/examples/benchmarks/PolyBench/trmm_species.c +61 -0
- data/test/examples/chunk/example01_species.c +58 -0
- data/test/examples/chunk/example02_species.c +48 -0
- data/test/examples/chunk/example03_species.c +63 -0
- data/test/examples/chunk/example04_species.c +58 -0
- data/test/examples/chunk/example05_species.c +56 -0
- data/test/examples/chunk/example06_species.c +49 -0
- data/test/examples/chunk/example07_species.c +53 -0
- data/test/examples/dependences/example01_species.c +46 -0
- data/test/examples/dependences/example02_species.c +44 -0
- data/test/examples/dependences/example03_species.c +47 -0
- data/test/examples/dependences/example04_species.c +48 -0
- data/test/examples/dependences/example05_species.c +46 -0
- data/test/examples/element/example01_species.c +50 -0
- data/test/examples/element/example02_species.c +50 -0
- data/test/examples/element/example03_species.c +62 -0
- data/test/examples/element/example04_species.c +53 -0
- data/test/examples/element/example05_species.c +59 -0
- data/test/examples/element/example06_species.c +50 -0
- data/test/examples/element/example07_species.c +58 -0
- data/test/examples/element/example08_species.c +49 -0
- data/test/examples/element/example09_species.c +52 -0
- data/test/examples/element/example10_species.c +54 -0
- data/test/examples/element/example11_species.c +51 -0
- data/test/examples/element/example12_species.c +60 -0
- data/test/examples/element/example13_species.c +77 -0
- data/test/examples/neighbourhood/example01_species.c +57 -0
- data/test/examples/neighbourhood/example02_species.c +56 -0
- data/test/examples/neighbourhood/example03_species.c +83 -0
- data/test/examples/neighbourhood/example04_species.c +55 -0
- data/test/examples/neighbourhood/example05_species.c +48 -0
- data/test/examples/shared/example01_species.c +49 -0
- data/test/examples/shared/example02_species.c +55 -0
- data/test/examples/shared/example03_species.c +59 -0
- data/test/examples/shared/example04_species.c +56 -0
- data/test/examples/shared/example05_species.c +52 -0
- metadata +193 -73
- data/examples/benchmarks/overview.txt +0 -38
- 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
|
+
|