
62C6000软件优化线性汇编.ppt
45页第6章 C6000 软件优化第第2节节 线性汇编和汇编优化器线性汇编和汇编优化器l写线性汇编代码l使用汇编优化器l多周期循环的软件流水l汇编优化器选项和伪指令本节学习内容本节学习内容主要内容主要内容一、写线性汇编代码二、写线性汇编代码举例—点积三、调用汇编优化器四、多周期循环的软件流水五、加权矢量和(WVS)循环展开一、写线性汇编代码一、写线性汇编代码1、软件工具流程、软件工具流程2、线性汇编文件基本考虑事项、线性汇编文件基本考虑事项Ø线性汇编文件使用“.sa”扩展名Ø仅对指定的代码段进行优化,指定代码段外的代码被拷贝为输出“.asm”文件Ø线性汇编过程可以:l传递参数l返回结果l使用符号变量l不考虑流水线问题二、写线性汇编代码举例二、写线性汇编代码举例 —点积点积1、点积线性汇编、点积线性汇编线性汇编不需要指出和考虑:l功能单元l寄存器l延迟间隙2、确定优化代码段、确定优化代码段Dotp: .cproc zero sumloop: ldh *p_m++, m ldh *p_n++, n mpy m, n, prod add prod, sum, sum [count] sub count, 1, count [count] b loop .endproc.cproc/ .endproc:·确定要优化的代码段·必须成对使用·可作为C调用的函数· 在汇编代码中使用在汇编代码中使用.proc/ .endproc确定要优化的代码段确定要优化的代码段,它们也必须成对使用它们也必须成对使用3、使用符号变量、使用符号变量Dotp: .cproc .reg p_m, m, p_n, n, prod,sum,count zero sumloop: ldh *p_m++, m ldh *p_n++, n mpy m, n, prod add prod, sum, sum [count] sub count, 1, count [count] b loop .endproc.reg伪指令:·声明符号变量,变量由优化器选择与功能单元一致的寄存器·.reg在.(c)proc/ .endproc内有效·当变量为40/64bit时,变量使用寄存器对格式:如ahi:alo4、参数传递、参数传递Dotp: .cproc p_m, p_n, count .reg p_m, m, p_n, n, prod,sum,count zero sumloop: ldh *p_m++, m ldh *p_n++, n mpy m, n, prod add prod, sum, sum [count] sub count, 1, count [count] b loop .return sum .endproc·.cproc [variable1[,variable2,]]:给出输入参数·.return:给出返回结果·.return仅在.cproc/ .endproc内有效.proc [register1[,register2, ]]; 给出输入参数.reg p_m, mv register1, p_m ;建立输入寄存器 : ;与变量关系mv sum, register1.endproc [register1[,register2, ]];给出返回结果5、保护寄存器、保护寄存器Dotp: .cproc p_m, p_n, count .reg p_m, m, p_n, n, prod,sum,count .reserve a3 zero sumloop: ldh *p_m++, m ldh *p_n++, n mpy m, n, prod add prod, sum, sum [count] sub count, 1, count [count] b loop .return sum .endproc· .reserve指出需要保护的寄存器·当.cproc/ .endproc内的代码明显 使用了要保护的寄存器,优化器 也可能使用该寄存器,如:6、流水代码的最小循环次数、流水代码的最小循环次数l具有填充和排空l5次运算迭代,循环计数设置为3l最小循环次数:3循环测试7、计算最小循环次数、计算最小循环次数最小循环次数最小循环次数= =循环和排空的周期数循环和排空的周期数这个点积代码最小循环次数=?8、冗余循环、冗余循环非流水代码非流水代码执行较慢执行较慢运算迭代次数运算迭代次数>=最小循环次数最小循环次数流水代码流水代码执行较快执行较快9、消除冗余循环、消除冗余循环l关闭软件流水(-mu) 减小代码尺寸,但也减小吞吐量l指出运算迭代次数(.trip) 如果.trip≧最小循环次数,仅产生流水循环 如果.trip<最小循环次数,产生两种循环l不产生冗余循环(-ms) 如果没给出.trip,仅产生不流水循环 如果给出.trip,且.trip≧最小循环次数,仅产生流水循环10、指出运算迭代次数、指出运算迭代次数_Dotp: .cproc p_m, p_n, count .reg p_m, m, p_n, n, prod,sum,count zero sumloop: .trip 40 ldh *p_m++, m ldh *p_n++, n mpy m, n, prod add prod, sum, sum [count] sub count, 1, count [count] b loop .return sum .endproc指出运算迭代次数指出运算迭代次数11、点积的完整线性汇编、点积的完整线性汇编Dotp: .cproc p_m, p_n, count .reg p_m, m, p_n, n, prod,sum,count zero sumloop: .trip 40 ldh *p_m++, m ldh *p_n++, n mpy m, n, prod add prod, sum, sum [count] sub count, 1, count [count] b loop .return sum .endproc三、调用汇编优化器三、调用汇编优化器调用汇编优化器调用汇编优化器和汇编器和汇编器仅调用汇编器仅调用汇编器四、多周期循环的软件流水四、多周期循环的软件流水1、软件流水过程、软件流水过程1. 用C语言实现算法并验证2. 写C6x线性汇编代码3. 画相关图4. 分配功能单元和寄存器5. 建编排表6. 将编排表转换为C6x汇编代码第一步:第一步:C代码代码第二步:线性汇编代码第二步:线性汇编代码第三步:相关图第三步:相关图第四步:分配功能单元第四步:分配功能单元2周期循环周期循环2 2个周期个周期/ /每每次循环迭代次循环迭代迭代间隔:每迭代间隔:每次循环迭代占次循环迭代占用的周期数用的周期数多周期循环多周期循环第五步:建迭代间隔编排表(第五步:建迭代间隔编排表(1))第五步:建迭代间隔编排表(第五步:建迭代间隔编排表(2))第五步:建迭代间隔编排表(第五步:建迭代间隔编排表(3))第五步:建迭代间隔编排表(第五步:建迭代间隔编排表(4))第五步:建迭代间隔编排表(第五步:建迭代间隔编排表(5))第五步:建迭代间隔编排表(第五步:建迭代间隔编排表(6))展开加权矢量和代码展开加权矢量和代码展开加权矢量和:2个结果/每3个周期要点: 循环展开,充分利用资源.D单元数/每次循环结果/每次循环循环周期312623五、汇编优化器选项和伪指令l-on选项选项 l-mt选项和选项和. .no_mdep伪指令伪指令 【C程序的 restrict关键字】l.mdep伪指令伪指令 l.mptr伪指令伪指令 l.trip伪指令伪指令 【C程序的MUST_ITERATE pragma】-on选项l软件流水需要选择软件流水需要选择-o2或或-o3选项选项l-o = -o2-o = -o2l-o3-o3优化的工作:文件级优化优化的工作:文件级优化 1.删除未使用的所有函数删除未使用的所有函数 2.当函数的返回值没有用到时,简化函数返回的形式当函数的返回值没有用到时,简化函数返回的形式 3.内联小的函数内联小的函数 4.重重新新对对函函数数声声明明进进行行排排序序。
这这样样就就使使得得当当优优化化调调用用代代码时,被调用函数的属性是已知的码时,被调用函数的属性是已知的 5.当当所所用用调调用用都都传传递递一一个个相相同同的的参参数数时时,,把把这这个个参参数数直直接接放放到到函函数数体体中中去去,,不不再再通通过过寄寄存存器器/存存储储器器的的方方式式传传递递这个参数这个参数 6.识别文件级变量的特征识别文件级变量的特征 -o3 + -pm -o3 + -pm ::程序级优化程序级优化 如果一个函数中的一个特殊的变量的值总是一样的,编译器会用这个值直接代替该变量,直接进行值传递而不是参数传递 如果一个函数的返回值都没有被用到,编译器就会删除这个函数的返回值 如果一个函数没有被直接或间接地被调用,编译器就会删除这个函数-mt选项和.no_mdep伪指令l因为当你执行读取或存储指令时,汇编优化器并不知道你要访问的对象在哪里,所以汇编优化器就非常保守地认为存储器操作之间有相关性l汇编优化器会确保在下一次从reg1地址中读取数据之前往reg5地址中存储数据的工作已经完成如果要存的.reg5中的地址不是“reg1”要读取的下一个地址,将导致循环优化效果不好。
对于那些“reg5”是指向“reg1”的下一个地址的循环,这些是必要的l对于大部分的循环,并不是这样的,可以告诉汇编优化器更积极地安排存储器操作可以通过性汇编函数中使用“.no_mdep” (无存储器相关性)伪指令或者在编译线性汇编文件的时候用-mt选项实现 .mdep伪指令l假如你需要指明2个或更多的存储体的相关性,你可以使用.mdep伪指令用存储体相关性标号来注释你的代码,并且性汇编函数中加上.mdep伪指令l当使用了.no_mdep或-mt后,才需要使用.mdep伪指令l.mdep伪指令表明从LDW指令到STW指令中有存储体相关性这就意味着STW指令必须在LDW指令后执行mdep伪指令不表明在STW指令到LDW指令中存在存储体相关性要处理后一种情况,还需要一个.mdep伪指令 .mptr伪指令l.mptr伪指令给汇编优化器提供了怎样避免存储体(bank)冲突的内容汇编优化器会重新安排汇编代码中生成的存储体引用,以避免存储器的冲突,这些冲突是由伪指令.mptr指明的这意味着通过避免存储器的冲突,汇编优化器产生的代码的执行速度会更快,没有因为存储体冲突而出现流水线停顿流水线停顿(stall)的情况。
.mptr伪指令C64的 L1D的存储体结构:8×32bit流水线停顿流水线停顿同一周期对同一bank的两次读取引起流水线阻塞的情况LDW .D1 *A4++,A5 ; load 1, A4 address is in bank 0 || LDW .D2 *B4++,B5; load 2, B4 address is in bank 0 .mptr伪指令例子:点积 .mptr伪指令例子:点积(续).trip伪指令 llabel: .trip minimum_value[, maximum value[, factor]] lLoop: .trip 10 告诉汇编优化器循环迭代的次数至少至少10次lLoop:.trip 20,20 告诉汇编优化器循环迭代20次l Loop: .trip 8, 48, 8 告诉汇编优化器循环迭代的次数是8,16,24,32,40或48次l当你的循环需要中断时,最大值参数和因子(factor)参数都是非常有用的 。
