-
Notifications
You must be signed in to change notification settings - Fork 14.6k
Description
int div(int a, int b, int c) {
return a / b / c;
}
compiled with clang --target=mipsel-freestanding -mcpu=mips3 -O3 -fomit-frame-pointer
div $zero, $4, $5
teq $5, $zero, 7
teq $6, $zero, 7
mflo $1
div $zero, $1, $6
jr $ra
mflo $2
The earlier mips ISAs require a minimum of 2 instructions between a mflo/mfhi and the next mul/div instruction. The output from clang V18.1.0 does not honor this. It is also more than happy to put the mflo into the delay slot for the return, which can also cause bugs.
The reason for this hazard is the div/mul instructions start an asynchronous operation. If an interrupt occurs the mfhi/mflo instruction might be flushed after the next div/mul has been started.
GCC correctly handles this in both cases.
I'm more than happy to work on this if anyone is willing to give me a few pointers. Forbidding mfhi/mflo in branch delay slots seems like a reasonable start, but I'm not sure how to handle the other case. I could add a pass to insert nops similar to the mulmul fix. I'm also not completely certain when the constraint goes away, but it's at least present in mips1-4.