BOAST 1.0.9 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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}"
|