BOAST 1.0.7 → 1.0.8

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.
@@ -4,6 +4,8 @@ module BOAST
4
4
  extend PrivateStateAccessor
5
5
  extend Intrinsics
6
6
 
7
+ DISCARD_OPTIONS = { :const => nil, :constant => nil, :direction => nil, :dir => nil, :align => nil }
8
+
7
9
  def Operator.inspect
8
10
  return "#{name}"
9
11
  end
@@ -11,9 +13,16 @@ module BOAST
11
13
  def Operator.convert(arg, type)
12
14
  return "convert_#{type.decl}( #{arg} )" if lang == CL
13
15
 
14
- instruction = intrinsics[get_architecture][:CVT][get_vector_name(type)][get_vector_name(arg.type)]
15
- raise "Unavailable conversion from #{get_vector_name(arg.type)} to #{get_vector_name(type)}!" if not instruction
16
- return "#{instruction}( #{arg} )"
16
+ 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
+ s = "#{arg}"
19
+ if path.length > 1 then
20
+ path.each_cons(2) { |slice|
21
+ instruction = intrinsics_by_vector_name(:CVT, slice[1], slice[0])
22
+ s = "#{instruction}( #{s} )"
23
+ }
24
+ end
25
+ return s
17
26
  end
18
27
 
19
28
  end
@@ -21,14 +30,11 @@ module BOAST
21
30
  class BasicBinaryOperator < Operator
22
31
 
23
32
  def BasicBinaryOperator.to_s(arg1, arg2, return_type)
24
- #puts "#{arg1.class} * #{arg2.class} : #{arg1} * #{arg2}"
25
33
  if lang == C and (arg1.class == Variable and arg2.class == Variable) and (arg1.type.vector_length > 1 or arg2.type.vector_length > 1) then
26
- raise "Vectors have different length: #{arg1} #{arg1.type.vector_length}, #{arg2} #{arg2.type.vector_length}" if arg1.type.vector_length != arg2.type.vector_length
27
- #puts "#{arg1.type.signed} #{arg2.type.signed} #{return_type.type.signed}"
28
- instruction = intrinsics[get_architecture][intr_symbol][get_vector_name(return_type.type)]
34
+ instruction = intrinsics(intr_symbol, return_type.type)
29
35
  raise "Unavailable operator #{symbol} for #{get_vector_name(return_type.type)}!" unless instruction
30
- a1 = ( arg1.type != return_type.type ? convert(arg1, return_type.type) : "#{arg1}" )
31
- a2 = ( arg2.type != return_type.type ? convert(arg2, return_type.type) : "#{arg2}" )
36
+ a1 = convert(arg1, return_type.type)
37
+ a2 = convert(arg2, return_type.type)
32
38
  return "#{instruction}( #{a1}, #{a2} )"
33
39
  else
34
40
  return basic_usage( arg1, arg2 )
@@ -37,54 +43,6 @@ module BOAST
37
43
 
38
44
  end
39
45
 
40
- class Set < Operator
41
-
42
- def Set.to_s(arg1, arg2, return_type)
43
- if lang == C or lang == CL then
44
- if arg1.class == Variable and arg1.type.vector_length > 1 then
45
- if arg2.kind_of?( Array ) then
46
- raise "Invalid array length!" unless arg2.length == arg1.type.vector_length
47
- return "#{arg1} = (#{arg1.type.decl})( #{arg2.join(", ")} )" if lang == CL
48
-
49
- instruction = intrinsics[get_architecture][:SET][get_vector_name(arg1.type)]
50
- if not instruction then
51
- instruction = intrinsics[get_architecture][:SET_LANE][get_vector_name(arg1.type)]
52
- raise "Unavailable operator set for #{get_vector_name(arg1.type)}!" unless instruction
53
- s = "#{arg1}"
54
- arg2.each_with_index { |v,i|
55
- s = "#{instruction}(#{v}, #{s}, #{i})"
56
- }
57
- return "#{arg1} = #{s}"
58
- else
59
- return "#{arg1} = #{instruction}( #{arg2.join(", ")} )"
60
- end
61
- elsif arg2.class != Variable or arg2.type.vector_length == 1 then
62
- return "#{arg1} = (#{arg1.type.decl})( #{arg2} )" if lang == CL
63
-
64
- instruction = intrinsics[get_architecture][:SET1][get_vector_name(arg1.type)]
65
- raise "Unavailable operator set1 for #{get_vector_name(arg1.type)}!" unless instruction
66
- return "#{arg1} = #{instruction}( #{arg2} )"
67
- elsif arg1.type == arg2.type then
68
- return basic_usage(arg1, arg2)
69
- elsif arg1.type.vector_length == arg2.type.vector_length then
70
- return "#{arg1} = #{convert(arg2, arg1.type)}"
71
- else
72
- raise "Unknown convertion between vector of different length!"
73
- end
74
- else
75
- return basic_usage(arg1, arg2)
76
- end
77
- else
78
- return basic_usage(arg1, arg2)
79
- end
80
- end
81
-
82
- def Set.basic_usage(arg1, arg2)
83
- return "(#{arg1} = #{arg2})"
84
- end
85
-
86
- end
87
-
88
46
  class Different < Operator
89
47
 
90
48
  def Different.to_s(arg1, arg2, return_type)
@@ -98,90 +56,13 @@ module BOAST
98
56
 
99
57
  end
100
58
 
101
- class Load < Operator
102
-
103
- def Load.to_s(arg1, arg2, return_type)
104
- if lang == C or lang == CL then
105
- if arg1 then
106
- if arg1.class == Variable and arg1.type.vector_length > 1 then
107
- if arg2.kind_of?( Array ) then
108
- return Set.to_s(arg1, arg2, return_type)
109
- elsif arg1.type == arg2.type then
110
- return Affectation.basic_usage(arg1, arg2)
111
- elsif arg1.type.vector_length == arg2.type.vector_length then
112
- return "#{arg1} = #{convert(arg2, arg1.type)}"
113
- elsif arg2.type.vector_length == 1 then
114
- return "#{arg1} = #{Load.to_s(nil, arg2, arg1)}"
115
- else
116
- raise "Unknown convertion between vectors of different length!"
117
- end
118
- else
119
- Affectation.basic_usage(arg1, arg2)
120
- end
121
- elsif arg2.class == Variable and arg2.type.vector_length == 1 then
122
- a2 = "#{arg2}"
123
- if a2[0] != "*" then
124
- a2 = "&" + a2
125
- else
126
- a2 = a2[1..-1]
127
- end
128
-
129
- return "vload#{return_type.type.vector_length}(0, #{a2})" if lang == CL
130
- return "#{arg1} = _m_from_int64( *((int64_t * ) #{a2} ) )" if get_architecture == X86 and arg2.type.total_size*8 == 64
131
-
132
- if arg2.align == return_type.type.total_size then
133
- instruction = intrinsics[get_architecture][:LOADA][get_vector_name(return_type.type)]
134
- else
135
- instruction = intrinsics[get_architecture][:LOAD][get_vector_name(return_type.type)]
136
- end
137
- raise "Unavailable operator load for #{get_vector_name(return_type.type)}!" unless instruction
138
- return "#{instruction}( #{a2} )"
139
- else
140
- return "#{arg2}"
141
- end
142
- end
143
- return Affectation.basic_usage(arg1, arg2) if arg1
144
- return "#{arg2}"
145
- end
146
-
147
- end
148
-
149
- class Store < Operator
150
-
151
- def Store.to_s(arg1, arg2, return_type)
152
- if lang == C or lang == CL then
153
- a1 = "#{arg1}"
154
- if a1[0] != "*" then
155
- a1 = "&" + a1
156
- else
157
- a1 = a1[1..-1]
158
- end
159
-
160
- return "vstore#{arg2.type.vector_length}(#{arg2}, 0, #{a1})" if lang == CL
161
- return "*((int64_t * ) #{a1}) = _m_to_int64( #{arg2} )" if get_architecture == X86 and arg2.type.total_size*8 == 64
162
-
163
- if arg1.align == arg2.type.total_size then
164
- instruction = intrinsics[get_architecture][:STOREA][get_vector_name(arg2.type)]
165
- else
166
- instruction = intrinsics[get_architecture][:STORE][get_vector_name(arg2.type)]
167
- end
168
- raise "Unavailable operator store for #{get_vector_name(arg2.type)}!" unless instruction
169
- p_type = arg2.type.copy(:vector_length => 1)
170
- p_type = arg2.type if get_architecture == X86 and arg2.type.kind_of?(Int)
171
- return "#{instruction}( (#{p_type.decl} * ) #{a1}, #{arg2} )"
172
- end
173
- return Affectation.basic_usage(arg1, arg2)
174
- end
175
-
176
- end
177
-
178
59
  class Affectation < Operator
179
60
 
180
61
  def Affectation.to_s(arg1, arg2, return_type)
181
62
  if arg1.class == Variable and arg1.type.vector_length > 1 then
182
- return Load.to_s(arg1, arg2, return_type)
63
+ return "#{arg1} = #{Load(arg2, arg1)}"
183
64
  elsif arg2.class == Variable and arg2.type.vector_length > 1 then
184
- return Store.to_s(arg1, arg2, return_type)
65
+ return "#{Store(arg1, arg2, return_type)}"
185
66
  end
186
67
  return basic_usage(arg1, arg2)
187
68
  end
@@ -288,6 +169,365 @@ module BOAST
288
169
 
289
170
  end
290
171
 
172
+ class Set < Operator
173
+ extend Functor
174
+ include Intrinsics
175
+ include Arithmetic
176
+ include Inspectable
177
+ include PrivateStateAccessor
178
+
179
+ attr_reader :source
180
+ attr_reader :return_type
181
+
182
+ def initialize(source, return_type)
183
+ @source = source
184
+ @return_type = return_type
185
+ end
186
+
187
+ def type
188
+ return @return_type.type
189
+ end
190
+
191
+ def to_var
192
+ if lang == C or lang == CL and @return_type.type.vector_length > 1 then
193
+ if @source.kind_of?( Array ) then
194
+ raise "Invalid array length!" unless @source.length == @return_type.type.vector_length
195
+ return @return_type.copy("(#{@return_type.type.decl})( #{@source.join(", ")} )", DISCARD_OPTIONS) if lang == CL
196
+
197
+ instruction = intrinsics(:SET, @return_type.type)
198
+ return @return_type.copy("#{instruction}( #{@source.join(", ")} )", DISCARD_OPTIONS) if instruction
199
+
200
+ instruction = intrinsics(:SET_LANE, @return_type.type)
201
+ raise "Unavailable operator set for #{get_vector_name(@return_type.type)}!" unless instruction
202
+ s = Set(0, @return_type).to_s
203
+ @source.each_with_index { |v,i|
204
+ s = "#{instruction}(#{v}, #{s}, #{i})"
205
+ }
206
+ return @return_type.copy(s, DISCARD_OPTIONS)
207
+ elsif @source.class != Variable or @source.type.vector_length == 1 then
208
+ return @return_type.copy("(#{@return_type.type.decl})( #{@source} )", DISCARD_OPTIONS) if lang == CL
209
+
210
+ instruction = intrinsics(:SET1, @return_type.type)
211
+ raise "Unavailable operator set1 for #{get_vector_name(@return_type.type)}!" unless instruction
212
+ return @return_type.copy("#{instruction}( #{@source} )", DISCARD_OPTIONS)
213
+ elsif @return_type.type != @source.type
214
+ return @return_type.copy("#{Operator.convert(@source, @return_type.type)}", DISCARD_OPTIONS)
215
+ end
216
+ end
217
+ return @return_type.copy("#{@source}", DISCARD_OPTIONS)
218
+ end
219
+
220
+ def to_s
221
+ return to_var.to_s
222
+ end
223
+
224
+ def pr
225
+ s=""
226
+ s += indent
227
+ s += to_s
228
+ s += ";" if [C, CL, CUDA].include?( lang )
229
+ output.puts s
230
+ return self
231
+ end
232
+
233
+ end
234
+
235
+ class Load < Operator
236
+ extend Functor
237
+ include Intrinsics
238
+ include Arithmetic
239
+ include Inspectable
240
+ include PrivateStateAccessor
241
+
242
+ attr_reader :source
243
+ attr_reader :return_type
244
+
245
+ def initialize(source, return_type)
246
+ @source = source
247
+ @return_type = return_type
248
+ end
249
+
250
+ def type
251
+ return @return_type.type
252
+ end
253
+
254
+ def to_var
255
+ if lang == C or lang == CL then
256
+ if @source.kind_of?(Array) then
257
+ return Set(@source, @return_type).to_var
258
+ elsif @source.class == Variable or @source.respond_to?(:to_var) then
259
+ if @source.to_var.type == @return_type.type
260
+ return @source.to_var
261
+ elsif @source.to_var.type.vector_length == 1 then
262
+ a2 = "#{@source}"
263
+ if a2[0] != "*" then
264
+ a2 = "&" + a2
265
+ else
266
+ a2 = a2[1..-1]
267
+ end
268
+ return @return_type.copy("vload#{@return_type.type.vector_length}(0, #{a2})", DISCARD_OPTIONS) if lang == CL
269
+ 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.align == @return_type.type.total_size then
271
+ instruction = intrinsics(:LOADA, @return_type.type)
272
+ else
273
+ instruction = intrinsics(:LOAD, @return_type.type)
274
+ end
275
+ raise "Unavailable operator load for #{get_vector_name(@return_type.type)}!" unless instruction
276
+ return @return_type.copy("#{instruction}( #{a2} )", DISCARD_OPTIONS)
277
+ else
278
+ return @return_type.copy("#{Operator.convert(@source, @return_type.type)}", DISCARD_OPTIONS)
279
+ end
280
+ end
281
+ end
282
+ return @return_type.copy("#{@source}", DISCARD_OPTIONS)
283
+ end
284
+
285
+ def to_s
286
+ return to_var.to_s
287
+ end
288
+
289
+ def pr
290
+ s=""
291
+ s += indent
292
+ s += to_s
293
+ s += ";" if [C, CL, CUDA].include?( lang )
294
+ output.puts s
295
+ return self
296
+ end
297
+
298
+ end
299
+
300
+ class MaskLoad < Operator
301
+ extend Functor
302
+ include Intrinsics
303
+ include Arithmetic
304
+ include Inspectable
305
+ include PrivateStateAccessor
306
+
307
+ attr_reader :source
308
+ attr_reader :mask
309
+ attr_reader :return_type
310
+
311
+ def initialize(source, mask, return_type)
312
+ @source = source
313
+ @mask = mask
314
+ @return_type = return_type
315
+ end
316
+
317
+ 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
319
+ 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
+ end
321
+
322
+ private :get_mask
323
+
324
+ def type
325
+ return @return_type.type
326
+ end
327
+
328
+ def to_var
329
+ raise "Cannot load unknown type!" unless @return_type
330
+ raise "Unsupported language!" unless lang == C
331
+ raise "MaskLoad not supported!"unless supported(:MASKLOAD, @return_type.type)
332
+ s = ""
333
+ src = "#{@source}"
334
+ if src[0] != "*" then
335
+ src = "&" + src
336
+ else
337
+ src = src[1..-1]
338
+ end
339
+ p_type = @return_type.type.copy(:vector_length => 1)
340
+ s += "#{intrinsics(:MASKLOAD, @return_type.type)}((#{p_type.decl} * )#{src}, #{get_mask})"
341
+ return @return_type.copy( s, DISCARD_OPTIONS)
342
+ end
343
+
344
+ def to_s
345
+ return to_var.to_s
346
+ end
347
+
348
+ def pr
349
+ s=""
350
+ s += indent
351
+ s += to_s
352
+ s += ";" if [C, CL, CUDA].include?( lang )
353
+ output.puts s
354
+ return self
355
+ end
356
+
357
+ end
358
+
359
+ class Store < Operator
360
+ extend Functor
361
+ include Intrinsics
362
+ include Arithmetic
363
+ include Inspectable
364
+ include PrivateStateAccessor
365
+
366
+ attr_reader :dest
367
+ attr_reader :source
368
+ attr_reader :store_type
369
+
370
+ def initialize(dest, source, mask, store_type = nil)
371
+ @dest = dest
372
+ @source = source
373
+ @store_type = store_type
374
+ @store_type = source unless @store_type
375
+ end
376
+
377
+ def to_s
378
+ if lang == C or lang == CL then
379
+ dst = "#{@dest}"
380
+ if dst[0] != "*" then
381
+ dst = "&" + dst
382
+ else
383
+ dst = dst[1..-1]
384
+ end
385
+
386
+ return "vstore#{@source.type.vector_length}(#{@source}, 0, #{dst})" if lang == CL
387
+ return "*((int64_t * ) #{dst}) = _m_to_int64( #{@source} )" if get_architecture == X86 and @source.type.total_size*8 == 64
388
+
389
+ if @dest.align == @source.type.total_size then
390
+ instruction = intrinsics(:STOREA, @source.type)
391
+ else
392
+ instruction = intrinsics(:STORE, @source.type)
393
+ end
394
+ raise "Unavailable operator store for #{get_vector_name(@source.type)}!" unless instruction
395
+ p_type = @source.type.copy(:vector_length => 1)
396
+ p_type = @source.type if get_architecture == X86 and @source.type.kind_of?(Int)
397
+ return "#{instruction}( (#{p_type.decl} * ) #{dst}, #{@source} )"
398
+ end
399
+ return Affectation.basic_usage(@dest, @source)
400
+ end
401
+
402
+ def pr
403
+ s=""
404
+ s += indent
405
+ s += to_s
406
+ s += ";" if [C, CL, CUDA].include?( lang )
407
+ output.puts s
408
+ return self
409
+ end
410
+
411
+ end
412
+
413
+ class MaskStore < Operator
414
+ extend Functor
415
+ include Intrinsics
416
+ include Arithmetic
417
+ include Inspectable
418
+ include PrivateStateAccessor
419
+
420
+ attr_reader :dest
421
+ attr_reader :source
422
+ attr_reader :mask
423
+ attr_reader :store_type
424
+
425
+ def initialize(dest, source, mask, store_type = nil)
426
+ @dest = dest
427
+ @source = source
428
+ @mask = mask
429
+ @store_type = store_type
430
+ @store_type = source unless @store_type
431
+ end
432
+
433
+ 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
435
+ 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
+ end
437
+
438
+ private :get_mask
439
+
440
+ def to_s
441
+ raise "Cannot store unknown type!" unless @store_type
442
+ raise "Unsupported language!" unless lang == C
443
+ raise "MaskStore not supported!"unless supported(:MASKSTORE, @store_type.type)
444
+ s = ""
445
+ dst = "#{@dest}"
446
+ if dst[0] != "*" then
447
+ dst = "&" + dst
448
+ else
449
+ dst = dst[1..-1]
450
+ end
451
+ p_type = @store_type.type.copy(:vector_length => 1)
452
+ return s += "#{intrinsics(:MASKSTORE, @store_type.type)}((#{p_type.decl} * )#{dst}, #{get_mask}, #{Operator.convert(@source, @store_type.type)})"
453
+ end
454
+
455
+ def pr
456
+ s=""
457
+ s += indent
458
+ s += to_s
459
+ s += ";" if [C, CL, CUDA].include?( lang )
460
+ output.puts s
461
+ return self
462
+ end
463
+
464
+ end
465
+
466
+ class FMA < Operator
467
+ extend Functor
468
+ include Intrinsics
469
+ include Arithmetic
470
+ include Inspectable
471
+ include PrivateStateAccessor
472
+
473
+ attr_reader :operand1
474
+ attr_reader :operand2
475
+ attr_reader :operand3
476
+ attr_reader :return_type
477
+
478
+ def initialize(a,b,c)
479
+ @operand1 = a
480
+ @operand2 = b
481
+ @operand3 = c
482
+ @return_type = nil
483
+ @return_type = @operand3.to_var unless @return_type
484
+ end
485
+
486
+ def convert_operand(op)
487
+ return "#{Operator.convert(op, @return_type.type)}"
488
+ end
489
+
490
+ private :convert_operand
491
+
492
+ def type
493
+ return @return_type.type
494
+ end
495
+
496
+ def to_var
497
+ return (@operand3 + @operand1 * @operand2).to_var unless lang != FORTRAN and @return_type and ( supported(:FMADD, @return_type.type) or ( [CL, CUDA].include?(lang) ) )
498
+ op1 = convert_operand(@operand1)
499
+ op2 = convert_operand(@operand2)
500
+ op3 = convert_operand(@operand3)
501
+ if [CL, CUDA].include?(lang)
502
+ ret_name = "fma(#{op1},#{op2},#{op3})"
503
+ else
504
+ case architecture
505
+ when X86
506
+ ret_name = "#{intrinsics(:FMADD,@return_type.type)}(#{op1},#{op2},#{op3})"
507
+ when ARM
508
+ ret_name = "#{intrinsics(:FMADD,@return_type.type)}(#{op2},#{op3},#{op1})"
509
+ else
510
+ return (@operand1 * @operand2 + @operand3).to_var
511
+ end
512
+ end
513
+ return @return_type.copy( ret_name, DISCARD_OPTIONS)
514
+ end
515
+
516
+ def to_s
517
+ return to_var.to_s
518
+ end
519
+
520
+ def pr
521
+ s=""
522
+ s += indent
523
+ s += to_s
524
+ s += ";" if [C, CL, CUDA].include?( lang )
525
+ output.puts s
526
+ return self
527
+ end
528
+
529
+ end
530
+
291
531
  class Ternary
292
532
  extend Functor
293
533
  include Arithmetic
@@ -218,7 +218,7 @@ module BOAST
218
218
  end
219
219
 
220
220
  def open_c
221
- s = decl_c_s + "{"
221
+ s = indent + decl_c_s + "{"
222
222
  output.puts s
223
223
  increment_indent_level
224
224
  constants.each { |c|
@@ -37,6 +37,20 @@ EOF
37
37
  }
38
38
  end
39
39
 
40
+ def self.default_state_getter(arg, default, get_env_string=nil, env = arg.upcase)
41
+ envs = "ENV['#{env}']"
42
+ s = <<EOF
43
+ def get_default_#{arg}
44
+ #{arg} = #{default.inspect}
45
+ #{arg} = #{get_env_string ? eval( "#{get_env_string}" ) : "YAML::load(#{envs})" } if #{envs}
46
+ return #{arg}
47
+ end
48
+ module_function :get_default_#{arg}
49
+ @@#{arg} = get_default_#{arg}
50
+ EOF
51
+ eval s
52
+ end
53
+
40
54
  module PrivateStateAccessor
41
55
 
42
56
  def self.private_state_accessor(*args)
@@ -34,7 +34,7 @@ module BOAST
34
34
  signed = (signed or var2.type.signed)
35
35
  size = [var1.type.size, var2.type.size].max
36
36
  vector_length = [var1.type.vector_length, var2.type.vector_length].max
37
- [Variable::new("dummy", return_type, :size => size, :signed => signed, :vector_length => vector_length), operator]
37
+ return [Variable::new("dummy", return_type, :size => size, :signed => signed, :vector_length => vector_length), operator]
38
38
  elsif var1.type.class == return_type then
39
39
  return [var1, operator]
40
40
  else # var2.type.class == return_type then