cast_off 0.2.3 → 0.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.
@@ -6,40 +6,55 @@ module CastOff::Compiler
6
6
  include CastOff::Util
7
7
  include SimpleIR
8
8
 
9
- attr_reader :variable_definition, :undefs, :block, :alias
10
- attr_reader :variable_condition
9
+ attr_reader :definition, :undefs, :block, :alias
11
10
 
12
- def initialize(block, vars, a, defs, undefs, ptr_defs, ptrs)
11
+ def initialize(block, vars, a, c, defs, undefs, ptr_defs, ptrs)
13
12
  @block = block
14
13
  @alias = a.instance_of?(Alias) ? a : Alias.new(@block, a, vars, ptrs)
15
- @variable_definition = defs
14
+ @condition = c
15
+ @definition = defs
16
16
  @ptr_defs = ptr_defs
17
17
  @undefs = undefs
18
18
  @ptrs = ptrs
19
19
  @vars = vars
20
- @variable_condition = VariableCondition.new(@block, @ptrs, @alias)
21
20
  check_initialize()
22
21
  end
23
22
 
23
+ def initialize_condition()
24
+ @condition = Condition.new(@block, @ptrs, @alias)
25
+ end
26
+
27
+ def condition()
28
+ @condition
29
+ end
30
+
31
+ def condition=(cond)
32
+ bug() unless @condition
33
+ bug() unless cond.instance_of?(Condition)
34
+ @condition = cond
35
+ end
36
+
24
37
  def freeze()
25
38
  super()
26
39
  check_initialize()
27
40
  @alias.freeze()
28
- @variable_definition.freeze()
41
+ @definition.freeze()
29
42
  @ptr_defs.freeze()
30
43
  @undefs.freeze()
31
44
  @ptrs.freeze()
32
45
  @vars.freeze()
33
- @variable_condition.freeze()
46
+ @condition.freeze()
47
+ self
34
48
  end
35
49
 
36
50
  def final_state()
37
51
  # variable_condition までは final_state にならないので注意
38
52
  check_initialize()
39
53
  final_alias = @alias.final_state()
40
- final_defs = (@variable_definition - @block.ekill) | @block.egen
54
+ final_cond = @condition ? @condition.final_state() : nil
55
+ final_defs = (@definition - @block.ekill) | @block.egen
41
56
  final_undefs = @undefs + @block.ekill.map{|ir| ir.result_variable} - @block.egen.map{|ir| ir.result_variable}
42
- Information.new(@block, @vars, final_alias, final_defs, final_undefs, @ptr_defs, @ptrs)
57
+ Information.new(@block, @vars, final_alias, final_cond, final_defs, final_undefs, @ptr_defs, @ptrs)
43
58
  end
44
59
 
45
60
  def find_same_variables(var)
@@ -51,7 +66,7 @@ module CastOff::Compiler
51
66
  check_initialize()
52
67
  @alias.validate()
53
68
  bug() unless @alias.final_state() == @block.information.alias.final_state()
54
- defs = @variable_definition.map{|d| d.result_variable}.compact()
69
+ defs = @definition.map{|d| d.result_variable}.compact()
55
70
  bug() unless (defs & @undefs).empty?
56
71
  bug() unless (@vars - (defs | @undefs)).empty?
57
72
  end
@@ -60,15 +75,19 @@ module CastOff::Compiler
60
75
  check_initialize()
61
76
  @alias.validate()
62
77
  bug() unless @alias == @block.information.alias.final_state()
63
- defs = @variable_definition.map{|d| d.result_variable}.compact()
78
+ defs = @definition.map{|d| d.result_variable}.compact()
64
79
  bug() unless (defs & @undefs).empty?
65
80
  bug() unless (@vars - (defs | @undefs)).empty?
81
+ bug() unless @condition.instance_of?(Condition)
82
+ bug() unless @block.information.condition.instance_of?(Condition)
83
+ bug() unless @condition == @block.information.condition.final_state()
66
84
  end
67
85
 
68
86
  def step(ir)
69
87
  check_initialize()
70
88
  @alias.step(ir)
71
- @variable_condition.step(ir)
89
+ bug() unless @condition.instance_of?(Condition)
90
+ @condition.step(ir)
72
91
  delete(ir)
73
92
  add(ir)
74
93
  end
@@ -76,13 +95,14 @@ module CastOff::Compiler
76
95
  def |(other)
77
96
  check_initialize()
78
97
  bug() unless other.instance_of?(Information)
79
- Information.new(@block, @vars, @alias.union(other.alias), @variable_definition | other.variable_definition, @undefs | other.undefs, @ptr_defs, @ptrs)
98
+ bug() if @condition
99
+ Information.new(@block, @vars, @alias.union(other.alias), nil, @definition | other.definition, @undefs | other.undefs, @ptr_defs, @ptrs)
80
100
  end
81
101
 
82
102
  def kill_definition(other)
83
- @variable_definition.delete_if do |d0|
103
+ @definition.delete_if do |d0|
84
104
  next unless d0.result_variable
85
- not other.variable_definition.find{|d1| d0.result_variable == d1.result_variable}
105
+ not other.definition.find{|d1| d0.result_variable == d1.result_variable}
86
106
  end
87
107
  end
88
108
 
@@ -90,8 +110,9 @@ module CastOff::Compiler
90
110
  check_initialize()
91
111
  bug() unless other.instance_of?(Information)
92
112
  bug() unless @block == other.block
93
- return false unless (@variable_definition - other.variable_definition).empty? && (other.variable_definition - @variable_definition).empty?
113
+ return false unless (@definition - other.definition).empty? && (other.definition - @definition).empty?
94
114
  return false unless (@undefs - other.undefs).empty? && (other.undefs - @undefs).empty?
115
+ return false unless @condition == other.condition
95
116
  @alias == other.alias
96
117
  end
97
118
 
@@ -102,23 +123,23 @@ module CastOff::Compiler
102
123
 
103
124
  def size()
104
125
  check_initialize()
105
- @variable_definition.size()
126
+ @definition.size()
106
127
  end
107
128
 
108
129
  def replace_entry(ir)
109
130
  check_initialize()
110
- i = @variable_definition.index(ir)
111
- @variable_definition[i] = ir if i
131
+ i = @definition.index(ir)
132
+ @definition[i] = ir if i
112
133
  end
113
134
 
114
135
  def reject!(&b)
115
136
  check_initialize()
116
- @variable_definition.reject!{|ir| yield ir}
137
+ @definition.reject!{|ir| yield ir}
117
138
  end
118
139
 
119
140
  def flatten!
120
141
  check_initialize()
121
- @variable_definition.flatten!
142
+ @definition.flatten!
122
143
  end
123
144
 
124
145
  def hash()
@@ -127,16 +148,16 @@ module CastOff::Compiler
127
148
 
128
149
  def dup()
129
150
  check_initialize()
130
- Information.new(@block, @vars, @alias.dup(), @variable_definition.dup(), @undefs.dup(), @ptr_defs, @ptrs)
151
+ Information.new(@block, @vars, @alias.dup(), @condition ? @condition.dup() : nil, @definition.dup(), @undefs.dup(), @ptr_defs, @ptrs)
131
152
  end
132
153
 
133
154
  def to_s()
134
- @variable_definition.join("\n")
155
+ @definition.join("\n")
135
156
  end
136
157
 
137
- def variable_definition_of(var)
158
+ def definition_of(var)
138
159
  check_initialize()
139
- @variable_definition.select{|d| d.result_variable == var}
160
+ @definition.select{|d| d.result_variable == var}
140
161
  end
141
162
 
142
163
  def undefined_variables()
@@ -146,7 +167,7 @@ module CastOff::Compiler
146
167
 
147
168
  def mark(var)
148
169
  check_initialize()
149
- ds = @variable_definition.select {|d| var == d.result_variable }
170
+ ds = @definition.select {|d| var == d.result_variable }
150
171
  ds.inject(false){|change, d| d.alive() || change}
151
172
  end
152
173
 
@@ -156,9 +177,9 @@ module CastOff::Compiler
156
177
  return false unless var.is_a?(Variable)
157
178
  ret = false
158
179
 
159
- bug() unless @variable_condition
160
- ret |= @variable_condition.use(var)
161
- ds = @variable_definition.select {|d| var == d.result_variable }
180
+ bug() unless @condition
181
+ ret |= @condition.use(var)
182
+ ds = @definition.select {|d| var == d.result_variable }
162
183
  if @undefs.include?(var) || ds.empty?
163
184
  case var
164
185
  when TmpBuffer
@@ -180,7 +201,7 @@ module CastOff::Compiler
180
201
  check_initialize()
181
202
  return false if !var.is_a?(Variable) || var.class_exact?
182
203
 
183
- ds = @variable_definition.select{|d| var == d.result_variable }
204
+ ds = @definition.select{|d| var == d.result_variable }
184
205
  if @undefs.include?(var) || ds.empty?
185
206
  case var
186
207
  when TmpBuffer, Pointer, Argument, Self
@@ -203,7 +224,7 @@ module CastOff::Compiler
203
224
  def can_not_unbox_variable_resolve_forward(var)
204
225
  check_initialize()
205
226
  return false if var.can_not_unbox?
206
- ds = @variable_definition.select {|d| var == d.result_variable }
227
+ ds = @definition.select {|d| var == d.result_variable }
207
228
  if ds.empty?
208
229
  case var
209
230
  when TmpBuffer, Pointer, Argument, Self, ConstWrapper, Literal
@@ -224,7 +245,7 @@ module CastOff::Compiler
224
245
  def can_not_unbox_variable_resolve_backward(var)
225
246
  check_initialize()
226
247
  bug() unless var.can_not_unbox?
227
- ds = @variable_definition.select {|d| var == d.result_variable }
248
+ ds = @definition.select {|d| var == d.result_variable }
228
249
  if ds.empty?
229
250
  case var
230
251
  when TmpBuffer, Pointer, Argument, Self, ConstWrapper, Literal
@@ -240,7 +261,7 @@ module CastOff::Compiler
240
261
  check_initialize()
241
262
  bug() if !var.unboxed? && !var.boxed?
242
263
  return false if var.boxed?
243
- ds = @variable_definition.select {|d| var == d.result_variable }
264
+ ds = @definition.select {|d| var == d.result_variable }
244
265
  if ds.empty?
245
266
  case var
246
267
  when TmpBuffer, Pointer, Argument, Self, ConstWrapper, Literal
@@ -262,7 +283,7 @@ module CastOff::Compiler
262
283
  def box_value_resolve_backward(var)
263
284
  check_initialize()
264
285
  bug() unless var.boxed?
265
- ds = @variable_definition.select {|d| var == d.result_variable }
286
+ ds = @definition.select {|d| var == d.result_variable }
266
287
  if ds.empty?
267
288
  case var
268
289
  when TmpBuffer, Pointer, Argument, Self, ConstWrapper, Literal
@@ -278,7 +299,7 @@ module CastOff::Compiler
278
299
  check_initialize()
279
300
  bug() if var.can_not_unbox?
280
301
  return false if var.unboxed?
281
- ds = @variable_definition.select {|d| var == d.result_variable }
302
+ ds = @definition.select {|d| var == d.result_variable }
282
303
  if ds.empty?
283
304
  case var
284
305
  when TmpBuffer, Pointer, Argument, Self, ConstWrapper, Literal
@@ -308,239 +329,331 @@ module CastOff::Compiler
308
329
 
309
330
  def check_initialize()
310
331
  bug() unless @block.instance_of?(BasicBlock)
311
- bug() unless @variable_definition.instance_of?(Array)
332
+ bug() unless @definition.instance_of?(Array)
312
333
  bug() unless @ptr_defs.instance_of?(Array)
313
334
  bug() unless @undefs.instance_of?(Array)
314
335
  bug() unless @ptrs.instance_of?(Array)
315
336
  bug() unless @vars.instance_of?(Array)
316
337
  bug() unless @alias.instance_of?(Alias)
317
- bug() unless @variable_condition.instance_of?(VariableCondition)
338
+ bug() unless @condition.nil? || @condition.instance_of?(Condition)
318
339
  end
319
340
 
320
341
  def delete(ir)
321
342
  check_initialize()
322
- @variable_definition.reject!{|d| d.result_variable == ir.result_variable}
343
+ @definition.reject!{|d| d.result_variable == ir.result_variable}
323
344
  if ir.dispatch_method?
324
- @variable_definition -= @ptr_defs
345
+ @definition -= @ptr_defs
325
346
  @undefs |= @ptrs
326
347
  end
327
348
  end
328
349
 
329
350
  def add(ir)
330
351
  check_initialize()
331
- @variable_definition << ir
352
+ @definition << ir
332
353
  result_variable = ir.result_variable
333
354
  @undefs -= [result_variable] if result_variable
334
355
  end
356
+ end # Information
335
357
 
336
- class Alias
337
- include CastOff::Compiler::SimpleIR
338
- include CastOff::Util
339
- attr_reader :set
340
-
341
- def initialize(b, a, all, ptrs)
342
- bug() unless b.instance_of?(BasicBlock)
343
- @block = b
344
- @all = all
345
- @ptrs = ptrs
346
- case a
347
- when NilClass
348
- a = all.dup()
349
- bug() if a.find{|v| not v.is_a?(Variable)}
350
- @set = [a]
351
- when Array
352
- bug() if a.find{|v| not v.is_a?(Variable)}
353
- @set = a.map{|v| [v]}
354
- when Alias
355
- @set = a.set.map{|s| s.dup()}
356
- else
357
- bug()
358
- end
359
- validate()
360
- end
361
-
362
- def freeze()
363
- super()
364
- @all.freeze()
365
- @set.freeze()
366
- @ptrs.freeze()
367
- end
358
+ class Condition
359
+ include CastOff::Util
360
+ include SimpleIR
368
361
 
369
- def final_state()
370
- a = dup()
371
- @block.irs.each{|ir| a.step(ir)}
372
- a
373
- end
362
+ attr_reader :block, :condition, :temporary_condition
374
363
 
375
- def step(ir)
376
- case ir
377
- when SubIR
378
- src = ir.src
379
- dst = ir.dst
380
- src.is_a?(Variable) ? sub(src, dst) : isolate(dst)
381
- when CallIR
382
- return_value = ir.return_value
383
- bug() unless return_value.is_a?(Variable)
384
- isolate(return_value)
385
- @ptrs.each{|p| isolate(p)} if ir.dispatch_method?
386
- end
364
+ def initialize(b, ptrs, a_or_c, tmp = nil)
365
+ # 管理が煩雑になるので、alias を内部で保持しないこと。
366
+ # step 時に alias まで進めないと、final_state で古い alias を持つことになる。
367
+ @block = b
368
+ @ptrs = ptrs
369
+ @temporary_condition = tmp
370
+ case a_or_c
371
+ when Alias
372
+ @condition = initialize_condition_from_block(a_or_c)
373
+ when Hash
374
+ # @condition は呼び出し元で dup している
375
+ @condition = a_or_c
376
+ bug() if @condition.keys.find{|v| !v.is_a?(Variable)}
377
+ bug() if @condition.values.find{|p| !p.is_a?(Proc)}
378
+ else
379
+ bug()
387
380
  end
381
+ end
388
382
 
389
- def dup()
390
- Alias.new(@block, self, @all, @ptrs)
391
- end
383
+ def use(v)
384
+ promote_temporary_condition()
385
+ bug() if @temporary_condition
386
+ p = @condition[v]
387
+ p ? p.call(v) : false
388
+ end
392
389
 
393
- def find_set(var)
394
- bug() unless var.is_a?(Variable)
395
- set.each{|s| return s if s.include?(var)}
396
- bug("set = #{set}, var = #{var}, #{var.class}")
390
+ def step(ir)
391
+ promote_temporary_condition()
392
+ bug() if @temporary_condition
393
+ unless ir.result_variable
394
+ bug() if ir.dispatch_method?
395
+ return
397
396
  end
398
-
399
- def validate()
400
- a = @set.inject([]) do |ary, s|
401
- bug() unless (ary & s).empty?
402
- ary + s
397
+ case ir
398
+ when SubIR
399
+ src = ir.src
400
+ dst = ir.dst
401
+ if @condition[src]
402
+ @condition[dst] = @condition[src]
403
+ else
404
+ @condition.delete(dst)
403
405
  end
404
- size = @all.size()
405
- bug() unless a.size() == size && (a & @all).size() == size
406
+ when CallIR
407
+ return_value = ir.return_value
408
+ bug() unless return_value.is_a?(Variable)
409
+ @condition.delete(return_value)
410
+ @ptrs.each{|p| @condition.delete(p)} if ir.dispatch_method?
406
411
  end
412
+ end
407
413
 
408
- def eql?(other)
409
- other_set = other.set.dup()
410
- @set.each{|s| other_set.delete(s){return false}}
411
- bug() unless other_set.empty?
412
- return true
413
- end
414
+ def dup()
415
+ # condition は呼び出し元で dup する
416
+ tmp = @temporary_condition ? @temporary_condition.dup() : nil
417
+ Condition.new(@block, @ptrs, @condition.dup, tmp)
418
+ end
414
419
 
415
- def ==(other)
416
- eql?(other)
417
- end
420
+ def final_state
421
+ v = dup()
422
+ @block.irs.each{|ir| v.step(ir)}
423
+ v
424
+ end
418
425
 
419
- def union(other)
420
- a = @all.dup()
421
- new_set = []
422
- until a.empty?
423
- var = a.pop()
424
- s0 = find_set(var)
425
- s1 = other.find_set(var)
426
- s = s0 & s1
427
- new_set << s
428
- a -= s
426
+ def union(other)
427
+ bug() unless @block.pre.include?(other.block)
428
+ bug() unless other.instance_of?(Condition)
429
+ if @temporary_condition
430
+ tmp = @temporary_condition.dup
431
+ other.condition.each do |(v, p)|
432
+ tmp.delete(v) if !tmp[v] || (tmp[v] && tmp[v] != p)
429
433
  end
430
- @set = new_set
431
- validate()
432
- dup()
434
+ else
435
+ tmp = other.condition.dup
433
436
  end
437
+ # condition は呼び出し元で dup する
438
+ Condition.new(@block, @ptrs, @condition.dup, tmp)
439
+ end
434
440
 
435
- private
441
+ def eql?(other)
442
+ return false unless @block == other.block
443
+ return false unless @temporary_condition == other.temporary_condition
444
+ @condition == other.condition
445
+ end
436
446
 
437
- def sub(arg0, result)
438
- return if arg0 == result
439
- reject(result)
440
- s = find_set(arg0)
441
- bug() if s.include?(result)
442
- s << result
443
- end
447
+ def ==(other)
448
+ eql?(other)
449
+ end
444
450
 
445
- def isolate(var)
446
- reject(var)
447
- @set << [var]
448
- end
451
+ def hash
452
+ bug()
453
+ end
449
454
 
450
- def reject(var)
451
- s = find_set(var)
452
- s.delete(var){bug()}
453
- @set.delete(s){bug()} if s.empty?
454
- end
455
- end # Alias
455
+ def freeze()
456
+ super()
457
+ @ptrs.freeze()
458
+ @condition.freeze()
459
+ self
460
+ end
456
461
 
457
- class VariableCondition
458
- include CastOff::Util
459
- include SimpleIR
462
+ def to_s
463
+ @condition.inject(''){|str, (v, p)|
464
+ str.concat("#{v} => #{p}\n")
465
+ }.chomp
466
+ end
460
467
 
461
- attr_reader :block, :condition
468
+ private
462
469
 
463
- def initialize(b, ptrs, a)
464
- @block = b
465
- @ptrs = ptrs
466
- @condition = initialize_condition_from_block(a)
470
+ NilWrapper = ClassWrapper.new(NilClass, true)
471
+ FalseWrapper = ClassWrapper.new(FalseClass, true)
472
+ CondNotNilNotFalse = proc{|v| v.is_not([NilWrapper, FalseWrapper])}
473
+ CondNilOrFalse = proc{|v| v.is_negative_cond_value; v.is_static([NilWrapper, FalseWrapper])}
474
+ CondNotNilNotFalse.instance_eval do
475
+ def to_s
476
+ "neither nil nor false"
467
477
  end
468
-
469
- def use(v)
470
- p = @condition[v]
471
- p ? p.call(v) : false
478
+ end
479
+ CondNilOrFalse.instance_eval do
480
+ def to_s
481
+ "nil or false"
472
482
  end
483
+ end
484
+ def initialize_condition_from_block(a)
485
+ cond = {}
486
+ bug() unless a.instance_of?(Alias)
487
+ return cond unless @block.pre.size == 1
488
+ b = @block.pre[0]
489
+ ir = b.irs.last
490
+ return cond unless ir.is_a?(JumpIR)
491
+ fallthrough = (ir.jump_targets & @block.labels).empty?
492
+ p = nil
493
+ case ir.jump_type
494
+ when :branchif
495
+ p = fallthrough ? CondNilOrFalse : CondNotNilNotFalse
496
+ when :branchunless
497
+ p = fallthrough ? CondNotNilNotFalse : CondNilOrFalse
498
+ end
499
+ if p
500
+ set = a.find_set(ir.cond_value)
501
+ bug() if set.empty?
502
+ set.each{|s| cond[s] = p}
503
+ end
504
+ cond
505
+ end
473
506
 
474
- def step(ir)
475
- unless ir.result_variable
476
- bug() if ir.dispatch_method?
477
- return
478
- end
479
- @condition.delete(ir.result_variable)
480
- @ptrs.each{|p| @condition.delete(p)} if ir.dispatch_method?
507
+ def promote_temporary_condition()
508
+ return unless @temporary_condition
509
+ bug() unless @temporary_condition.instance_of?(Hash)
510
+ @temporary_condition.each do |(v, p)|
511
+ bug() unless v.is_a?(Variable)
512
+ bug() if @condition[v] && @condition[v] != p
513
+ @condition[v] = p
481
514
  end
515
+ @temporary_condition = nil
516
+ end
517
+ end #Condition
482
518
 
483
- def eql?(other)
484
- #@condition == other.condition && @block == other.block
519
+ def calc_egen_ekill
520
+ all = all_ir()
521
+ @blocks.each { |b| b.calc_egen() }
522
+ @blocks.each { |b| b.calc_ekill(all) }
523
+ end
524
+
525
+ class Alias
526
+ include CastOff::Compiler::SimpleIR
527
+ include CastOff::Util
528
+ attr_reader :set
529
+
530
+ def initialize(b, a, all, ptrs)
531
+ bug() unless b.instance_of?(BasicBlock)
532
+ @block = b
533
+ @all = all
534
+ @ptrs = ptrs
535
+ case a
536
+ when NilClass
537
+ a = all.dup()
538
+ bug() if a.find{|v| not v.is_a?(Variable)}
539
+ @set = [a]
540
+ when Array
541
+ bug() if a.find{|v| not v.is_a?(Variable)}
542
+ @set = a.map{|v| [v]}
543
+ when Alias
544
+ @set = a.set.map{|s| s.dup()}
545
+ else
485
546
  bug()
486
547
  end
548
+ validate()
549
+ end
550
+
551
+ def freeze()
552
+ super()
553
+ @all.freeze()
554
+ @set.freeze()
555
+ @ptrs.freeze()
556
+ self
557
+ end
487
558
 
488
- def ==(other)
489
- eql?(other)
559
+ def final_state()
560
+ a = dup()
561
+ @block.irs.each{|ir| a.step(ir)}
562
+ a
563
+ end
564
+
565
+ def step(ir)
566
+ case ir
567
+ when SubIR
568
+ src = ir.src
569
+ dst = ir.dst
570
+ src.is_a?(Variable) ? sub(src, dst) : isolate(dst)
571
+ when CallIR
572
+ return_value = ir.return_value
573
+ bug() unless return_value.is_a?(Variable)
574
+ isolate(return_value)
575
+ @ptrs.each{|p| isolate(p)} if ir.dispatch_method?
490
576
  end
577
+ end
491
578
 
492
- def hash
493
- bug()
579
+ def dup()
580
+ Alias.new(@block, self, @all, @ptrs)
581
+ end
582
+
583
+ def find_set(var)
584
+ bug() unless var.is_a?(Variable)
585
+ set.each{|s| return s if s.include?(var)}
586
+ bug("set = #{set}, var = #{var}, #{var.class}")
587
+ end
588
+
589
+ def validate()
590
+ a = @set.inject([]) do |ary, s|
591
+ bug() unless (ary & s).empty?
592
+ ary + s
494
593
  end
594
+ size = @all.size()
595
+ bug() unless a.size() == size && (a & @all).size() == size
596
+ end
495
597
 
496
- def freeze()
497
- super()
498
- @ptrs.freeze()
499
- @condition.freeze()
500
- end
501
-
502
- private
503
-
504
- NilWrapper = ClassWrapper.new(NilClass, true)
505
- FalseWrapper = ClassWrapper.new(FalseClass, true)
506
- def initialize_condition_from_block(a)
507
- cond = {}
508
- bug() unless a.instance_of?(Alias)
509
- return cond unless @block.pre.size == 1
510
- b = @block.pre[0]
511
- ir = b.irs.last
512
- return cond unless ir.is_a?(JumpIR)
513
- fallthrough = (ir.jump_targets & @block.labels).empty?
514
- p = nil
515
- case ir.jump_type
516
- when :branchif
517
- if fallthrough
518
- p = proc{|v| v.is_negative_cond_value; v.is_static([NilWrapper, FalseWrapper])}
519
- else
520
- p = proc{|v| v.is_not([NilWrapper, FalseWrapper])}
521
- end
522
- when :branchunless
523
- if fallthrough
524
- p = proc{|v| v.is_not([NilWrapper, FalseWrapper])}
525
- else
526
- p = proc{|v| v.is_negative_cond_value; v.is_static([NilWrapper, FalseWrapper])}
527
- end
528
- end
529
- if p
530
- set = a.find_set(ir.cond_value)
531
- bug() if set.empty?
532
- set.each{|s| cond[s] = p}
533
- end
534
- cond
598
+ def eql?(other)
599
+ other_set = other.set.dup()
600
+ @set.each{|s| other_set.delete(s){return false}}
601
+ bug() unless other_set.empty?
602
+ return true
603
+ end
604
+
605
+ def ==(other)
606
+ eql?(other)
607
+ end
608
+
609
+ def __union(other)
610
+ a = @all.dup()
611
+ new_set = []
612
+ until a.empty?
613
+ var = a.pop()
614
+ s0 = find_set(var)
615
+ s1 = other.find_set(var)
616
+ s = s0 & s1
617
+ new_set << s
618
+ a -= s
535
619
  end
536
- end #VariableCondition
537
- end # Information
620
+ @set = new_set
621
+ validate()
622
+ end
538
623
 
539
- def calc_egen_ekill
540
- all = all_ir()
541
- @blocks.each { |b| b.calc_egen() }
542
- @blocks.each { |b| b.calc_ekill(all) }
543
- end
624
+ def union(other)
625
+ a = dup()
626
+ a.__union(other)
627
+ a
628
+ end
629
+
630
+ def to_s
631
+ @set.inject(''){|str, s|
632
+ str.concat(s.map{|v| v.to_debug_string}.join(", ")).concat("\n")
633
+ }.chomp
634
+ end
635
+
636
+ private
637
+
638
+ def sub(arg0, result)
639
+ return if arg0 == result
640
+ reject(result)
641
+ s = find_set(arg0)
642
+ bug() if s.include?(result)
643
+ s << result
644
+ end
645
+
646
+ def isolate(var)
647
+ reject(var)
648
+ @set << [var]
649
+ end
650
+
651
+ def reject(var)
652
+ s = find_set(var)
653
+ s.delete(var){bug()}
654
+ @set.delete(s){bug()} if s.empty?
655
+ end
656
+ end # Alias
544
657
 
545
658
  class BasicBlock
546
659
  attr_reader :egen, :ekill
@@ -612,6 +725,25 @@ module CastOff::Compiler
612
725
  end
613
726
  end
614
727
 
728
+ def set_condition
729
+ @blocks.each{|b| b.information.initialize_condition()}
730
+ change = true
731
+ entry = @blocks.first
732
+ while change
733
+ change = false
734
+ @blocks.each do |b0|
735
+ next if b0 == entry
736
+ info = b0.information
737
+ cond = b0.pre.inject(info.condition.dup) do |c, b1|
738
+ next c if b0 == b1
739
+ c.union(b1.information.condition.final_state)
740
+ end
741
+ change = true if info.condition != cond
742
+ info.condition = cond
743
+ end
744
+ end
745
+ end
746
+
615
747
  def set_information
616
748
  ptr_defs = all_pointer_definition()
617
749
  ptrs = all_pointer()
@@ -622,14 +754,14 @@ module CastOff::Compiler
622
754
  bug() if @blocks.find{|b| (not b.in_undefined) || (not b.out_undefined)}
623
755
  bug() if @blocks.find{|b| b != entry && b.pre.empty? }
624
756
  bug() unless entry.pre.empty?
625
- @blocks.each{|b| b.information = Information.new(b, vars, vars, [], [], ptr_defs, ptrs)}
626
- entry.information = Information.new(entry, vars, vars, [], vars, ptr_defs, ptrs)
757
+ @blocks.each{|b| b.information = Information.new(b, vars, vars, nil, [], [], ptr_defs, ptrs)}
758
+ entry.information = Information.new(entry, vars, vars, nil, [], vars, ptr_defs, ptrs)
627
759
  change = true
628
760
  while change
629
761
  change = false
630
762
  @blocks.each do |b0|
631
763
  next if b0 == entry
632
- info = b0.pre.inject(Information.new(b0, vars, nil, [], [], ptr_defs, ptrs)) {|info, b1| info | b1.information.final_state()}
764
+ info = b0.pre.inject(Information.new(b0, vars, nil, nil, [], [], ptr_defs, ptrs)) {|info, b1| info | b1.information.final_state()}
633
765
  change = true if b0.information != info
634
766
  b0.information = info
635
767
  end
@@ -645,18 +777,19 @@ module CastOff::Compiler
645
777
  b0.information = info
646
778
  end
647
779
  end
780
+ set_condition()
648
781
  @blocks.each{|b| b.information.freeze()}
649
782
  # validation
650
783
  @blocks.each do |b|
651
- variable_definition = b.information.dup()
652
- variable_definition.validate()
784
+ definition = b.information.dup()
785
+ definition.validate()
653
786
  b.irs.each do |ir|
654
787
  ir.variables_without_result.each do |var|
655
- var.has_undefined_path() if variable_definition.undefined_variables.include?(var)
788
+ var.has_undefined_path() if definition.undefined_variables.include?(var)
656
789
  end
657
- variable_definition.step(ir)
790
+ definition.step(ir)
658
791
  end
659
- variable_definition.validate_final()
792
+ definition.validate_final()
660
793
  end
661
794
  @blocks.each do |b|
662
795
  u0 = b.in_undefined
@@ -676,18 +809,18 @@ module CastOff::Compiler
676
809
 
677
810
  def initialize(b, d, g, ptrs)
678
811
  @block = b
679
- @variable_definition = d
812
+ @definition = d
680
813
  @guards = g
681
814
  @ptrs = ptrs
682
815
  end
683
816
 
684
817
  def dup()
685
- Guards.new(@block, @variable_definition.dup(), @guards.dup(), @ptrs)
818
+ Guards.new(@block, @definition.dup(), @guards.dup(), @ptrs)
686
819
  end
687
820
 
688
821
  def &(other)
689
822
  bug() unless other.instance_of?(Guards)
690
- Guards.new(@block, @variable_definition.dup(), @guards & other.guards, @ptrs)
823
+ Guards.new(@block, @definition.dup(), @guards & other.guards, @ptrs)
691
824
  end
692
825
 
693
826
  def eql?(other)
@@ -707,7 +840,7 @@ module CastOff::Compiler
707
840
  end
708
841
 
709
842
  def validate_final()
710
- @variable_definition.validate_final()
843
+ @definition.validate_final()
711
844
  end
712
845
 
713
846
  def redundant?(ir)
@@ -720,7 +853,7 @@ module CastOff::Compiler
720
853
  guard_value = ir.guard_value
721
854
  bug() unless guard_value.is_a?(Variable)
722
855
  @guards | [guard_value]
723
- @guards |= @variable_definition.find_same_variables(guard_value)
856
+ @guards |= @definition.find_same_variables(guard_value)
724
857
  when SubIR
725
858
  src = ir.src
726
859
  dst = ir.dst
@@ -733,13 +866,14 @@ module CastOff::Compiler
733
866
  @guards -= [ir.return_value]
734
867
  @guards -= @ptrs if ir.dispatch_method?
735
868
  end
736
- @variable_definition.step(ir)
869
+ @definition.step(ir)
737
870
  end
738
871
 
739
872
  def freeze()
740
873
  super()
741
874
  @guards.freeze()
742
- @variable_definition.freeze()
875
+ @definition.freeze()
876
+ self
743
877
  end
744
878
 
745
879
  def to_s()