Part Number: TMS320F28377D
Tool/software: TI C/C++ Compiler
I am trying to get the compiler to generate efficient code for finding the minimum of a 16-bit integer array:
int array_min_i16( const int *array, int num )
{
int min;
_nassert( num > 0 );
min = *array++;
while ( --num )
{
min = __min(min, *array++);
}
return min;
}
This produces the assembly (compiler options can be gleaned from the .compiler_opts tag)
;***************************************************************
;* TMS320C2000 C/C++ Codegen PC v17.9.0.STS *
;* Date/Time created: Tue Nov 14 16:56:02 2017 *
;***************************************************************
.compiler_opts --abi=coffabi --cla_support=cla1 --diag_wrap=off --float_support=fpu32 --hll_source=on --mem_model:code=flat --mem_model:data=large --object_format=coff --section_sizes=on --silicon_version=28 --symdebug:none --tmu_support=tmu0
.asg XAR2, FP
; C:\ti\ccsv6\tools\compiler\ti-cgt-c2000_17.9.0.STS\bin\opt2000.exe --gen_opt_info=1 C:\\Users\\XXXX\\AppData\\Local\\Temp\\{B44A09E1-C4D6-4F83-8D85-016C0A54BF9C} C:\\Users\\rist-1\\AppData\\Local\\Temp\\{1B9ACCCD-52A8-467C-A4F1-6323A6F25624} --opt_info_filename=temp.nfo
; C:\ti\ccsv6\tools\compiler\ti-cgt-c2000_17.9.0.STS\bin\ac2000.exe -@C:\\Users\\XXX\\AppData\\Local\\Temp\\{74F4C8A9-E322-45BA-9328-AB0817806698}
.sect ".TI.ramfunc:_array_min_i16"
.clink
.global _array_min_i16
;***************************************************************
;* FNAME: _array_min_i16 FR SIZE: 0 *
;* *
;* FUNCTION ENVIRONMENT *
;* *
;* FUNCTION PROPERTIES *
;* 0 Parameter, 0 Auto, 0 SOE *
;***************************************************************
_array_min_i16:
;*** 7 ----------------------- min = *array;
;*** 8 ----------------------- if ( !(--num) ) goto g7;
ADDB AL,#-1 ; [CPU_ALU] |8|
MOVZ AR6,AL ; [CPU_ALU] |8|
MOV AL,*+XAR4[0] ; [CPU_ALU] |7|
MOV AH,AR6 ; [CPU_ALU] |7|
BF $C$L3,EQ ; [CPU_ALU] |8|
; branchcc occurs ; [] |8|
;*** 10 ----------------------- d$1 = num&1;
;*** 7 ----------------------- ++array;
;*** 10 ----------------------- if ( num < 2 ) goto g5;
ANDB AH,#1 ; [CPU_ALU] |10|
MOVZ AR7,AH ; [CPU_ALU] |10|
ADDB XAR4,#1 ; [CPU_ALU] |7|
MOV AH,AR6 ; [CPU_FPU] |7|
CMPB AH,#2 ; [CPU_ALU] |10|
BF $C$L2,LT ; [CPU_ALU] |10|
; branchcc occurs ; [] |10|
;*** ----------------------- L$1 = (num>>1)-1;
;*** ----------------------- #pragma MUST_ITERATE(1, 16383, 1)
;*** ----------------------- // LOOP BELOW UNROLLED BY FACTOR(2)
;*** ----------------------- #pragma LOOP_FLAGS(4102u)
ASR AH,1 ; [CPU_ALU]
ADDB AH,#-1 ; [CPU_ALU]
MOVZ AR6,AH ; [CPU_ALU]
$C$L1:
;*** -----------------------g4:
;*** 10 ----------------------- min = __min(min, *array++);
;*** 10 ----------------------- min = __min(min, *array++);
;*** 8 ----------------------- if ( (--L$1) != (-1) ) goto g4;
MIN AL,*XAR4++ ; [CPU_ALU] |10|
MIN AL,*XAR4++ ; [CPU_ALU] |10|
BANZ $C$L1,AR6-- ; [CPU_ALU] |8|
; branchcc occurs ; [] |8|
$C$L2:
;*** -----------------------g5:
;*** ----------------------- if ( d$1 <= 0 ) goto g7;
MOV AH,AR7 ; [CPU_ALU]
BF $C$L3,LEQ ; [CPU_ALU]
; branchcc occurs ; []
; Peeled loop iterations for unrolled loop:
;*** 10 ----------------------- min = __min(min, *array);
;*** -----------------------g7:
;*** 13 ----------------------- return min;
MIN AL,*+XAR4[0] ; [CPU_ALU] |10|
$C$L3:
LRETR ; [CPU_ALU]
; return occurs ; []
I cannot get the compiler to produce the much more efficient
_array_min_i16:
SUBB ACC,#2
MOV AH,AL
MOV AL,*XAR4++
RPT AH
|| MIN AL,*XAR0++ ;
LRETR ;
How can I get the compiler to produce a more optimised version of the function? Is there a compiler switch I am missing (max uninterruptable sequence perhaps)?