BOAST 1.0.9 → 1.1.0
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 +4 -4
- data/BOAST.gemspec +1 -1
- data/lib/BOAST.rb +5 -1
- data/lib/BOAST/Language/Algorithm.rb +104 -22
- data/lib/BOAST/Language/Annotation.rb +55 -0
- data/lib/BOAST/Language/Arithmetic.rb +44 -10
- data/lib/BOAST/Language/Case.rb +89 -52
- data/lib/BOAST/Language/CodeBlock.rb +17 -0
- data/lib/BOAST/Language/Comment.rb +38 -0
- data/lib/BOAST/Language/ControlStructure.rb +7 -0
- data/lib/BOAST/Language/Error.rb +7 -0
- data/lib/BOAST/Language/Expression.rb +4 -5
- data/lib/BOAST/Language/For.rb +59 -27
- data/lib/BOAST/Language/If.rb +12 -17
- data/lib/BOAST/Language/Index.rb +5 -5
- data/lib/BOAST/Language/Intrinsics.rb +38 -32
- data/lib/BOAST/Language/OpenMP.rb +1 -1
- data/lib/BOAST/Language/Operators.rb +208 -53
- data/lib/BOAST/Language/Pragma.rb +3 -3
- data/lib/BOAST/Language/Print.rb +3 -3
- data/lib/BOAST/Language/Procedure.rb +15 -8
- data/lib/BOAST/Language/Variable.rb +45 -87
- data/lib/BOAST/Language/While.rb +3 -0
- data/lib/BOAST/Optimization/Optimization.rb +241 -0
- metadata +7 -4
- data/lib/BOAST/Language/Optimization.rb +0 -74
- data/lib/BOAST/Language/Vector.rb +0 -6
@@ -1,5 +1,8 @@
|
|
1
1
|
module BOAST
|
2
2
|
|
3
|
+
class OperatorError < Error
|
4
|
+
end
|
5
|
+
|
3
6
|
class Operator
|
4
7
|
extend PrivateStateAccessor
|
5
8
|
extend Intrinsics
|
@@ -11,10 +14,10 @@ module BOAST
|
|
11
14
|
end
|
12
15
|
|
13
16
|
def Operator.convert(arg, type)
|
17
|
+
return "#{arg}" if get_vector_name(arg.type) == get_vector_name(type) or lang == CUDA
|
14
18
|
return "convert_#{type.decl}( #{arg} )" if lang == CL
|
15
19
|
|
16
20
|
path = get_conversion_path(type, arg.type)
|
17
|
-
raise "Unavailable conversion from #{get_vector_name(arg.type)} to #{get_vector_name(type)}!" if not path
|
18
21
|
s = "#{arg}"
|
19
22
|
if path.length > 1 then
|
20
23
|
path.each_cons(2) { |slice|
|
@@ -29,10 +32,9 @@ module BOAST
|
|
29
32
|
|
30
33
|
class BasicBinaryOperator < Operator
|
31
34
|
|
32
|
-
def BasicBinaryOperator.
|
35
|
+
def BasicBinaryOperator.string(arg1, arg2, return_type)
|
33
36
|
if lang == C and (arg1.class == Variable and arg2.class == Variable) and (arg1.type.vector_length > 1 or arg2.type.vector_length > 1) then
|
34
37
|
instruction = intrinsics(intr_symbol, return_type.type)
|
35
|
-
raise "Unavailable operator #{symbol} for #{get_vector_name(return_type.type)}!" unless instruction
|
36
38
|
a1 = convert(arg1, return_type.type)
|
37
39
|
a2 = convert(arg2, return_type.type)
|
38
40
|
return "#{instruction}( #{a1}, #{a2} )"
|
@@ -43,9 +45,63 @@ module BOAST
|
|
43
45
|
|
44
46
|
end
|
45
47
|
|
48
|
+
class Minus < Operator
|
49
|
+
|
50
|
+
def Minus.string(arg1, arg2, return_type)
|
51
|
+
return " -(#{arg2})"
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
class Plus < Operator
|
57
|
+
|
58
|
+
def Plus.string(arg1, arg2, return_type)
|
59
|
+
return " +#{arg2}"
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
class Not < Operator
|
65
|
+
|
66
|
+
def Not.string(arg1, arg2, return_type)
|
67
|
+
return " (.not. (#{arg2}))" if lang == FORTRAN
|
68
|
+
return " !(#{arg2})"
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
class Reference < Operator
|
74
|
+
|
75
|
+
def Reference.string(arg1, arg2, return_type)
|
76
|
+
return " #{arg2}" if lang == FORTRAN
|
77
|
+
return " &#{arg2}"
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
class Dereference < Operator
|
83
|
+
|
84
|
+
def Dereference.string(arg1, arg2, return_type)
|
85
|
+
return " *(#{arg2})"
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
class Equal < Operator
|
91
|
+
|
92
|
+
def Equal.string(arg1, arg2, return_type)
|
93
|
+
return basic_usage(arg1, arg2)
|
94
|
+
end
|
95
|
+
|
96
|
+
def Equal.basic_usage(arg1, arg2)
|
97
|
+
return "#{arg1} == #{arg2}"
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
46
102
|
class Different < Operator
|
47
103
|
|
48
|
-
def Different.
|
104
|
+
def Different.string(arg1, arg2, return_type)
|
49
105
|
return basic_usage(arg1, arg2)
|
50
106
|
end
|
51
107
|
|
@@ -56,9 +112,83 @@ module BOAST
|
|
56
112
|
|
57
113
|
end
|
58
114
|
|
115
|
+
class Greater < Operator
|
116
|
+
|
117
|
+
def Greater.string(arg1, arg2, return_type)
|
118
|
+
return basic_usage(arg1, arg2)
|
119
|
+
end
|
120
|
+
|
121
|
+
def Greater.basic_usage(arg1, arg2)
|
122
|
+
return "#{arg1} > #{arg2}"
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
class Less < Operator
|
128
|
+
|
129
|
+
def Less.string(arg1, arg2, return_type)
|
130
|
+
return basic_usage(arg1, arg2)
|
131
|
+
end
|
132
|
+
|
133
|
+
def Less.basic_usage(arg1, arg2)
|
134
|
+
return "#{arg1} < #{arg2}"
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
class GreaterOrEqual < Operator
|
140
|
+
|
141
|
+
def GreaterOrEqual.string(arg1, arg2, return_type)
|
142
|
+
return basic_usage(arg1, arg2)
|
143
|
+
end
|
144
|
+
|
145
|
+
def GreaterOrEqual.basic_usage(arg1, arg2)
|
146
|
+
return "#{arg1} >= #{arg2}"
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
class LessOrEqual < Operator
|
152
|
+
|
153
|
+
def LessOrEqual.string(arg1, arg2, return_type)
|
154
|
+
return basic_usage(arg1, arg2)
|
155
|
+
end
|
156
|
+
|
157
|
+
def LessOrEqual.basic_usage(arg1, arg2)
|
158
|
+
return "#{arg1} <= #{arg2}"
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
class And < Operator
|
164
|
+
|
165
|
+
def And.string(arg1, arg2, return_type)
|
166
|
+
return basic_usage(arg1, arg2)
|
167
|
+
end
|
168
|
+
|
169
|
+
def And.basic_usage(arg1, arg2)
|
170
|
+
return "#{arg1} .and. #{arg2}" if lang == FORTRAN
|
171
|
+
return "#{arg1} && #{arg2}"
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
class Or < Operator
|
177
|
+
|
178
|
+
def Or.string(arg1, arg2, return_type)
|
179
|
+
return basic_usage(arg1, arg2)
|
180
|
+
end
|
181
|
+
|
182
|
+
def Or.basic_usage(arg1, arg2)
|
183
|
+
return "#{arg1} .or. #{arg2}" if lang == FORTRAN
|
184
|
+
return "#{arg1} || #{arg2}"
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
|
59
189
|
class Affectation < Operator
|
60
190
|
|
61
|
-
def Affectation.
|
191
|
+
def Affectation.string(arg1, arg2, return_type)
|
62
192
|
if arg1.class == Variable and arg1.type.vector_length > 1 then
|
63
193
|
return "#{arg1} = #{Load(arg2, arg1)}"
|
64
194
|
elsif arg2.class == Variable and arg2.type.vector_length > 1 then
|
@@ -73,6 +203,27 @@ module BOAST
|
|
73
203
|
|
74
204
|
end
|
75
205
|
|
206
|
+
class Exponentiation < BasicBinaryOperator
|
207
|
+
|
208
|
+
class << self
|
209
|
+
|
210
|
+
def symbol
|
211
|
+
return "**"
|
212
|
+
end
|
213
|
+
|
214
|
+
def intr_symbol
|
215
|
+
return :POW
|
216
|
+
end
|
217
|
+
|
218
|
+
def basic_usage(arg1, arg2)
|
219
|
+
return "(#{arg1})**(#{arg2})" if lang == FORTRAN
|
220
|
+
return "pow(#{arg1}, #{arg2})"
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|
224
|
+
|
225
|
+
end
|
226
|
+
|
76
227
|
class Multiplication < BasicBinaryOperator
|
77
228
|
|
78
229
|
class << self
|
@@ -153,22 +304,6 @@ module BOAST
|
|
153
304
|
|
154
305
|
end
|
155
306
|
|
156
|
-
class Minus < Operator
|
157
|
-
|
158
|
-
def Minus.to_s(arg1, arg2, return_type)
|
159
|
-
return " -(#{arg2})"
|
160
|
-
end
|
161
|
-
|
162
|
-
end
|
163
|
-
|
164
|
-
class Not < Operator
|
165
|
-
|
166
|
-
def Not.to_s(arg1, arg2, return_type)
|
167
|
-
return " ! #{arg2}"
|
168
|
-
end
|
169
|
-
|
170
|
-
end
|
171
|
-
|
172
307
|
class Set < Operator
|
173
308
|
extend Functor
|
174
309
|
include Intrinsics
|
@@ -191,24 +326,24 @@ module BOAST
|
|
191
326
|
def to_var
|
192
327
|
if lang == C or lang == CL and @return_type.type.vector_length > 1 then
|
193
328
|
if @source.kind_of?( Array ) then
|
194
|
-
raise "Invalid array length!" unless @source.length == @return_type.type.vector_length
|
329
|
+
raise OperatorError, "Invalid array length!" unless @source.length == @return_type.type.vector_length
|
195
330
|
return @return_type.copy("(#{@return_type.type.decl})( #{@source.join(", ")} )", DISCARD_OPTIONS) if lang == CL
|
196
331
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
332
|
+
begin
|
333
|
+
instruction = intrinsics(:SET, @return_type.type)
|
334
|
+
return @return_type.copy("#{instruction}( #{@source.join(", ")} )", DISCARD_OPTIONS)
|
335
|
+
rescue IntrinsicsError
|
336
|
+
instruction = intrinsics(:SET_LANE, @return_type.type)
|
337
|
+
s = Set(0, @return_type).to_s
|
338
|
+
@source.each_with_index { |v,i|
|
339
|
+
s = "#{instruction}(#{v}, #{s}, #{i})"
|
340
|
+
}
|
341
|
+
return @return_type.copy(s, DISCARD_OPTIONS)
|
342
|
+
end
|
207
343
|
elsif @source.class != Variable or @source.type.vector_length == 1 then
|
208
344
|
return @return_type.copy("(#{@return_type.type.decl})( #{@source} )", DISCARD_OPTIONS) if lang == CL
|
209
345
|
|
210
346
|
instruction = intrinsics(:SET1, @return_type.type)
|
211
|
-
raise "Unavailable operator set1 for #{get_vector_name(@return_type.type)}!" unless instruction
|
212
347
|
return @return_type.copy("#{instruction}( #{@source} )", DISCARD_OPTIONS)
|
213
348
|
elsif @return_type.type != @source.type
|
214
349
|
return @return_type.copy("#{Operator.convert(@source, @return_type.type)}", DISCARD_OPTIONS)
|
@@ -267,12 +402,11 @@ module BOAST
|
|
267
402
|
end
|
268
403
|
return @return_type.copy("vload#{@return_type.type.vector_length}(0, #{a2})", DISCARD_OPTIONS) if lang == CL
|
269
404
|
return @return_type.copy("_m_from_int64( *((int64_t * ) #{a2} ) )", DISCARD_OPTIONS) if get_architecture == X86 and @return_type.type.total_size*8 == 64
|
270
|
-
if @source.
|
405
|
+
if @source.alignment == @return_type.type.total_size then
|
271
406
|
instruction = intrinsics(:LOADA, @return_type.type)
|
272
407
|
else
|
273
408
|
instruction = intrinsics(:LOAD, @return_type.type)
|
274
409
|
end
|
275
|
-
raise "Unavailable operator load for #{get_vector_name(@return_type.type)}!" unless instruction
|
276
410
|
return @return_type.copy("#{instruction}( #{a2} )", DISCARD_OPTIONS)
|
277
411
|
else
|
278
412
|
return @return_type.copy("#{Operator.convert(@source, @return_type.type)}", DISCARD_OPTIONS)
|
@@ -315,7 +449,7 @@ module BOAST
|
|
315
449
|
end
|
316
450
|
|
317
451
|
def get_mask
|
318
|
-
raise "Mask size is wrong: #{@mask.length} for #{@return_type.type.vector_length}!" if @mask.length != @return_type.type.vector_length
|
452
|
+
raise OperatorError, "Mask size is wrong: #{@mask.length} for #{@return_type.type.vector_length}!" if @mask.length != @return_type.type.vector_length
|
319
453
|
return Load(@mask.collect { |m| ( m and m != 0 ) ? -1 : 0 }, Int("mask", :size => @return_type.type.size, :vector_length => @return_type.type.vector_length ) )
|
320
454
|
end
|
321
455
|
|
@@ -326,9 +460,9 @@ module BOAST
|
|
326
460
|
end
|
327
461
|
|
328
462
|
def to_var
|
329
|
-
raise "Cannot load unknown type!" unless @return_type
|
330
|
-
raise "Unsupported language!" unless lang == C
|
331
|
-
|
463
|
+
raise OperatorError, "Cannot load unknown type!" unless @return_type
|
464
|
+
raise LanguageError, "Unsupported language!" unless lang == C
|
465
|
+
instruction = intrinsics(:MASKLOAD, @return_type.type)
|
332
466
|
s = ""
|
333
467
|
src = "#{@source}"
|
334
468
|
if src[0] != "*" then
|
@@ -337,7 +471,7 @@ module BOAST
|
|
337
471
|
src = src[1..-1]
|
338
472
|
end
|
339
473
|
p_type = @return_type.type.copy(:vector_length => 1)
|
340
|
-
s += "#{
|
474
|
+
s += "#{instruction}((#{p_type.decl} * )#{src}, #{get_mask})"
|
341
475
|
return @return_type.copy( s, DISCARD_OPTIONS)
|
342
476
|
end
|
343
477
|
|
@@ -386,12 +520,11 @@ module BOAST
|
|
386
520
|
return "vstore#{@source.type.vector_length}(#{@source}, 0, #{dst})" if lang == CL
|
387
521
|
return "*((int64_t * ) #{dst}) = _m_to_int64( #{@source} )" if get_architecture == X86 and @source.type.total_size*8 == 64
|
388
522
|
|
389
|
-
if @dest.
|
523
|
+
if @dest.alignment == @source.type.total_size then
|
390
524
|
instruction = intrinsics(:STOREA, @source.type)
|
391
525
|
else
|
392
526
|
instruction = intrinsics(:STORE, @source.type)
|
393
527
|
end
|
394
|
-
raise "Unavailable operator store for #{get_vector_name(@source.type)}!" unless instruction
|
395
528
|
p_type = @source.type.copy(:vector_length => 1)
|
396
529
|
p_type = @source.type if get_architecture == X86 and @source.type.kind_of?(Int)
|
397
530
|
return "#{instruction}( (#{p_type.decl} * ) #{dst}, #{@source} )"
|
@@ -431,16 +564,16 @@ module BOAST
|
|
431
564
|
end
|
432
565
|
|
433
566
|
def get_mask
|
434
|
-
raise "Mask size is wrong: #{@mask.length} for #{@store_type.type.vector_length}!" if @mask.length != @store_type.type.vector_length
|
567
|
+
raise OperatorError, "Mask size is wrong: #{@mask.length} for #{@store_type.type.vector_length}!" if @mask.length != @store_type.type.vector_length
|
435
568
|
return Load.to_s(@mask.collect { |m| ( m and m != 0 ) ? -1 : 0 }, Int("mask", :size => @store_type.type.size, :vector_length => @store_type.type.vector_length ) )
|
436
569
|
end
|
437
570
|
|
438
571
|
private :get_mask
|
439
572
|
|
440
573
|
def to_s
|
441
|
-
raise "Cannot store unknown type!" unless @store_type
|
442
|
-
raise "Unsupported language!" unless lang == C
|
443
|
-
|
574
|
+
raise OperatorError, "Cannot store unknown type!" unless @store_type
|
575
|
+
raise LanguageError, "Unsupported language!" unless lang == C
|
576
|
+
instruction = intrinsics(:MASKSTORE, @store_type.type)
|
444
577
|
s = ""
|
445
578
|
dst = "#{@dest}"
|
446
579
|
if dst[0] != "*" then
|
@@ -449,7 +582,7 @@ module BOAST
|
|
449
582
|
dst = dst[1..-1]
|
450
583
|
end
|
451
584
|
p_type = @store_type.type.copy(:vector_length => 1)
|
452
|
-
return s += "#{
|
585
|
+
return s += "#{instruction}((#{p_type.decl} * )#{dst}, #{get_mask}, #{Operator.convert(@source, @store_type.type)})"
|
453
586
|
end
|
454
587
|
|
455
588
|
def pr
|
@@ -494,7 +627,12 @@ module BOAST
|
|
494
627
|
end
|
495
628
|
|
496
629
|
def to_var
|
497
|
-
|
630
|
+
instruction = nil
|
631
|
+
begin
|
632
|
+
instruction = intrinsics(:FMADD,@return_type.type)
|
633
|
+
rescue
|
634
|
+
end
|
635
|
+
return (@operand3 + @operand1 * @operand2).to_var unless lang != FORTRAN and @return_type and ( instruction or ( [CL, CUDA].include?(lang) ) )
|
498
636
|
op1 = convert_operand(@operand1)
|
499
637
|
op2 = convert_operand(@operand2)
|
500
638
|
op3 = convert_operand(@operand3)
|
@@ -503,9 +641,9 @@ module BOAST
|
|
503
641
|
else
|
504
642
|
case architecture
|
505
643
|
when X86
|
506
|
-
ret_name = "#{
|
644
|
+
ret_name = "#{instruction}(#{op1},#{op2},#{op3})"
|
507
645
|
when ARM
|
508
|
-
ret_name = "#{
|
646
|
+
ret_name = "#{instruction}(#{op2},#{op3},#{op1})"
|
509
647
|
else
|
510
648
|
return (@operand1 * @operand2 + @operand3).to_var
|
511
649
|
end
|
@@ -544,14 +682,31 @@ module BOAST
|
|
544
682
|
@operand3 = z
|
545
683
|
end
|
546
684
|
|
685
|
+
def op_to_var
|
686
|
+
op1 = @operand1.respond_to?(:to_var) ? @operand1.to_var : @operand1
|
687
|
+
op1 = @operand1 unless op1
|
688
|
+
op2 = @operand2.respond_to?(:to_var) ? @operand2.to_var : @operand2
|
689
|
+
op2 = @operand2 unless op2
|
690
|
+
op3 = @operand3.respond_to?(:to_var) ? @operand3.to_var : @operand3
|
691
|
+
op3 = @operand3 unless op3
|
692
|
+
return [op1, op2, op3]
|
693
|
+
end
|
694
|
+
|
695
|
+
private :op_to_var
|
696
|
+
|
547
697
|
def to_s
|
548
|
-
|
698
|
+
return to_s_fortran if lang == FORTRAN
|
549
699
|
return to_s_c if [C, CL, CUDA].include?( lang )
|
550
700
|
end
|
551
701
|
|
702
|
+
def to_s_fortran
|
703
|
+
op1, op2, op3 = op_to_var
|
704
|
+
"merge(#{op2}, #{op3}, #{op1})"
|
705
|
+
end
|
706
|
+
|
552
707
|
def to_s_c
|
553
|
-
|
554
|
-
|
708
|
+
op1, op2, op3 = op_to_var
|
709
|
+
"(#{op1} ? #{op2} : #{op3})"
|
555
710
|
end
|
556
711
|
|
557
712
|
def pr
|
@@ -8,7 +8,7 @@ module BOAST
|
|
8
8
|
attr_reader :name
|
9
9
|
attr_reader :options
|
10
10
|
|
11
|
-
def initialize(name, options)
|
11
|
+
def initialize(name, *options)
|
12
12
|
@name = name
|
13
13
|
@options = options
|
14
14
|
end
|
@@ -16,9 +16,9 @@ module BOAST
|
|
16
16
|
def to_s
|
17
17
|
s = ""
|
18
18
|
if lang == FORTRAN then
|
19
|
-
s += "
|
19
|
+
s += "!#{@name}$"
|
20
20
|
else
|
21
|
-
s += "#pragma"
|
21
|
+
s += "#pragma #{name}"
|
22
22
|
end
|
23
23
|
@options.each{ |opt|
|
24
24
|
s += " #{opt}"
|