Skip to content

[mips] mfhi/mflo hazard miscompilation #81291

@cmccord-dev

Description

@cmccord-dev
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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions