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.
- 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
|
+
|