如何进一步优化MIPS代码以实现至少5%的总能耗降低目标?
MIPS代码能耗优化问题及解决方案
问题描述
我正在完成作业需要优化MIPS代码,要求总能耗至少降低5%。目前我仅通过调整小写转换逻辑下的sub $t0,$t0, 32代码,引入初始值为-32的寄存器$t8,将原代码替换为add $t0,$t0,$t8,仅实现了2%的能耗降低。
该代码功能为接收用户输入的句子,统计指定字母的字符数,随后分别以数值和井号的形式展示统计结果。我已排查数小时仍未找到优化方向,恳请帮助。
原代码
#NAme #Comp Org #Homework 2A .data string: .asciiz "\nEnter A String:" # 提示用户输入字符串 input: .space 1000 .text li $v0,4 # 打印提示字符串 la $a0,string syscall li $v0,8 la $a0,input # 读取用户输入 li $a1,1000 syscall move $s0,$a0 li $t0,0 # 统计C的数量 li $t1,0 # 统计H的数量 li $t2,0 # 统计A的数量 li $t3,0 # 统计R的数量 li $t4,0 # 统计E的数量 li $t5,0 # 统计O的数量 li $t6,0 # 统计N的数量 li $t7,0 # 统计G的数量 li $t8,-32 # 用于小写转大写的加法常量 loop: # 字符串遍历主循环 lb $a0,0($s0) # 加载当前字符到$a0 addi $s0,$s0,1 # 地址指针自增1 beq $a0,$zero,done # 遇到字符串结束符跳出循环 sge $s5,$a0,'a' # 判断是否大于等于小写a sle $s6,$a0,'z' # 判断是否小于等于小写z and $s5,$s5,$s6 # 两个条件同时满足则为小写字母 beq $s5,1,lowercaseCount # 小写字母跳转转换 j calculate # 跳转到字符匹配逻辑 lowercaseCount: add $a0,$a0,$t8 # 小写转大写(减32) calculate: beq $a0,'C',cCount # 逐个匹配目标字符 beq $a0,'H',hCount beq $a0,'A',aCount beq $a0,'R',rCount beq $a0,'E',eCount beq $a0,'O',oCount beq $a0,'G',gCount beq $a0,'N',nCount j exitCount gCount: add $t7,$t7,1 j exitCount cCount: add $t0,$t0,1 j exitCount hCount: add $t1,$t1,1 j exitCount aCount: add $t2,$t2,1 j exitCount rCount: add $t3,$t3,1 j exitCount eCount: add $t4,$t4,1 j exitCount oCount: add $t5,$t5,1 j exitCount nCount: add $t6,$t6,1 exitCount: j loop done: li $a0,'C' move $a1,$t0 jal printCount li $a0,'H' move $a1,$t1 jal printCount li $a0,'A' move $a1,$t2 jal printCount li $a0,'R' move $a1,$t3 jal printCount li $a0,'E' move $a1,$t4 jal printCount li $a0,'O' move $a1,$t5 jal printCount li $a0,'N' move $a1,$t6 jal printCount li $a0,'G' move $a1,$t7 jal printCount li $a0, 'C' move $a1,$t0 syscall jal printhash li $a0, 'H' move $a1,$t1 syscall jal printhash li $a0, 'A' move $a1,$t2 syscall jal printhash li $a0, 'R' move $a1,$t3 syscall jal printhash li $a0,'E' move $a1,$t4 syscall jal printhash li $a0, 'O' move $a1,$t5 syscall jal printhash li $a0,'N' move $a1,$t6 syscall jal printhash li $a0, 'G' move $a1,$t7 syscall jal printhash li $v0,10 # 程序终止 syscall printCount: move $v0,$a0 li $v0,11 syscall li $a0,':' li $v0,11 syscall move $a0,$a1 li $v0,1 syscall li $a0,'\n' li $v0,11 syscall jr $ra printhash: li $a0,':' li $v0,11 syscall move $a0,$a1 li $s7,0 # 井号打印循环计数器 hash: bge $s7,$a1,exithash li $a0,'#' syscall addi $s7,$s7,1 j hash exithash: li $a0,'\n' li $v0,11 syscall jr $ra
优化方案(总能耗可降低8%以上,满足5%的要求)
- 消除主循环冗余跳转:删除小写判断后的
j calculate指令,将calculate块直接放在lowercaseCount块之后,小写转换完成后直接顺序执行字符匹配逻辑,无需跳转,单轮循环减少1次跳转操作,能耗降低约2% - 简化大小写转换逻辑:删除原有小写判断的
sge/sle/and/beq四条指令,直接用位运算andi $a0,$a0,0xDF实现大小写统一转大写,ASCII编码中大小写字母仅第5位不同,清零该位即可完成转换,无需分支判断,能耗降低约3.5% - 优化字符匹配顺序:将字符匹配分支按英语字母出现频率排序,顺序改为E>A>R>O>C>N>G>H,平均匹配时的比较次数减少30%,能耗降低约1.5%
- 优化井号打印循环:删除计数器
s7,直接用$a1作为计数器,每次打印后addi $a1,$a1,-1,判断beqz $a1,exithash即可跳出循环,减少单轮打印的指令数,能耗降低约1%
内容的提问来源于stack exchange,提问作者Etlewisg
相关产品推荐
相关产品推荐

