TC-9 Samples

This section will not demonstrate the output of the option -S, --asm-display, since it outputs the long Tiger runtime. Once the registers are allocated (i.e., once -s, --asm-compute is executed) the option -I, --instr-display produces the code without the runtime. In short: we use -sI instead of -S to save space.

Allocating registers in the main function, when there is no register pressure is easy, as, in particular, there are no spills. A direct consequence is that many move’s are now useless, and have disappeared.

seven.tig
1 + 2 * 3
tc -sI seven.tig
$ tc -sI seven.tig
# == Final assembler ouput. == #
# Routine: _main
tc_main:
# Allocate frame
l0:
	li	$t1, 1
	li	$t0, 2
	mul	$t0, $t0, 3
	add	$t0, $t1, $t0
l1:
# Deallocate frame
	jr	$ra
$ echo $?
0
tc -S seven.tig > seven.s
$ tc -S seven.tig > seven.s

$ echo $?
0
nolimips -l nolimips -Ne seven.s
$ nolimips -l nolimips -Ne seven.s

$ echo $?
0

Another means to display the result of register allocation consists in reporting the mapping from temp s to actual registers:

tc -s --tempmap-display seven.tig
$ tc -s --tempmap-display seven.tig
/* Temporary map. */
fp -> $fp
rv -> $v0
t1 -> $t1
t2 -> $t0
t3 -> $t0
t4 -> $t0
t5 -> $s0
t6 -> $s1
t7 -> $s2
t8 -> $s3
t9 -> $s4
t10 -> $s5
t11 -> $s6
t12 -> $s7
t13 -> $ra
$ echo $?
0

Of course it is much better to see what is going on:

print-seven.tig
(print_int(1 + 2 * 3); print("\n"))
tc -sI print-seven.tig
$ tc -sI print-seven.tig
# == Final assembler ouput. == #
.data
l0:
	.word 1
	.asciiz "\n"
.text

# Routine: _main
tc_main:
	sw	$fp, -4 ($sp)
	move	$fp, $sp
	sub	$sp, $sp, 8
	sw	$ra, ($fp)
l1:
	li	$t0, 1
	li	$ra, 2
	mul	$ra, $ra, 3
	add	$a0, $t0, $ra
	jal	tc_print_int
	la	$a0, l0
	jal	tc_print
l2:
	lw	$ra, ($fp)
	move	$sp, $fp
	lw	$fp, -4 ($fp)
	jr	$ra
$ echo $?
0
tc -S print-seven.tig > print-seven.s
$ tc -S print-seven.tig > print-seven.s

$ echo $?
0
nolimips -l nolimips -Ne print-seven.s
$ nolimips -l nolimips -Ne print-seven.s
7
$ echo $?
0

To torture your compiler, you ought to use many temporaries. To be honest, ours is quite slow, it spends way too much time in register allocation.

print-many.tig
let
  var a00 := 00      var a55 := 55
  var a11 := 11      var a66 := 66
  var a22 := 22      var a77 := 77
  var a33 := 33      var a88 := 88
  var a44 := 44      var a99 := 99
in
  print_int(0
            +  a00 + a00 + a55 + a55
            +  a11 + a11 + a66 + a66
            +  a22 + a22 + a77 + a77
            +  a33 + a33 + a88 + a88
            +  a44 + a44 + a99 + a99);
  print("\n")
end
tc -eIs --tempmap-display -I --time-report print-many.tig
$ tc -eIs --tempmap-display -I --time-report print-many.tig
# == Final assembler ouput. == #
.data
l0:
	.word 1
	.asciiz "\n"
.text

# Routine: _main
tc_main:
# Allocate frame
	move	$x41, $ra
	move	$x33, $s0
	move	$x34, $s1
	move	$x35, $s2
	move	$x36, $s3
	move	$x37, $s4
	move	$x38, $s5
	move	$x39, $s6
	move	$x40, $s7
l1:
	li	$x0, 0
	li	$x1, 55
	li	$x2, 11
	li	$x3, 66
	li	$x4, 22
	li	$x5, 77
	li	$x6, 33
	li	$x7, 88
	li	$x8, 44
	li	$x9, 99
	li	$x11, 0
	add	$x12, $x11, $x0
	add	$x13, $x12, $x0
	add	$x14, $x13, $x1
	add	$x15, $x14, $x1
	add	$x16, $x15, $x2
	add	$x17, $x16, $x2
	add	$x18, $x17, $x3
	add	$x19, $x18, $x3
	add	$x20, $x19, $x4
	add	$x21, $x20, $x4
	add	$x22, $x21, $x5
	add	$x23, $x22, $x5
	add	$x24, $x23, $x6
	add	$x25, $x24, $x6
	add	$x26, $x25, $x7
	add	$x27, $x26, $x7
	add	$x28, $x27, $x8
	add	$x29, $x28, $x8
	add	$x30, $x29, $x9
	add	$x31, $x30, $x9
	move	$a0, $x31
	jal	tc_print_int
	la	$x32, l0
	move	$a0, $x32
	jal	tc_print
l2:
	move	$s0, $x33
	move	$s1, $x34
	move	$s2, $x35
	move	$s3, $x36
	move	$s4, $x37
	move	$s5, $x38
	move	$s6, $x39
	move	$s7, $x40
	move	$ra, $x41
# Deallocate frame
	jr	$ra
/* Temporary map. */
fp -> $fp
rv -> $v0
t0 -> $t9
t1 -> $t8
t2 -> $t7
t3 -> $t6
t4 -> $t5
t5 -> $t4
t6 -> $t3
t7 -> $t2
t8 -> $t1
t9 -> $t0
t11 -> $ra
t12 -> $ra
t13 -> $ra
t14 -> $ra
t15 -> $ra
t16 -> $ra
t17 -> $ra
t18 -> $ra
t19 -> $ra
t20 -> $ra
t21 -> $ra
t22 -> $ra
t23 -> $ra
t24 -> $ra
t25 -> $ra
t26 -> $ra
t27 -> $ra
t28 -> $ra
t29 -> $ra
t30 -> $ra
t31 -> $a0
t32 -> $a0
t33 -> $s0
t34 -> $s1
t35 -> $s2
t36 -> $s3
t37 -> $s4
t38 -> $s5
t39 -> $s6
t40 -> $s7
t110 -> $ra
t111 -> $ra

# == Final assembler ouput. == #
.data
l0:
	.word 1
	.asciiz "\n"
.text

# Routine: _main
tc_main:
	sw	$fp, -4 ($sp)
	move	$fp, $sp
	sub	$sp, $sp, 8
	sw	$ra, ($fp)
l1:
	li	$t9, 0
	li	$t8, 55
	li	$t7, 11
	li	$t6, 66
	li	$t5, 22
	li	$t4, 77
	li	$t3, 33
	li	$t2, 88
	li	$t1, 44
	li	$t0, 99
	li	$ra, 0
	add	$ra, $ra, $t9
	add	$ra, $ra, $t9
	add	$ra, $ra, $t8
	add	$ra, $ra, $t8
	add	$ra, $ra, $t7
	add	$ra, $ra, $t7
	add	$ra, $ra, $t6
	add	$ra, $ra, $t6
	add	$ra, $ra, $t5
	add	$ra, $ra, $t5
	add	$ra, $ra, $t4
	add	$ra, $ra, $t4
	add	$ra, $ra, $t3
	add	$ra, $ra, $t3
	add	$ra, $ra, $t2
	add	$ra, $ra, $t2
	add	$ra, $ra, $t1
	add	$ra, $ra, $t1
	add	$ra, $ra, $t0
	add	$a0, $ra, $t0
	jal	tc_print_int
	la	$a0, l0
	jal	tc_print
l2:
	lw	$ra, ($fp)
	move	$sp, $fp
	lw	$fp, -4 ($fp)
	jr	$ra
Execution times (seconds)
 1: parse                : 0.04   (   80%)   0      (    0%)   0.04   (   80%) 
 8: interference graph   : 0      (    0%)   0      (    0%)   0.01   (   20%) 
 9: asm-compute          : 0.01   (   20%)   0      (    0%)   0.01   (   20%) 
 rest                    : 0.05   (  100%)   0      (    0%)   0.05   (  100%) 

Cumulated times (seconds)
 1: parse                : 0.04   (   80%)   0      (    0%)   0.04   (   80%) 
 7: inst-display         : 0.01   (   20%)   0      (    0%)   0.01   (   20%) 
 8: interference graph   : 0      (    0%)   0      (    0%)   0.01   (   20%) 
 9: asm-compute          : 0.01   (   20%)   0      (    0%)   0.01   (   20%) 
 rest                    : 0.05   (  100%)   0      (    0%)   0.05   (  100%) 

 TOTAL (seconds)         : 0.05   user,      0      system,    0.05   wall
$ echo $?
0