tclquadcode

Check-in [e2750cb57e]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Restructure pass management in 'tidy'. Add constant folding of a few more operations.
Timelines: family | ancestors | descendants | both | kbk-pre
Files: files | file ages | folders
SHA3-256:e2750cb57e4bd50578bc733e452958f525e1028f454faa6d021d711924bdc938
User & Date: kbk 2018-12-01 17:37:33
Context
2018-12-02
23:27
Turn on partial redundancy elimination. Correct bug in availability analysis that led to infinite loop in 'msrange2' check-in: 68da56cfee user: kbk tags: notworking, kbk-pre
2018-12-01
17:37
Restructure pass management in 'tidy'. Add constant folding of a few more operations. check-in: e2750cb57e user: kbk tags: kbk-pre
2018-11-29
00:56
merge trunk check-in: 815387c202 user: kbk tags: notworking, kbk-pre
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to quadcode/constfold.tcl.

59
60
61
62
63
64
65
66


67
68
69
70
71
72
73
..
81
82
83
84
85
86
87

































88
89
90
91
92
93
94
...
227
228
229
230
231
232
233


































































234
235
236
237
238
239
240
...
259
260
261
262
263
264
265

































266
267
268
269
270
271
272
...
372
373
374
375
376
377
378

































379
380
381
382
383
384
385
		    "directArrayLappend" - "directArrayLappendList" -
		    "directArraySet" - "directArrayUnset" - "directExists" -
		    "directGet" - "directLappend" - "directLappendList" -
		    "directSet" - "directUnset" - "directIsArray" -
		    "directMakeArray" - "foreachStart" - "entry" -
		    "extractExists" - "extractFail" -
		    "extractMaybe" - "initException" -
		    "jump" - "jumpFalse" - "jumpMaybe" - "jumpTrue" - "purify" -


		    "split" - "unshareList" -
		    "initArray" - "setReturnCode" - "resolveCmd" - "originCmd" {
			# do nothing - these insns are not killable
			# this case goes away once I have a better handle
			# on what's killable.
			# Note that the "direct..." operations are probably
			# never killable due to the potential for global
................................................................................
			my debug-constfold {
			    puts "$b:$pc: $q"
			    puts "    replace [lindex $q 1] with $res"
			}
			my replaceUses [lindex $q 1] $res
			set changed 1
		    }


































		    "bitand" {
			lassign $argl x y
			set res [list literal [expr {$x & $y}]]
			my debug-constfold {
			    puts "$b:$pc: $q"
			    puts "    replace [lindex $q 1] with $res"
................................................................................
			my debug-constfold {
			    puts "$b:$pc: $q"
			    puts "    replace [lindex $q 1] with {literal 1}"
			}
			my replaceUses [lindex $q 1] {literal 1}
			set changed 1
		    }



































































		    "ge" {
			lassign $argl x y
			set res [list literal [expr {$x >= $y}]]
			my debug-constfold {
			    puts "$b:$pc: $q"
			    puts "    replace [lindex $q 1] with $res"
................................................................................
			my debug-constfold {
			    puts "$b:$pc: $q"
			    puts "    replace [lindex $q 1] with $res"
			}
			my replaceUses [lindex $q 1] $res
			set changed 1
		    }


































		    "le" {
			lassign $argl x y
			set res [list literal [expr {$x <= $y}]]
			my debug-constfold {
			    puts "$b:$pc: $q"
			    puts "    replace [lindex $q 1] with $res"
................................................................................
			my debug-constfold {
			    puts "$b:$pc: $q"
			    puts "    replace [lindex $q 1] with $res"
			}
			my replaceUses [lindex $q 1] $res
			set changed 1
		    }


































		    "ne" {
			lassign $argl x y
			set res [list literal [expr {$x != $y}]]
			my debug-constfold {
			    puts "$b:$pc: $q"
			    puts "    replace [lindex $q 1] with $res"







|
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
..
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
...
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
...
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
...
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
		    "directArrayLappend" - "directArrayLappendList" -
		    "directArraySet" - "directArrayUnset" - "directExists" -
		    "directGet" - "directLappend" - "directLappendList" -
		    "directSet" - "directUnset" - "directIsArray" -
		    "directMakeArray" - "foreachStart" - "entry" -
		    "extractExists" - "extractFail" -
		    "extractMaybe" - "initException" -
		    "jump" - "jumpFalse" - "jumpMaybe" - "jumpTrue" -
		    "narrowToType" -
		    "procLeave" - "purify" -
		    "split" - "unshareList" -
		    "initArray" - "setReturnCode" - "resolveCmd" - "originCmd" {
			# do nothing - these insns are not killable
			# this case goes away once I have a better handle
			# on what's killable.
			# Note that the "direct..." operations are probably
			# never killable due to the potential for global
................................................................................
			my debug-constfold {
			    puts "$b:$pc: $q"
			    puts "    replace [lindex $q 1] with $res"
			}
			my replaceUses [lindex $q 1] $res
			set changed 1
		    }

		    "arrayExists" {
			my debug-constfold {
			    puts "$b:$pc: examine $q"
			}

			# What type do I want?
			set want $quadcode::dataType::ARRAY

			# What type do I have?
			set source [lindex $argl 0]
			set have [typeOfLiteral $source]

			# Can I say sommething definitive?
			unset -nocomplain replacement
			if {[quadcode::dataType::isa $have $want]} {
			    set replacement {literal 1}
			} elseif {![quadcode::dataType::mightbea $have $want]} {
			    set replacement {literal 0}
			}
			if {[info exists replacement]} {
			    my debug-constfold {
				puts "$b:$pc: can replace [lindex $q 1] with\
                                      $replacement and remove the instruction"
			    }
			    lset bbcontent $b $pc [list nop {}]
			    my removeUse $source $b
			    my replaceUses [lindex $q 1] $replacement
			    dict unset udchain [lindex $q 1]
			    set changed 1
			    continue; # delete the quad
			}			
		    }

		    "bitand" {
			lassign $argl x y
			set res [list literal [expr {$x & $y}]]
			my debug-constfold {
			    puts "$b:$pc: $q"
			    puts "    replace [lindex $q 1] with $res"
................................................................................
			my debug-constfold {
			    puts "$b:$pc: $q"
			    puts "    replace [lindex $q 1] with {literal 1}"
			}
			my replaceUses [lindex $q 1] {literal 1}
			set changed 1
		    }

		    "extractArray" {
			my debug-constfold {
			    puts "$b:$pc: examine $q"
			}

			# What type do I want?
			set want $quadcode::dataType::ARRAY

			# What type do I have?
			set source [lindex $argl 0]
			set have [typeOfLiteral $source]

			# Can I say sommething definitive?
			unset -nocomplain replacement
			if {[quadcode::dataType::isa $have $want]} {
			    set replacement [list literal $source]
			} elseif {![quadcode::dataType::mightbea $have $want]} {
			    # This is dead code, but we don't know it yet
			}
			if {[info exists replacement]} {
			    my debug-constfold {
				puts "$b:$pc: can replace [lindex $q 1] with\
                                      $replacement and remove the instruction"
			    }
			    lset bbcontent $b $pc [list nop {}]
			    my removeUse $source $b
			    my replaceUses [lindex $q 1] $replacement
			    dict unset udchain [lindex $q 1]
			    set changed 1
			    continue; # delete the quad
			}			
		    }

		    "extractScalar" {
			my debug-constfold {
			    puts "$b:$pc: examine $q"
			}

			# What type do I want?
			set want $quadcode::dataType::ARRAY

			# What type do I have?
			set source [lindex $argl 0]
			set have [typeOfLiteral $source]

			# Can I say sommething definitive?
			unset -nocomplain replacement
			if {[quadcode::dataType::isa $have $want]} {
			    # This is dead code, but we don't know it yet
			} elseif {![quadcode::dataType::mightbea $have $want]} {
			    set replacement [list literal $source]
			}
			if {[info exists replacement]} {
			    my debug-constfold {
				puts "$b:$pc: can replace [lindex $q 1] with\
                                      $replacement and remove the instruction"
			    }
			    lset bbcontent $b $pc [list nop {}]
			    my removeUse $source $b
			    my replaceUses [lindex $q 1] $replacement
			    dict unset udchain [lindex $q 1]
			    set changed 1
			    continue; # delete the quad
			}			
		    }

		    "ge" {
			lassign $argl x y
			set res [list literal [expr {$x >= $y}]]
			my debug-constfold {
			    puts "$b:$pc: $q"
			    puts "    replace [lindex $q 1] with $res"
................................................................................
			my debug-constfold {
			    puts "$b:$pc: $q"
			    puts "    replace [lindex $q 1] with $res"
			}
			my replaceUses [lindex $q 1] $res
			set changed 1
		    }

		    "instanceOf" {
			my debug-constfold {
			    puts "$b:$pc: examine $q"
			}

			# What type do I want?
			set want [lindex $q 0 1]

			# What type do I have?
			set source [lindex $argl 0]
			set have [typeOfLiteral $source]

			# Can I say sommething definitive?
			unset -nocomplain replacement
			if {[quadcode::dataType::isa $have $want]} {
			    set replacement {literal 1}
			} elseif {![quadcode::dataType::mightbea $have $want]} {
			    set replacement {literal 0}
			}
			if {[info exists replacement]} {
			    my debug-constfold {
				puts "$b:$pc: can replace [lindex $q 1] with\
                                      $replacement and remove the instruction"
			    }
			    lset bbcontent $b $pc [list nop {}]
			    my removeUse $source $b
			    my replaceUses [lindex $q 1] $replacement
			    dict unset udchain [lindex $q 1]
			    set changed 1
			    continue; # delete the quad
			}			
		    }

		    "le" {
			lassign $argl x y
			set res [list literal [expr {$x <= $y}]]
			my debug-constfold {
			    puts "$b:$pc: $q"
			    puts "    replace [lindex $q 1] with $res"
................................................................................
			my debug-constfold {
			    puts "$b:$pc: $q"
			    puts "    replace [lindex $q 1] with $res"
			}
			my replaceUses [lindex $q 1] $res
			set changed 1
		    }

		    "narrowToType" {
			my debug-constfold {
			    puts "$b:$pc: examine $q"
			}

			# What type do I want?
			set want [lindex $q 0 1]

			# What type do I have?
			set source [lindex $argl 0]
			set have [typeOfLiteral $source]

			# Can I say sommething definitive?
			unset -nocomplain replacement
			if {[quadcode::dataType::isa $have $want]} {
			    set replacement [lindex $q 0]
			} elseif {![quadcode::dataType::mightbea $have $want]} {
			    # this is dead code, but we don't know it yet
			}
			if {[info exists replacement]} {
			    my debug-constfold {
				puts "$b:$pc: can replace [lindex $q 1] with\
                                      $replacement and remove the instruction"
			    }
			    lset bbcontent $b $pc [list nop {}]
			    my removeUse $source $b
			    my replaceUses [lindex $q 1] $replacement
			    dict unset udchain [lindex $q 1]
			    set changed 1
			    continue; # delete the quad
			}			
		    }

		    "ne" {
			lassign $argl x y
			set res [list literal [expr {$x != $y}]]
			my debug-constfold {
			    puts "$b:$pc: $q"
			    puts "    replace [lindex $q 1] with $res"

Changes to quadcode/deadcode.tcl.

433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
...
450
451
452
453
454
455
456


457
458
459
460
461
462
463
...
530
531
532
533
534
535
536


537
538
539
540
541
542
543
...
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
    }
     
    # uselessphis --
    #
    #	Removes dead phi operations from the basic blocks
    #
    # Results:
    #	None.
    #
    # Side effects:
    #	Removes code and rewrites variable references.
    #
    # Precondition:
    #	Code should be in SSA form with blocks ordered in depth-first numbering
    #
................................................................................
    # output variable replaced with the input.

    method uselessphis {} {
	my debug-uselessphis {
	    puts "uselessphis:"
	    my dump-bb
	}



	# Add all basic blocks to the worklist, with the entry at the end

	set worklist {}
	for {set b [expr {[llength $bbcontent] - 1}]} {$b > 0} {incr b -1} {
	    lappend worklist $b
	}
................................................................................
		    my replaceUses $dest $source

		    # Get rid of the destination variable

		    dict unset udchain $dest
		    dict unset duchain $dest
		    dict unset types $dest



		    # delete the quad
		    
		} else {

		    my debug-uselessphis {
			puts "The phi at $b:$j is still useful"
................................................................................
		set block [lindex $bbcontent $b]
		lset bbcontent $b {}
		lset bbcontent $b \
		    [lreplace $block[set block {}] $j [expr {$i-1}]]
	    }
	}

	if 0 {
	my debug-uselessphis {
	    puts "after uselessphis:"
	    my dump-bb
	}
	}
	return
    }
 
    # unkillable --
    #
    #	Tests whether a quadcode instruction is unkillable
    #
    # Parameters:







|







 







>
>







 







>
>







 







<




|
|







433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
...
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
...
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
...
558
559
560
561
562
563
564

565
566
567
568
569
570
571
572
573
574
575
576
577
    }
     
    # uselessphis --
    #
    #	Removes dead phi operations from the basic blocks
    #
    # Results:
    #	Returns 1 if anything was removed, 0 otherwise
    #
    # Side effects:
    #	Removes code and rewrites variable references.
    #
    # Precondition:
    #	Code should be in SSA form with blocks ordered in depth-first numbering
    #
................................................................................
    # output variable replaced with the input.

    method uselessphis {} {
	my debug-uselessphis {
	    puts "uselessphis:"
	    my dump-bb
	}

	set changed 0

	# Add all basic blocks to the worklist, with the entry at the end

	set worklist {}
	for {set b [expr {[llength $bbcontent] - 1}]} {$b > 0} {incr b -1} {
	    lappend worklist $b
	}
................................................................................
		    my replaceUses $dest $source

		    # Get rid of the destination variable

		    dict unset udchain $dest
		    dict unset duchain $dest
		    dict unset types $dest

		    set changed 1

		    # delete the quad
		    
		} else {

		    my debug-uselessphis {
			puts "The phi at $b:$j is still useful"
................................................................................
		set block [lindex $bbcontent $b]
		lset bbcontent $b {}
		lset bbcontent $b \
		    [lreplace $block[set block {}] $j [expr {$i-1}]]
	    }
	}


	my debug-uselessphis {
	    puts "after uselessphis:"
	    my dump-bb
	}

	return $changed
    }
 
    # unkillable --
    #
    #	Tests whether a quadcode instruction is unkillable
    #
    # Parameters:

Changes to quadcode/narrow.tcl.

189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
...
219
220
221
222
223
224
225

226
227
228
229
230
231
232
233
234
235
236
...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# Results:
#	Returns 1 if the program was modified in a way that may have
#	spoilt data type analysis, 0 if the analysis is still stable.
#
# This procedure does not depend on having dominance information.
# It is expected to make wholesale changes to the flow graph, so it
# also does not attempt to maintain dominance information. Instead, it
# expects that deadcode, deadvars, uselessphis, bbidom, bblevel,
# udchain and duchain will be run after it is done to reconstruct the
# structure.

oo::define quadcode::transformer method cleanupNarrow {} {

    namespace upvar ::quadcode::dataType IMPURE IMPURE ARRAY ARRAY \
	NEXIST NEXIST STRING STRING FOREACH FOREACH DICTITER DICTITER
    set NONARRAY [expr {$STRING | $FOREACH | $DICTITER}]

................................................................................
    # types and existence of objects are known.

    # It is tempting to use a 'foreach' loop, but we want always to be
    # working on the current instance of each basic block, since
    # basic blocks remote from the current block will be rewritten as
    # instructions are removed.


    for {set b 0} {$b < [llength $bbcontent]} {incr b} {

	set changed 0

	set newpc 0
	for {set pc 0} {$pc < [llength [lindex $bbcontent $b]]} {incr pc} {
	    set q [lindex $bbcontent $b $pc]

	    switch -exact [lindex $q 0 0] {

		arrayExists {
................................................................................
			    [quadcode::dataType::isa $inputType $ARRAY]} {
			set replacer {literal 1}
		    }
		    if {[info exists replacer]} {
			my debug-cleanupNarrow {
			    puts "$b:$pc: Able to remove $q because $source is\
			          [quadcode::nameOfType $inputType]\
				  and hence result is $result"
			}
			lset bbcontent $b $pc {nop {}}
			my removeUse $source $b
			my replaceUses $result $replacer
			dict unset udchain $result
			set changed 1
			continue; # delete the quad







|
|
<







 







>


<
<







 







|







189
190
191
192
193
194
195
196
197

198
199
200
201
202
203
204
...
218
219
220
221
222
223
224
225
226
227


228
229
230
231
232
233
234
...
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# Results:
#	Returns 1 if the program was modified in a way that may have
#	spoilt data type analysis, 0 if the analysis is still stable.
#
# This procedure does not depend on having dominance information.
# It is expected to make wholesale changes to the flow graph, so it
# also does not attempt to maintain dominance information. Instead, it
# expects that deadcode, deadvars, uselessphis, bbidom, and bblevel
# will be run after it is done to reconstruct the structure.


oo::define quadcode::transformer method cleanupNarrow {} {

    namespace upvar ::quadcode::dataType IMPURE IMPURE ARRAY ARRAY \
	NEXIST NEXIST STRING STRING FOREACH FOREACH DICTITER DICTITER
    set NONARRAY [expr {$STRING | $FOREACH | $DICTITER}]

................................................................................
    # types and existence of objects are known.

    # It is tempting to use a 'foreach' loop, but we want always to be
    # working on the current instance of each basic block, since
    # basic blocks remote from the current block will be rewritten as
    # instructions are removed.

    set changed 0
    for {set b 0} {$b < [llength $bbcontent]} {incr b} {



	set newpc 0
	for {set pc 0} {$pc < [llength [lindex $bbcontent $b]]} {incr pc} {
	    set q [lindex $bbcontent $b $pc]

	    switch -exact [lindex $q 0 0] {

		arrayExists {
................................................................................
			    [quadcode::dataType::isa $inputType $ARRAY]} {
			set replacer {literal 1}
		    }
		    if {[info exists replacer]} {
			my debug-cleanupNarrow {
			    puts "$b:$pc: Able to remove $q because $source is\
			          [quadcode::nameOfType $inputType]\
				  and hence result is $replacer"
			}
			lset bbcontent $b $pc {nop {}}
			my removeUse $source $b
			my replaceUses $result $replacer
			dict unset udchain $result
			set changed 1
			continue; # delete the quad

Changes to quadcode/transformer.tcl.

578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594

595
596
597
598
599
600
601
602
603
604
605
606
607
608


609
610
611
612
613
614
615



616
617
618
619
620
621
622
623






624
625
626
627
628
629
630
631
632
633
634










635
636
637
638
639
640
641

642
643
644
645
646
647
648
649
650

651
652
653
654
655
656
657
658

659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
    #
    # We can now try partial redundancy elimination, which cannot change
    # data types but only moves around operations of known type.
    # It can leave a mess to clean up, with dead variables, useless phis,
    # and the possibility that it's given rise to empty basic blocks,
    # allowing deadbb/deadjump possibly to do further restructuring.

    set changed 0

    lappend timings cleanupNarrow \
	[lindex [time {set result [my cleanupNarrow]}] 0]
    if {$result} {
	set changed 1
    }
    my debug-audit {
	my audit-duchain cleanupNarrow
	my audit-phis cleanupNarrow

    }

    foreach pass {
	deadjump
	deadbb
	deadvars
	uselessphis
	deadjump
	deadbb
    } {
	lappend timings $pass [lindex [time [list my $pass]] 0]
	my debug-audit {
	    my audit-duchain $pass
	    my audit-phis $pass


	}
    }

    if {$changed} {
	my bbidom
	my bblevel
	return 1



    }
	
    foreach pass {
	copyprop
	constfold
	cleanupMoveFromCallFrame
	cleanupMoveToCallFrame
	cleanupCallFrameUse






    } {
	set passcmd [string map [list @pass $pass] {
	    set result [my @pass]
	}]
	lappend timings $pass [lindex [time $passcmd] 0]
	if {$result} {
	    set changed 1
	}
	my debug-audit {
	    my audit-duchain $pass
	    my audit-phis $pass










	}
    }

    # want partialredundancy on the blank line
    foreach pass {
	bbidom
	bblevel


	copyprop
	constfold
	deadjump
	deadbb
	deadvars
	uselessphis
	deadjump
	deadbb

	bbidom
	bblevel
    } {
	lappend timings $pass [lindex [time [list my $pass]] 0]
	my debug-audit {
	    my audit-duchain $pass
	    my audit-phis $pass
	}

    }

    my debug-timings {
	foreach {pass usec} $timings {
	    puts "$pass: $usec microseconds"
	}
    }

    return $changed

}
 
# quadcode::transformer method sourceFile --
#
#	Returns the source file that this module was compiled from
#







<
<
<
<
<
<
<
|
<
<
>


<
<
<
<
<
<
<
<
<
<
<
<
>
>
|
<
<
|
<
<
<
>
>
>
|
<
|
|
<
|
|
|
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>



|
|
|
|
>
|
<
<
<
<
<
<
<
<
>
|
|
<
<
<
<
<
|
>
|
<
<
<
<
<
<
<
|







578
579
580
581
582
583
584







585


586
587
588












589
590
591


592



593
594
595
596

597
598

599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637








638
639
640





641
642
643







644
645
646
647
648
649
650
651
    #
    # We can now try partial redundancy elimination, which cannot change
    # data types but only moves around operations of known type.
    # It can leave a mess to clean up, with dead variables, useless phis,
    # and the possibility that it's given rise to empty basic blocks,
    # allowing deadbb/deadjump possibly to do further restructuring.








    my debug-tidy {


	puts "tidy: [my full-name]"
    }













    set somethingChanged 0
    set changed 1



    while {$changed} {



	set changed 0
	my debug-tidy {
	    set debugLine {tidy:}
	}

	foreach pass {
	    copyprop

	    cleanupMoveFromCallFrame
	    cleanupMoveToCallFrame
	    cleanupCallFrameUse
	    cleanupNarrow
	    constfold
	    deadjump
	    deadbb
	    deadvars
	    uselessphis
	} {
	    set cmd [string map [list @pass $pass] {
		set result [my @pass]
	    }]
	    lappend timings $pass [lindex [time $cmd] 0]
	    if {$result} {
		set changed 1
	    }
	    my debug-audit {
		my audit-duchain $pass
		my audit-phis $pass
	    }
	    my debug-tidy {
		lappend debugLine $result
	    }
	}
	my debug-tidy {
	    puts $debugLine
	}
	if {$changed} {
	    set somethingChanged 1
	}
    }

    # If any of these changes actually changed anything, it may
    # have narrowed types, so we need to return for more interprocedural
    # type analysis
    if {$somethingChanged} {
	return 1
    }








	
    my bbidom
    my bblevel





	
    # TODO - Add partialredundancy!








    return $somethingChanged

}
 
# quadcode::transformer method sourceFile --
#
#	Returns the source file that this module was compiled from
#