Hardware udiv/sdiv for integer division/modulo

Asked by Tony Kao

Hi,

It appears that the current ARM GCC (I'm using 4.7 2013q1) does not emit udiv or sdiv instructions for division and modulo when compiling for architectures that support hardware division.

I compiled the following code with -march=armv7-m -mthumb

volatile int test;
int main() {
 test = test / 1000;
 return test;
}

which results in this assembly listing

int main() {
    8000: b480 push {r7}
    8002: af00 add r7, sp, #0
 test = test / 1000;
    8004: f240 4354 movw r3, #1108 ; 0x454
    8008: f2c0 0301 movt r3, #1
    800c: 681a ldr r2, [r3, #0]
    800e: f644 53d3 movw r3, #19923 ; 0x4dd3
    8012: f2c1 0362 movt r3, #4194 ; 0x1062
    8016: fb83 1302 smull r1, r3, r3, r2
    801a: ea4f 11a3 mov.w r1, r3, asr #6
    801e: ea4f 73e2 mov.w r3, r2, asr #31
    8022: 1aca subs r2, r1, r3
    8024: f240 4354 movw r3, #1108 ; 0x454
    8028: f2c0 0301 movt r3, #1
    802c: 601a str r2, [r3, #0]
 return test;
    802e: f240 4354 movw r3, #1108 ; 0x454
    8032: f2c0 0301 movt r3, #1
    8036: 681b ldr r3, [r3, #0]
}

As you can see, the compiler is using software emulation for division, even though ARMv7-M is specified. I have also tried to compile with -mcpu=cortex-m3 -mthumb, -mcpu=cortex-m3 -mthumb, and -march=armv7-r -mthumb, to no avail.

The same problem occurs when using the % operator, as well as directly calling the library division functions (the __aeabi_sidiv called appears to be a soft implementation).

Are udiv and sdiv currently being used by GCC? If so, is there some compiler switch I'm missing to get it to emit these instructions?

Thanks for the help.

Tony Kao

Question information

Language:
English Edit question
Status:
Solved
For:
GNU Arm Embedded Toolchain Edit question
Assignee:
No assignee Edit question
Solved by:
Joey Ye
Solved:
Last query:
Last reply:
Revision history for this message
chengbin (can-finner) said :
#1

Yes, there are switches in GCC to turn on fpu instructions for armv7-m.
For example, on cortex-m4 with fpu, you can specify below options when compiling/linking:

-mfpu=fpv4-sp-d16

There is another option "-mfloat-abi=hard" which determines passing float arguments using fpu registers or not.

Revision history for this message
chengbin (can-finner) said :
#2

Ahh, sorry that I mis understood your problem, please ignore the previous answer.

Revision history for this message
Best Joey Ye (jinyun-ye) said :
#3

Tony,

GCC does use sdiv/udiv for Cortex-M. The case you shared were actually optimized by strengthen reduction, which convert immediate division to multiple so as to run faster.

To have GCC actually emit sdiv/udiv, you can either
- compile with -Os, or
- replace 1000 with global variable
int div = 1000;
...
test = test / div;

Hopefully this is helpful.

- Joey

Revision history for this message
Tony Kao (c-tony) said :
#4

Thanks Joey Ye, that solved my question.