Hi,
I've encountered a bug in CLA C compiler code generation.
For the C code:
float a, b, res[1];
__interrupt void testTask() {
float p, n;
p = a;
n = b;
res[0] = (p > n) ? p : -n;
}
the following assembly is generated:
MMOV32 MR0,@a ; [CPU_FPU] |6|
MMOV32 MR1,@b ; [CPU_FPU] |9|
MCMPF32 MR0,MR1 ; [CPU_FPU] |9|
MNEGF32 MR0,MR1,LEQ ; [CPU_FPU] |9|
MMOV32 @res,MR0 ; [CPU_FPU] |9|
The problem is, that instruction MNEGF32 copies variable b to res independently of the comparison result. Effectively, the generated assembly would look like this in C, which is wrong:
res[0] = (p > n) ? n : -n;
I tried to investigate this case further, and without res variable as an array, the generated code has branches, but is correct:
float a, b, res;
__interrupt void testTask()
{
float p, n;
p = a;
n = b;
res = (p > n) ? p : -n;
}
MMOV32 MR0,@a ; [CPU_FPU] |6|
MMOV32 MR1,@b ; [CPU_FPU] |9|
MCMPF32 MR0,MR1 ; [CPU_FPU] |9|
MNOP ; [CPU_FPU]
MNOP ; [CPU_FPU]
MNOP ; [CPU_FPU]
MBCNDD $C$L1,GT ; [CPU_FPU] |9|
MNOP ; [CPU_FPU]
MNOP ; [CPU_FPU]
MNOP ; [CPU_FPU]
; branchcc occurs ; [] |9|
MNEGF32 MR0,MR1 ; [CPU_FPU] |9|
$C$L1:
MMOV32 @res,MR0 ; [CPU_FPU] |9|
Although, in my application, I need to have the result in an array, so I found a workaround:
if (p > n) res[0] = p; else res[0] = -n;
For this C code, the assembly is the same as in the case above (without array).
PS. The command line invocation and compiler version:
cl2000 -c --cla_support=cla2 --abi=eabi -mt --keep_asm -O4 --opt_for_speed=5 test.cla
;*************************************************************** ;* TMS320x280xx Control Law Accelerator G3 C/C++ Codegen Unix v22.6.0.LTS * ;* Date/Time created: Tue Feb 14 12:50:54 2023 * ;*************************************************************** .compiler_opts --abi=eabi --cla_support=cla2 --float_support=softlib --hll_source=on --mem_model:code=flat --mem_model:data=large --object_format=elf --silicon_errata_fpu1_workaround=on --silicon_version=28 --symdebug:dwarf --symdebug:dwarf_version=4